diff --git a/.clang-format b/.clang-format index bb609cbfb..8075a51e3 100644 --- a/.clang-format +++ b/.clang-format @@ -1,148 +1,116 @@ +# SPDX-License-Identifier: GPL-2.0 +# +# clang-format configuration file. Intended for clang-format >= 11. +# +# For more information, see: +# +# Documentation/dev-tools/clang-format.rst +# https://clang.llvm.org/docs/ClangFormat.html +# https://clang.llvm.org/docs/ClangFormatStyleOptions.html +# --- -Language: Cpp -# BasedOnStyle: Google -AccessModifierOffset: -1 +AccessModifierOffset: -4 AlignAfterOpenBracket: Align AlignConsecutiveAssignments: false AlignConsecutiveDeclarations: false AlignEscapedNewlines: Left -AlignOperands: true -AlignTrailingComments: true -AllowAllParametersOfDeclarationOnNextLine: true +AlignOperands: true +AlignTrailingComments: false +AllowAllParametersOfDeclarationOnNextLine: false AllowShortBlocksOnASingleLine: false AllowShortCaseLabelsOnASingleLine: false -AllowShortFunctionsOnASingleLine: All -AllowShortIfStatementsOnASingleLine: true -AllowShortLoopsOnASingleLine: true +AllowShortFunctionsOnASingleLine: None +AllowShortIfStatementsOnASingleLine: false +AllowShortLoopsOnASingleLine: false AlwaysBreakAfterDefinitionReturnType: None AlwaysBreakAfterReturnType: None -AlwaysBreakBeforeMultilineStrings: true -AlwaysBreakTemplateDeclarations: Yes +AlwaysBreakBeforeMultilineStrings: false +AlwaysBreakTemplateDeclarations: false BinPackArguments: true BinPackParameters: true -BraceWrapping: - AfterClass: false +BraceWrapping: + AfterClass: false AfterControlStatement: false - AfterEnum: false - AfterFunction: false - AfterNamespace: false + AfterEnum: false + AfterFunction: true + AfterNamespace: true AfterObjCDeclaration: false - AfterStruct: false - AfterUnion: false + AfterStruct: false + AfterUnion: false AfterExternBlock: false - BeforeCatch: false - BeforeElse: false - IndentBraces: false + BeforeCatch: false + BeforeElse: false + IndentBraces: false SplitEmptyFunction: true SplitEmptyRecord: true SplitEmptyNamespace: true BreakBeforeBinaryOperators: None -BreakBeforeBraces: Attach +BreakBeforeBraces: Custom BreakBeforeInheritanceComma: false -BreakInheritanceList: BeforeColon -BreakBeforeTernaryOperators: true +BreakBeforeTernaryOperators: false BreakConstructorInitializersBeforeComma: false -BreakConstructorInitializers: BeforeColon +BreakConstructorInitializers: BeforeComma BreakAfterJavaFieldAnnotations: false -BreakStringLiterals: true -ColumnLimit: 120 -CommentPragmas: '^ IWYU pragma:' +BreakStringLiterals: false +ColumnLimit: 80 +CommentPragmas: '^ IWYU pragma:' CompactNamespaces: false -ConstructorInitializerAllOnOneLineOrOnePerLine: true +ConstructorInitializerAllOnOneLineOrOnePerLine: false ConstructorInitializerIndentWidth: 4 ContinuationIndentWidth: 4 -Cpp11BracedListStyle: true -DerivePointerAlignment: true -DisableFormat: false +Cpp11BracedListStyle: false +DerivePointerAlignment: false +DisableFormat: false ExperimentalAutoDetectBinPacking: false -FixNamespaceComments: true -ForEachMacros: - - foreach - - Q_FOREACH - - BOOST_FOREACH -IncludeBlocks: Preserve -IncludeCategories: - - Regex: '^' - Priority: 2 - - Regex: '^<.*\.h>' - Priority: 1 - - Regex: '^<.*' - Priority: 2 - - Regex: '.*' - Priority: 3 -IncludeIsMainRegex: '([-_](test|unittest))?$' -IndentCaseLabels: true +FixNamespaceComments: false +IncludeBlocks: Preserve +IncludeCategories: + - Regex: '.*' + Priority: 1 +IncludeIsMainRegex: '(Test)?$' +IndentCaseLabels: false +IndentGotoLabels: false IndentPPDirectives: None -IndentWidth: 2 +IndentWidth: 4 IndentWrappedFunctionNames: false JavaScriptQuotes: Leave JavaScriptWrapImports: true KeepEmptyLinesAtTheStartOfBlocks: false MacroBlockBegin: '' -MacroBlockEnd: '' +MacroBlockEnd: '' MaxEmptyLinesToKeep: 1 NamespaceIndentation: None -ObjCBinPackProtocolList: Never -ObjCBlockIndentWidth: 2 -ObjCSpaceAfterProperty: false +ObjCBinPackProtocolList: Auto +ObjCBlockIndentWidth: 4 +ObjCSpaceAfterProperty: true ObjCSpaceBeforeProtocolList: true -PenaltyBreakAssignment: 2 -PenaltyBreakBeforeFirstCallParameter: 1 -PenaltyBreakComment: 300 -PenaltyBreakFirstLessLess: 120 -PenaltyBreakString: 1000 -PenaltyBreakTemplateDeclaration: 10 -PenaltyExcessCharacter: 1000000 -PenaltyReturnTypeOnItsOwnLine: 200 -PointerAlignment: Left -RawStringFormats: - - Language: Cpp - Delimiters: - - cc - - CC - - cpp - - Cpp - - CPP - - 'c++' - - 'C++' - CanonicalDelimiter: '' - BasedOnStyle: google - - Language: TextProto - Delimiters: - - pb - - PB - - proto - - PROTO - EnclosingFunctions: - - EqualsProto - - EquivToProto - - PARSE_PARTIAL_TEXT_PROTO - - PARSE_TEST_PROTO - - PARSE_TEXT_PROTO - - ParseTextOrDie - - ParseTextProtoOrDie - CanonicalDelimiter: '' - BasedOnStyle: google -ReflowComments: true -SortIncludes: true -SortUsingDeclarations: true + +# Taken from git's rules +PenaltyBreakAssignment: 10 +PenaltyBreakBeforeFirstCallParameter: 30 +PenaltyBreakComment: 10 +PenaltyBreakFirstLessLess: 0 +PenaltyBreakString: 10 +PenaltyExcessCharacter: 100 +PenaltyReturnTypeOnItsOwnLine: 60 + +PointerAlignment: Right +ReflowComments: false +SortIncludes: false +SortUsingDeclarations: false SpaceAfterCStyleCast: false SpaceAfterTemplateKeyword: true SpaceBeforeAssignmentOperators: true -SpaceBeforeCpp11BracedList: false SpaceBeforeCtorInitializerColon: true SpaceBeforeInheritanceColon: true -SpaceBeforeParens: ControlStatements SpaceBeforeRangeBasedForLoopColon: true SpaceInEmptyParentheses: false -SpacesBeforeTrailingComments: 2 -SpacesInAngles: false -SpacesInContainerLiterals: true +SpacesBeforeTrailingComments: 1 +SpacesInAngles: false +SpacesInContainerLiterals: false SpacesInCStyleCastParentheses: false SpacesInParentheses: false SpacesInSquareBrackets: false -Standard: Auto -TabWidth: 8 -UseTab: Never +TabWidth: 4 +UseTab: Always ... - diff --git a/.clang-tidy b/.clang-tidy new file mode 100644 index 000000000..fd8c681c4 --- /dev/null +++ b/.clang-tidy @@ -0,0 +1,147 @@ +# Generated from CLion Inspection settings +--- +Checks: '-*, +bugprone-argument-comment, +bugprone-assert-side-effect, +bugprone-bad-signal-to-kill-thread, +bugprone-branch-clone, +bugprone-copy-constructor-init, +bugprone-dangling-handle, +bugprone-dynamic-static-initializers, +bugprone-fold-init-type, +bugprone-forward-declaration-namespace, +bugprone-forwarding-reference-overload, +bugprone-inaccurate-erase, +bugprone-incorrect-roundings, +bugprone-integer-division, +bugprone-lambda-function-name, +bugprone-macro-parentheses, +bugprone-macro-repeated-side-effects, +bugprone-misplaced-operator-in-strlen-in-alloc, +bugprone-misplaced-pointer-arithmetic-in-alloc, +bugprone-misplaced-widening-cast, +bugprone-move-forwarding-reference, +bugprone-multiple-statement-macro, +bugprone-no-escape, +bugprone-parent-virtual-call, +bugprone-posix-return, +bugprone-reserved-identifier, +bugprone-sizeof-container, +bugprone-sizeof-expression, +bugprone-spuriously-wake-up-functions, +bugprone-string-constructor, +bugprone-string-integer-assignment, +bugprone-string-literal-with-embedded-nul, +bugprone-suspicious-enum-usage, +bugprone-suspicious-include, +bugprone-suspicious-memset-usage, +bugprone-suspicious-missing-comma, +bugprone-suspicious-semicolon, +bugprone-suspicious-string-compare, +bugprone-suspicious-memory-comparison, +bugprone-suspicious-realloc-usage, +bugprone-swapped-arguments, +bugprone-terminating-continue, +bugprone-throw-keyword-missing, +bugprone-too-small-loop-variable, +bugprone-undefined-memory-manipulation, +bugprone-undelegated-constructor, +bugprone-unhandled-self-assignment, +bugprone-unused-raii, +bugprone-unused-return-value, +bugprone-use-after-move, +bugprone-virtual-near-miss, +cert-dcl21-cpp, +cert-dcl58-cpp, +cert-err34-c, +cert-err52-cpp, +cert-err60-cpp, +cert-flp30-c, +cert-msc50-cpp, +cert-msc51-cpp, +cert-str34-c, +cppcoreguidelines-interfaces-global-init, +cppcoreguidelines-narrowing-conversions, +cppcoreguidelines-pro-type-member-init, +cppcoreguidelines-pro-type-static-cast-downcast, +cppcoreguidelines-slicing, +google-default-arguments, +google-explicit-constructor, +google-runtime-operator, +hicpp-exception-baseclass, +hicpp-multiway-paths-covered, +misc-misplaced-const, +misc-new-delete-overloads, +misc-no-recursion, +misc-non-copyable-objects, +misc-throw-by-value-catch-by-reference, +misc-unconventional-assign-operator, +misc-uniqueptr-reset-release, +modernize-avoid-bind, +modernize-concat-nested-namespaces, +modernize-deprecated-headers, +modernize-deprecated-ios-base-aliases, +modernize-loop-convert, +modernize-make-shared, +modernize-make-unique, +modernize-pass-by-value, +modernize-raw-string-literal, +modernize-redundant-void-arg, +modernize-replace-auto-ptr, +modernize-replace-disallow-copy-and-assign-macro, +modernize-replace-random-shuffle, +modernize-return-braced-init-list, +modernize-shrink-to-fit, +modernize-unary-static-assert, +modernize-use-auto, +modernize-use-bool-literals, +modernize-use-emplace, +modernize-use-equals-default, +modernize-use-equals-delete, +modernize-use-nodiscard, +modernize-use-noexcept, +modernize-use-nullptr, +modernize-use-override, +modernize-use-transparent-functors, +modernize-use-uncaught-exceptions, +mpi-buffer-deref, +mpi-type-mismatch, +openmp-use-default-none, +performance-faster-string-find, +performance-for-range-copy, +performance-implicit-conversion-in-loop, +performance-inefficient-algorithm, +performance-inefficient-string-concatenation, +performance-inefficient-vector-operation, +performance-move-const-arg, +performance-move-constructor-init, +performance-no-automatic-move, +performance-noexcept-move-constructor, +performance-trivially-destructible, +performance-type-promotion-in-math-fn, +performance-unnecessary-copy-initialization, +performance-unnecessary-value-param, +portability-simd-intrinsics, +readability-avoid-const-params-in-decls, +readability-const-return-type, +readability-container-size-empty, +readability-convert-member-functions-to-static, +readability-delete-null-pointer, +readability-deleted-default, +readability-inconsistent-declaration-parameter-name, +readability-make-member-function-const, +readability-misleading-indentation, +readability-misplaced-array-index, +readability-non-const-parameter, +readability-redundant-control-flow, +readability-redundant-declaration, +readability-redundant-function-ptr-dereference, +readability-redundant-smartptr-get, +readability-redundant-string-cstr, +readability-redundant-string-init, +readability-simplify-subscript-expr, +readability-static-accessed-through-instance, +readability-static-definition-in-anonymous-namespace, +readability-string-compare, +readability-uniqueptr-delete-release, +readability-use-anyofallof' \ No newline at end of file diff --git a/app/audio/audiomanager.cpp b/app/audio/audiomanager.cpp index 47b3e84a8..e97107780 100644 --- a/app/audio/audiomanager.cpp +++ b/app/audio/audiomanager.cpp @@ -28,290 +28,319 @@ #include "config/config.h" -namespace olive { +namespace olive +{ -AudioManager* AudioManager::instance_ = nullptr; +AudioManager *AudioManager::instance_ = nullptr; void AudioManager::CreateInstance() { - if (instance_ == nullptr) { - instance_ = new AudioManager(); - } + if (instance_ == nullptr) { + instance_ = new AudioManager(); + } } void AudioManager::DestroyInstance() { - delete instance_; - instance_ = nullptr; + delete instance_; + instance_ = nullptr; } AudioManager *AudioManager::instance() { - return instance_; + return instance_; } void AudioManager::SetOutputNotifyInterval(int n) { - output_buffer_->set_notify_interval(n); + output_buffer_->set_notify_interval(n); } -int OutputCallback(const void *input, void *output, unsigned long frameCount, const PaStreamCallbackTimeInfo *timeInfo, PaStreamCallbackFlags statusFlags, void *userData) +int OutputCallback(const void *input, void *output, unsigned long frameCount, + const PaStreamCallbackTimeInfo *timeInfo, + PaStreamCallbackFlags statusFlags, void *userData) { - PreviewAudioDevice *device = static_cast(userData); + PreviewAudioDevice *device = static_cast(userData); - qint64 max_read = frameCount * device->bytes_per_frame(); - qint64 read_count = device->read(reinterpret_cast(output), max_read); - if (read_count < max_read) { - memset(reinterpret_cast(output) + read_count, 0, max_read - read_count); - } + qint64 max_read = frameCount * device->bytes_per_frame(); + qint64 read_count = + device->read(reinterpret_cast(output), max_read); + if (read_count < max_read) { + memset(reinterpret_cast(output) + read_count, 0, + max_read - read_count); + } - return paContinue; + return paContinue; } -int InputCallback(const void *input, void *output, unsigned long frameCount, const PaStreamCallbackTimeInfo *timeInfo, PaStreamCallbackFlags statusFlags, void *userData) +int InputCallback(const void *input, void *output, unsigned long frameCount, + const PaStreamCallbackTimeInfo *timeInfo, + PaStreamCallbackFlags statusFlags, void *userData) { - FFmpegEncoder *f = static_cast(userData); + FFmpegEncoder *f = static_cast(userData); - AudioParams our_params = f->params().audio_params(); - our_params.set_format(f->params().audio_params().format().to_packed_equivalent()); + AudioParams our_params = f->params().audio_params(); + our_params.set_format( + f->params().audio_params().format().to_packed_equivalent()); - f->WriteAudioData(our_params, reinterpret_cast(&input), frameCount); + f->WriteAudioData(our_params, reinterpret_cast(&input), + frameCount); - return paContinue; + return paContinue; } -bool AudioManager::PushToOutput(const AudioParams ¶ms, const QByteArray &samples, QString *error) +bool AudioManager::PushToOutput(const AudioParams ¶ms, + const QByteArray &samples, QString *error) { - if (output_device_ == paNoDevice) { - if (error) *error = tr("No output device is set"); - return false; - } + if (output_device_ == paNoDevice) { + if (error) + *error = tr("No output device is set"); + return false; + } - if (output_params_ != params || output_stream_ == nullptr) { - output_params_ = params; + if (output_params_ != params || output_stream_ == nullptr) { + output_params_ = params; - CloseOutputStream(); + CloseOutputStream(); - PaStreamParameters p = GetPortAudioParams(params, output_device_); + PaStreamParameters p = GetPortAudioParams(params, output_device_); - PaError r = Pa_OpenStream(&output_stream_, nullptr, &p, output_params_.sample_rate(), paFramesPerBufferUnspecified, paNoFlag, OutputCallback, output_buffer_); - if (r != paNoError) { - // Unhandled error - //qCritical() << "Failed to open output stream:" << Pa_GetErrorText(r); - if (error) *error = Pa_GetErrorText(r); - return false; - } + PaError r = Pa_OpenStream(&output_stream_, nullptr, &p, + output_params_.sample_rate(), + paFramesPerBufferUnspecified, paNoFlag, + OutputCallback, output_buffer_); + if (r != paNoError) { + // Unhandled error + //qCritical() << "Failed to open output stream:" << Pa_GetErrorText(r); + if (error) + *error = Pa_GetErrorText(r); + return false; + } - output_buffer_->set_bytes_per_frame(output_params_.samples_to_bytes(1)); - } + output_buffer_->set_bytes_per_frame(output_params_.samples_to_bytes(1)); + } - output_buffer_->write(samples); + output_buffer_->write(samples); - if (!Pa_IsStreamActive(output_stream_)) { - Pa_StartStream(output_stream_); - } + if (!Pa_IsStreamActive(output_stream_)) { + Pa_StartStream(output_stream_); + } - return true; + return true; } void AudioManager::ClearBufferedOutput() { - output_buffer_->clear(); + output_buffer_->clear(); } PaSampleFormat AudioManager::GetPortAudioSampleFormat(SampleFormat fmt) { - switch (fmt) { - case SampleFormat::U8: - case SampleFormat::U8P: - return paUInt8; - case SampleFormat::S16: - case SampleFormat::S16P: - return paInt16; - case SampleFormat::S32: - case SampleFormat::S32P: - return paInt32; - case SampleFormat::F32: - case SampleFormat::F32P: - return paFloat32; - case SampleFormat::S64: - case SampleFormat::S64P: - case SampleFormat::F64: - case SampleFormat::F64P: - case SampleFormat::INVALID: - case SampleFormat::COUNT: - break; - } + switch (fmt) { + case SampleFormat::U8: + case SampleFormat::U8P: + return paUInt8; + case SampleFormat::S16: + case SampleFormat::S16P: + return paInt16; + case SampleFormat::S32: + case SampleFormat::S32P: + return paInt32; + case SampleFormat::F32: + case SampleFormat::F32P: + return paFloat32; + case SampleFormat::S64: + case SampleFormat::S64P: + case SampleFormat::F64: + case SampleFormat::F64P: + case SampleFormat::INVALID: + case SampleFormat::COUNT: + break; + } - return 0; + return 0; } void AudioManager::CloseOutputStream() { - if (output_stream_) { - if (Pa_IsStreamActive(output_stream_)) { - StopOutput(); - } - Pa_CloseStream(output_stream_); - output_stream_ = nullptr; - } + if (output_stream_) { + if (Pa_IsStreamActive(output_stream_)) { + StopOutput(); + } + Pa_CloseStream(output_stream_); + output_stream_ = nullptr; + } } void AudioManager::StopOutput() { - // Abort the stream so playback stops immediately - if (output_stream_) { - Pa_AbortStream(output_stream_); - ClearBufferedOutput(); - } + // Abort the stream so playback stops immediately + if (output_stream_) { + Pa_AbortStream(output_stream_); + ClearBufferedOutput(); + } } void AudioManager::SetOutputDevice(PaDeviceIndex device) { - if (device == paNoDevice) { - qInfo() << "No output device found"; - } else { - qInfo() << "Setting output audio device to" << Pa_GetDeviceInfo(device)->name; - } + if (device == paNoDevice) { + qInfo() << "No output device found"; + } else { + qInfo() << "Setting output audio device to" + << Pa_GetDeviceInfo(device)->name; + } - output_device_ = device; + output_device_ = device; - CloseOutputStream(); + CloseOutputStream(); } void AudioManager::SetInputDevice(PaDeviceIndex device) { - if (device == paNoDevice) { - qInfo() << "No input device found"; - } else { - qInfo() << "Setting input audio device to" << Pa_GetDeviceInfo(device)->name; - } + if (device == paNoDevice) { + qInfo() << "No input device found"; + } else { + qInfo() << "Setting input audio device to" + << Pa_GetDeviceInfo(device)->name; + } - input_device_ = device; + input_device_ = device; } void AudioManager::HardReset() { - CloseOutputStream(); - Pa_Terminate(); - Pa_Initialize(); + CloseOutputStream(); + Pa_Terminate(); + Pa_Initialize(); } -bool AudioManager::StartRecording(const EncodingParams ¶ms, QString *error_str) +bool AudioManager::StartRecording(const EncodingParams ¶ms, + QString *error_str) { - if (input_device_ == paNoDevice) { - return false; - } + if (input_device_ == paNoDevice) { + return false; + } - input_encoder_ = new FFmpegEncoder(params); - if (!input_encoder_->Open()) { - qCritical() << "Failed to open encoder for recording"; - return false; - } + input_encoder_ = new FFmpegEncoder(params); + if (!input_encoder_->Open()) { + qCritical() << "Failed to open encoder for recording"; + return false; + } - PaStreamParameters p = GetPortAudioParams(params.audio_params(), input_device_); + PaStreamParameters p = + GetPortAudioParams(params.audio_params(), input_device_); - PaError r = Pa_OpenStream(&input_stream_, &p, nullptr, params.audio_params().sample_rate(), paFramesPerBufferUnspecified, paNoFlag, InputCallback, input_encoder_); - if (r == paNoError) { - //const PaStreamInfo* info = Pa_GetStreamInfo(input_stream_); - r = Pa_StartStream(input_stream_); - if (r == paNoError) { - return true; - } - } + PaError r = Pa_OpenStream(&input_stream_, &p, nullptr, + params.audio_params().sample_rate(), + paFramesPerBufferUnspecified, paNoFlag, + InputCallback, input_encoder_); + if (r == paNoError) { + //const PaStreamInfo* info = Pa_GetStreamInfo(input_stream_); + r = Pa_StartStream(input_stream_); + if (r == paNoError) { + return true; + } + } - if (error_str) { - *error_str = Pa_GetErrorText(r); - } + if (error_str) { + *error_str = Pa_GetErrorText(r); + } - StopRecording(); - return false; + StopRecording(); + return false; } void AudioManager::StopRecording() { - if (input_stream_) { - if (Pa_IsStreamActive(input_stream_)) { - Pa_StopStream(input_stream_); - } - Pa_CloseStream(input_stream_); + if (input_stream_) { + if (Pa_IsStreamActive(input_stream_)) { + Pa_StopStream(input_stream_); + } + Pa_CloseStream(input_stream_); - input_stream_ = nullptr; - } + input_stream_ = nullptr; + } - if (input_encoder_) { - input_encoder_->Close(); - delete input_encoder_; - input_encoder_ = nullptr; - } + if (input_encoder_) { + input_encoder_->Close(); + delete input_encoder_; + input_encoder_ = nullptr; + } } PaDeviceIndex AudioManager::FindConfigDeviceByName(bool is_output_device) { - QString entry = is_output_device ? QStringLiteral("AudioOutput") : QStringLiteral("AudioInput"); + QString entry = is_output_device ? QStringLiteral("AudioOutput") : + QStringLiteral("AudioInput"); - return FindDeviceByName(OLIVE_CONFIG_STR(entry).toString(), is_output_device); + return FindDeviceByName(OLIVE_CONFIG_STR(entry).toString(), + is_output_device); } -PaDeviceIndex AudioManager::FindDeviceByName(const QString &s, bool is_output_device) +PaDeviceIndex AudioManager::FindDeviceByName(const QString &s, + bool is_output_device) { - if (!s.isEmpty()) { - for (PaDeviceIndex i=0, end=Pa_GetDeviceCount(); imaxOutputChannels) || (!is_output_device && device->maxInputChannels)) - && !s.compare(device->name)) { - return i; - } - } - } + if (((is_output_device && device->maxOutputChannels) || + (!is_output_device && device->maxInputChannels)) && + !s.compare(device->name)) { + return i; + } + } + } - return is_output_device ? Pa_GetDefaultOutputDevice() : Pa_GetDefaultInputDevice(); + return is_output_device ? Pa_GetDefaultOutputDevice() : + Pa_GetDefaultInputDevice(); } -PaStreamParameters AudioManager::GetPortAudioParams(const AudioParams ¶ms, PaDeviceIndex device) +PaStreamParameters AudioManager::GetPortAudioParams(const AudioParams ¶ms, + PaDeviceIndex device) { - PaStreamParameters p; + PaStreamParameters p; - p.channelCount = params.channel_count(); - p.device = device; - p.hostApiSpecificStreamInfo = nullptr; - p.sampleFormat = GetPortAudioSampleFormat(params.format()); - p.suggestedLatency = Pa_GetDeviceInfo(device)->defaultLowOutputLatency; + p.channelCount = params.channel_count(); + p.device = device; + p.hostApiSpecificStreamInfo = nullptr; + p.sampleFormat = GetPortAudioSampleFormat(params.format()); + p.suggestedLatency = Pa_GetDeviceInfo(device)->defaultLowOutputLatency; - return p; + return p; } -AudioManager::AudioManager() : - output_stream_(nullptr), - input_stream_(nullptr), - input_encoder_(nullptr) +AudioManager::AudioManager() + : output_stream_(nullptr) + , input_stream_(nullptr) + , input_encoder_(nullptr) { #ifdef PA_HAS_JACK - // PortAudio doesn't do a strcpy, so we need a const char that's readily accessible (i.e. not - // a QString converted to UTF-8) - PaJack_SetClientName("Olive"); + // PortAudio doesn't do a strcpy, so we need a const char that's readily accessible (i.e. not + // a QString converted to UTF-8) + PaJack_SetClientName("Olive"); #endif - Pa_Initialize(); + Pa_Initialize(); - // Get device from config - PaDeviceIndex output_device = FindConfigDeviceByName(true); - PaDeviceIndex input_device = FindConfigDeviceByName(false); + // Get device from config + PaDeviceIndex output_device = FindConfigDeviceByName(true); + PaDeviceIndex input_device = FindConfigDeviceByName(false); - SetOutputDevice(output_device); - SetInputDevice(input_device); + SetOutputDevice(output_device); + SetInputDevice(input_device); - output_buffer_ = new PreviewAudioDevice(this); - output_buffer_->open(PreviewAudioDevice::ReadWrite); - connect(output_buffer_, &PreviewAudioDevice::Notify, this, &AudioManager::OutputNotify); + output_buffer_ = new PreviewAudioDevice(this); + output_buffer_->open(PreviewAudioDevice::ReadWrite); + connect(output_buffer_, &PreviewAudioDevice::Notify, this, + &AudioManager::OutputNotify); } AudioManager::~AudioManager() { - CloseOutputStream(); + CloseOutputStream(); - Pa_Terminate(); + Pa_Terminate(); } } diff --git a/app/audio/audiomanager.h b/app/audio/audiomanager.h index 7f47d979c..b91fdcfa3 100644 --- a/app/audio/audiomanager.h +++ b/app/audio/audiomanager.h @@ -33,7 +33,8 @@ #include "render/audioplaybackcache.h" #include "render/previewaudiodevice.h" -namespace olive { +namespace olive +{ /** * @brief Audio input and output management class @@ -41,74 +42,76 @@ namespace olive { * Wraps around a QAudioOutput and AudioHybridDevice, connecting them together and exposing audio functionality to * the rest of the system. */ -class AudioManager : public QObject -{ - Q_OBJECT +class AudioManager : public QObject { + Q_OBJECT public: - static void CreateInstance(); - static void DestroyInstance(); + static void CreateInstance(); + static void DestroyInstance(); - static AudioManager* instance(); + static AudioManager *instance(); - void SetOutputNotifyInterval(int n); + void SetOutputNotifyInterval(int n); - bool PushToOutput(const AudioParams ¶ms, const QByteArray& samples, QString *error = nullptr); + bool PushToOutput(const AudioParams ¶ms, const QByteArray &samples, + QString *error = nullptr); - void ClearBufferedOutput(); + void ClearBufferedOutput(); - void StopOutput(); + void StopOutput(); - PaDeviceIndex GetOutputDevice() const - { - return output_device_; - } + PaDeviceIndex GetOutputDevice() const + { + return output_device_; + } - PaDeviceIndex GetInputDevice() const - { - return input_device_; - } + PaDeviceIndex GetInputDevice() const + { + return input_device_; + } - void SetOutputDevice(PaDeviceIndex device); + void SetOutputDevice(PaDeviceIndex device); - void SetInputDevice(PaDeviceIndex device); + void SetInputDevice(PaDeviceIndex device); - void HardReset(); + void HardReset(); - bool StartRecording(const EncodingParams ¶ms, QString *error_str = nullptr); + bool StartRecording(const EncodingParams ¶ms, + QString *error_str = nullptr); - void StopRecording(); + void StopRecording(); - static PaDeviceIndex FindConfigDeviceByName(bool is_output_device); - static PaDeviceIndex FindDeviceByName(const QString &s, bool is_output_device); + static PaDeviceIndex FindConfigDeviceByName(bool is_output_device); + static PaDeviceIndex FindDeviceByName(const QString &s, + bool is_output_device); - static PaStreamParameters GetPortAudioParams(const AudioParams &p, PaDeviceIndex device); + static PaStreamParameters GetPortAudioParams(const AudioParams &p, + PaDeviceIndex device); signals: - void OutputNotify(); + void OutputNotify(); - void OutputParamsChanged(); + void OutputParamsChanged(); private: - AudioManager(); + AudioManager(); - virtual ~AudioManager() override; + virtual ~AudioManager() override; - static PaSampleFormat GetPortAudioSampleFormat(SampleFormat fmt); + static PaSampleFormat GetPortAudioSampleFormat(SampleFormat fmt); - void CloseOutputStream(); + void CloseOutputStream(); - static AudioManager* instance_; + static AudioManager *instance_; - PaDeviceIndex output_device_; - PaStream *output_stream_; - AudioParams output_params_; - PreviewAudioDevice *output_buffer_; + PaDeviceIndex output_device_; + PaStream *output_stream_; + AudioParams output_params_; + PreviewAudioDevice *output_buffer_; - PaDeviceIndex input_device_; - PaStream *input_stream_; - - FFmpegEncoder *input_encoder_; + PaDeviceIndex input_device_; + PaStream *input_stream_; + FFmpegEncoder *input_encoder_; }; } diff --git a/app/audio/audioprocessor.cpp b/app/audio/audioprocessor.cpp index 59e69927e..7dee52dbe 100644 --- a/app/audio/audioprocessor.cpp +++ b/app/audio/audioprocessor.cpp @@ -29,279 +29,298 @@ extern "C" { #include "common/ffmpegutils.h" -namespace olive { +namespace olive +{ AudioProcessor::AudioProcessor() { - filter_graph_ = nullptr; - in_frame_ = nullptr; - out_frame_ = nullptr; + filter_graph_ = nullptr; + in_frame_ = nullptr; + out_frame_ = nullptr; } AudioProcessor::~AudioProcessor() { - Close(); + Close(); } -bool AudioProcessor::Open(const AudioParams &from, const AudioParams &to, double tempo) +bool AudioProcessor::Open(const AudioParams &from, const AudioParams &to, + double tempo) { - if (filter_graph_) { - qWarning() << "Tried to open a processor that was already open"; - return false; - } + if (filter_graph_) { + qWarning() << "Tried to open a processor that was already open"; + return false; + } - filter_graph_ = avfilter_graph_alloc(); - if (!filter_graph_) { - qCritical() << "Failed to allocate filter graph"; - return false; - } + filter_graph_ = avfilter_graph_alloc(); + if (!filter_graph_) { + qCritical() << "Failed to allocate filter graph"; + return false; + } - from_fmt_ = FFmpegUtils::GetFFmpegSampleFormat(from.format()); - to_fmt_ = FFmpegUtils::GetFFmpegSampleFormat(to.format()); + from_fmt_ = FFmpegUtils::GetFFmpegSampleFormat(from.format()); + to_fmt_ = FFmpegUtils::GetFFmpegSampleFormat(to.format()); - // Set up audio buffer args - char filter_args[200]; - snprintf(filter_args, 200, "time_base=%d/%d:sample_rate=%d:sample_fmt=%d:channel_layout=0x%" PRIx64, - 1, - from.sample_rate(), - from.sample_rate(), - from_fmt_, - from.channel_layout().u.mask); + // Set up audio buffer args + char filter_args[200]; + snprintf( + filter_args, 200, + "time_base=%d/%d:sample_rate=%d:sample_fmt=%d:channel_layout=0x%" PRIx64, + 1, from.sample_rate(), from.sample_rate(), from_fmt_, + from.channel_layout().u.mask); - int r; + int r; - // Create buffersrc (input) - r = avfilter_graph_create_filter(&buffersrc_ctx_, avfilter_get_by_name("abuffer"), "in", filter_args, nullptr, filter_graph_); - if (r < 0) { - qCritical() << "Failed to create buffersrc:" << r; - Close(); - return false; - } + // Create buffersrc (input) + r = avfilter_graph_create_filter(&buffersrc_ctx_, + avfilter_get_by_name("abuffer"), "in", + filter_args, nullptr, filter_graph_); + if (r < 0) { + qCritical() << "Failed to create buffersrc:" << r; + Close(); + return false; + } - // Store "previous" filter for linking - AVFilterContext *previous_filter = buffersrc_ctx_; + // Store "previous" filter for linking + AVFilterContext *previous_filter = buffersrc_ctx_; - // Create tempo - bool create_tempo; - if ((create_tempo = !qFuzzyCompare(tempo, 1.0))) { - // Create audio tempo filters: FFmpeg's atempo can only be set between 0.5 and 2.0. If the requested speed is outside - // those boundaries, we need to daisychain more than one together. - double base = (tempo > 1.0) ? 2.0 : 0.5; - double speed_log = log(tempo) / log(base); + // Create tempo + bool create_tempo; + if ((create_tempo = !qFuzzyCompare(tempo, 1.0))) { + // Create audio tempo filters: FFmpeg's atempo can only be set between 0.5 and 2.0. If the requested speed is outside + // those boundaries, we need to daisychain more than one together. + double base = (tempo > 1.0) ? 2.0 : 0.5; + double speed_log = log(tempo) / log(base); - // This is the number of how many 0.5 or 2.0 tempos we need to daisychain - int whole = std::floor(speed_log); + // This is the number of how many 0.5 or 2.0 tempos we need to daisychain + int whole = std::floor(speed_log); - // Set speed_log to the remainder - speed_log -= whole; + // Set speed_log to the remainder + speed_log -= whole; - for (int i=0;i<=whole;i++) { - double filter_tempo = (i == whole) ? std::pow(base, speed_log) : base; -/* + for (int i = 0; i <= whole; i++) { + double filter_tempo = (i == whole) ? std::pow(base, speed_log) : + base; + /* if (qFuzzyCompare(filter_tempo, 1.0)) { // This filter would do nothing continue; }*/ - previous_filter = CreateTempoFilter(filter_graph_, - previous_filter, - filter_tempo); + previous_filter = + CreateTempoFilter(filter_graph_, previous_filter, filter_tempo); - if (!previous_filter) { - qCritical() << "Failed to create audio tempo filter"; - Close(); - return false; - } - } - } + if (!previous_filter) { + qCritical() << "Failed to create audio tempo filter"; + Close(); + return false; + } + } + } - // Create conversion filter - auto ch1=from.channel_layout(); - auto ch2=to.channel_layout(); - if (from.sample_rate() != to.sample_rate() || av_channel_layout_compare(&ch1, &ch2) || from.format() != to.format() - || (to.format().is_planar() && create_tempo)) { // Tempo processor automatically converts to packed, - // so if the desired output is planar, it'll need - // to be converted - snprintf(filter_args, 200, "sample_fmts=%s:sample_rates=%d:channel_layouts=0x%" PRIx64, - av_get_sample_fmt_name(to_fmt_), - to.sample_rate(), - to.channel_layout().u.mask); + // Create conversion filter + auto ch1 = from.channel_layout(); + auto ch2 = to.channel_layout(); + if (from.sample_rate() != to.sample_rate() || + av_channel_layout_compare(&ch1, &ch2) || from.format() != to.format() || + (to.format().is_planar() && + create_tempo)) { // Tempo processor automatically converts to packed, + // so if the desired output is planar, it'll need + // to be converted + snprintf(filter_args, 200, + "sample_fmts=%s:sample_rates=%d:channel_layouts=0x%" PRIx64, + av_get_sample_fmt_name(to_fmt_), to.sample_rate(), + to.channel_layout().u.mask); - AVFilterContext *c; - r = avfilter_graph_create_filter(&c, avfilter_get_by_name("aformat"), "fmt", filter_args, nullptr, filter_graph_); - if (r < 0) { - qCritical() << "Failed to create format conversion filter:" << r << filter_args; - Close(); - return false; - } + AVFilterContext *c; + r = avfilter_graph_create_filter(&c, avfilter_get_by_name("aformat"), + "fmt", filter_args, nullptr, + filter_graph_); + if (r < 0) { + qCritical() << "Failed to create format conversion filter:" << r + << filter_args; + Close(); + return false; + } - r = avfilter_link(previous_filter, 0, c, 0); - if (r < 0) { - qCritical() << "Failed to link filters:" << r; - Close(); - return false; - } + r = avfilter_link(previous_filter, 0, c, 0); + if (r < 0) { + qCritical() << "Failed to link filters:" << r; + Close(); + return false; + } - previous_filter = c; - } + previous_filter = c; + } - // Create buffersink (output) - r = avfilter_graph_create_filter(&buffersink_ctx_, avfilter_get_by_name("abuffersink"), "out", nullptr, nullptr, filter_graph_); - if (r < 0) { - qCritical() << "Failed to create buffersink:" << r; - Close(); - return false; - } + // Create buffersink (output) + r = avfilter_graph_create_filter(&buffersink_ctx_, + avfilter_get_by_name("abuffersink"), "out", + nullptr, nullptr, filter_graph_); + if (r < 0) { + qCritical() << "Failed to create buffersink:" << r; + Close(); + return false; + } - r = avfilter_link(previous_filter, 0, buffersink_ctx_, 0); - if (r < 0) { - qCritical() << "Failed to link filters:" << r; - Close(); - return false; - } - char *dump = avfilter_graph_dump(filter_graph_, nullptr); - qDebug() << dump; - av_free(dump); - r = avfilter_graph_config(filter_graph_, nullptr); - if (r < 0) { - qCritical() << "Failed to configure graph:" << r; - Close(); - return false; - } + r = avfilter_link(previous_filter, 0, buffersink_ctx_, 0); + if (r < 0) { + qCritical() << "Failed to link filters:" << r; + Close(); + return false; + } + char *dump = avfilter_graph_dump(filter_graph_, nullptr); + qDebug() << dump; + av_free(dump); + r = avfilter_graph_config(filter_graph_, nullptr); + if (r < 0) { + qCritical() << "Failed to configure graph:" << r; + Close(); + return false; + } - in_frame_ = av_frame_alloc(); - if (in_frame_) { - in_frame_->sample_rate = from.sample_rate(); - in_frame_->format = from_fmt_; - in_frame_->ch_layout = from.channel_layout(); - in_frame_->pts = 0; - } else { - qCritical() << "Failed to allocate input frame"; - Close(); - return false; - } + in_frame_ = av_frame_alloc(); + if (in_frame_) { + in_frame_->sample_rate = from.sample_rate(); + in_frame_->format = from_fmt_; + in_frame_->ch_layout = from.channel_layout(); + in_frame_->pts = 0; + } else { + qCritical() << "Failed to allocate input frame"; + Close(); + return false; + } - out_frame_ = av_frame_alloc(); - if (!out_frame_) { - qCritical() << "Failed to allocate output frame"; - Close(); - return false; - } + out_frame_ = av_frame_alloc(); + if (!out_frame_) { + qCritical() << "Failed to allocate output frame"; + Close(); + return false; + } - from_ = from; - to_ = to; + from_ = from; + to_ = to; - return true; + return true; } void AudioProcessor::Close() { - if (filter_graph_) { - avfilter_graph_free(&filter_graph_); - filter_graph_ = nullptr; - buffersrc_ctx_ = nullptr; - buffersink_ctx_ = nullptr; - } + if (filter_graph_) { + avfilter_graph_free(&filter_graph_); + filter_graph_ = nullptr; + buffersrc_ctx_ = nullptr; + buffersink_ctx_ = nullptr; + } - if (in_frame_) { - av_frame_free(&in_frame_); - in_frame_ = nullptr; - } + if (in_frame_) { + av_frame_free(&in_frame_); + in_frame_ = nullptr; + } - if (out_frame_) { - av_frame_free(&out_frame_); - out_frame_ = nullptr; - } + if (out_frame_) { + av_frame_free(&out_frame_); + out_frame_ = nullptr; + } } -int AudioProcessor::Convert(float **in, int nb_in_samples, AudioProcessor::Buffer *output) +int AudioProcessor::Convert(float **in, int nb_in_samples, + AudioProcessor::Buffer *output) { - if (!IsOpen()) { - qCritical() << "Tried to convert on closed processor"; - return -1; - } + if (!IsOpen()) { + qCritical() << "Tried to convert on closed processor"; + return -1; + } - int r = 0; + int r = 0; - if (in && nb_in_samples) { - // Set frame parameters - in_frame_->nb_samples = nb_in_samples; - for (int i=0; idata[i] = reinterpret_cast(in[i]); - in_frame_->linesize[i] = from_.samples_to_bytes(nb_in_samples); - } + if (in && nb_in_samples) { + // Set frame parameters + in_frame_->nb_samples = nb_in_samples; + for (int i = 0; i < from_.channel_count(); i++) { + in_frame_->data[i] = reinterpret_cast(in[i]); + in_frame_->linesize[i] = from_.samples_to_bytes(nb_in_samples); + } - r = av_buffersrc_add_frame_flags(buffersrc_ctx_, in_frame_, AV_BUFFERSRC_FLAG_KEEP_REF); - if (r < 0) { - qCritical() << "Failed to add frame to buffersrc:" << r; - return r; - } - } + r = av_buffersrc_add_frame_flags(buffersrc_ctx_, in_frame_, + AV_BUFFERSRC_FLAG_KEEP_REF); + if (r < 0) { + qCritical() << "Failed to add frame to buffersrc:" << r; + return r; + } + } - if (output) { - int nb_channels = to_.channel_count(); + if (output) { + int nb_channels = to_.channel_count(); - if (to_.format().is_packed()) { - nb_channels = 1; - } + if (to_.format().is_packed()) { + nb_channels = 1; + } - AudioProcessor::Buffer &result = *output; - result.resize(nb_channels); + AudioProcessor::Buffer &result = *output; + result.resize(nb_channels); - int byte_offset = 0; + int byte_offset = 0; - while (true) { - av_frame_unref(out_frame_); - r = av_buffersink_get_frame(buffersink_ctx_, out_frame_); - if (r < 0) { - if (r == AVERROR(EAGAIN)) { - r = 0; - } else { - // Handle unexpected error - qCritical() << "Failed to pull from buffersink:" << r; - } - break; - } + while (true) { + av_frame_unref(out_frame_); + r = av_buffersink_get_frame(buffersink_ctx_, out_frame_); + if (r < 0) { + if (r == AVERROR(EAGAIN)) { + r = 0; + } else { + // Handle unexpected error + qCritical() << "Failed to pull from buffersink:" << r; + } + break; + } - int nb_bytes = out_frame_->nb_samples * to_.bytes_per_sample_per_channel(); - if (to_.format().is_packed()) { - nb_bytes *= to_.channel_count(); - } + int nb_bytes = + out_frame_->nb_samples * to_.bytes_per_sample_per_channel(); + if (to_.format().is_packed()) { + nb_bytes *= to_.channel_count(); + } - for (int i=0; idata[i], nb_bytes); - } - byte_offset += nb_bytes; - } - av_frame_unref(out_frame_); - } + for (int i = 0; i < nb_channels; i++) { + result[i].resize(byte_offset + nb_bytes); + memcpy(result[i].data() + byte_offset, out_frame_->data[i], + nb_bytes); + } + byte_offset += nb_bytes; + } + av_frame_unref(out_frame_); + } - return r; + return r; } void AudioProcessor::Flush() { - int r = av_buffersrc_add_frame_flags(buffersrc_ctx_, nullptr, AV_BUFFERSRC_FLAG_KEEP_REF); - if (r < 0) { - qCritical() << "Failed to flush:" << r; - } + int r = av_buffersrc_add_frame_flags(buffersrc_ctx_, nullptr, + AV_BUFFERSRC_FLAG_KEEP_REF); + if (r < 0) { + qCritical() << "Failed to flush:" << r; + } } -AVFilterContext *AudioProcessor::CreateTempoFilter(AVFilterGraph* graph, AVFilterContext* link, const double &tempo) +AVFilterContext *AudioProcessor::CreateTempoFilter(AVFilterGraph *graph, + AVFilterContext *link, + const double &tempo) { - // Set up tempo param, which is taken as a C string - char speed_param[20]; - snprintf(speed_param, 20, "%f", tempo); + // Set up tempo param, which is taken as a C string + char speed_param[20]; + snprintf(speed_param, 20, "%f", tempo); - AVFilterContext* tempo_ctx = nullptr; + AVFilterContext *tempo_ctx = nullptr; - if (avfilter_graph_create_filter(&tempo_ctx, avfilter_get_by_name("atempo"), "atempo", speed_param, nullptr, graph) >= 0 - && avfilter_link(link, 0, tempo_ctx, 0) == 0) { - return tempo_ctx; - } + if (avfilter_graph_create_filter(&tempo_ctx, avfilter_get_by_name("atempo"), + "atempo", speed_param, nullptr, + graph) >= 0 && + avfilter_link(link, 0, tempo_ctx, 0) == 0) { + return tempo_ctx; + } - return nullptr; + return nullptr; } } diff --git a/app/audio/audioprocessor.h b/app/audio/audioprocessor.h index a92e7627f..a5a9a34c7 100644 --- a/app/audio/audioprocessor.h +++ b/app/audio/audioprocessor.h @@ -31,52 +31,63 @@ extern "C" { #include "common/define.h" -namespace olive { +namespace olive +{ using namespace core; -class AudioProcessor -{ +class AudioProcessor { public: - AudioProcessor(); + AudioProcessor(); - ~AudioProcessor(); + ~AudioProcessor(); - DISABLE_COPY_MOVE(AudioProcessor) + DISABLE_COPY_MOVE(AudioProcessor) - bool Open(const AudioParams &from, const AudioParams &to, double tempo = 1.0); + bool Open(const AudioParams &from, const AudioParams &to, + double tempo = 1.0); - void Close(); + void Close(); - bool IsOpen() const { return filter_graph_; } + bool IsOpen() const + { + return filter_graph_; + } - using Buffer = QVector; - int Convert(float **in, int nb_in_samples, AudioProcessor::Buffer *output); + using Buffer = QVector; + int Convert(float **in, int nb_in_samples, AudioProcessor::Buffer *output); - void Flush(); + void Flush(); - const AudioParams &from() const { return from_; } - const AudioParams &to() const { return to_; } + const AudioParams &from() const + { + return from_; + } + const AudioParams &to() const + { + return to_; + } private: - static AVFilterContext* CreateTempoFilter(AVFilterGraph *graph, AVFilterContext *link, const double& tempo); + static AVFilterContext *CreateTempoFilter(AVFilterGraph *graph, + AVFilterContext *link, + const double &tempo); - AVFilterGraph* filter_graph_; + AVFilterGraph *filter_graph_; - AVFilterContext* buffersrc_ctx_; + AVFilterContext *buffersrc_ctx_; - AVFilterContext* buffersink_ctx_; + AVFilterContext *buffersink_ctx_; - AudioParams from_; - AVSampleFormat from_fmt_; + AudioParams from_; + AVSampleFormat from_fmt_; - AudioParams to_; - AVSampleFormat to_fmt_; + AudioParams to_; + AVSampleFormat to_fmt_; - AVFrame *in_frame_; - - AVFrame *out_frame_; + AVFrame *in_frame_; + AVFrame *out_frame_; }; } diff --git a/app/audio/audiovisualwaveform.cpp b/app/audio/audiovisualwaveform.cpp index 0558eb600..8782766c2 100644 --- a/app/audio/audiovisualwaveform.cpp +++ b/app/audio/audiovisualwaveform.cpp @@ -25,480 +25,536 @@ #include "config/config.h" -namespace olive { +namespace olive +{ const rational AudioVisualWaveform::kMinimumSampleRate = rational(1, 8); const rational AudioVisualWaveform::kMaximumSampleRate = 1024; -AudioVisualWaveform::AudioVisualWaveform() : - channels_(0) +AudioVisualWaveform::AudioVisualWaveform() + : channels_(0) { - for (rational i=kMinimumSampleRate; i<=kMaximumSampleRate; i*=2) { - mipmapped_data_.insert({i, Sample()}); - } + for (rational i = kMinimumSampleRate; i <= kMaximumSampleRate; i *= 2) { + mipmapped_data_.insert({ i, Sample() }); + } } -void AudioVisualWaveform::OverwriteSamplesFromBuffer(const SampleBuffer &samples, int sample_rate, const rational &start, double target_rate, Sample& data, size_t &start_index, size_t &samples_length) +void AudioVisualWaveform::OverwriteSamplesFromBuffer( + const SampleBuffer &samples, int sample_rate, const rational &start, + double target_rate, Sample &data, size_t &start_index, + size_t &samples_length) { - start_index = time_to_samples(start, target_rate); - samples_length = time_to_samples(static_cast(samples.sample_count()) / static_cast(sample_rate), target_rate); + start_index = time_to_samples(start, target_rate); + samples_length = + time_to_samples(static_cast(samples.sample_count()) / + static_cast(sample_rate), + target_rate); - size_t end_index = start_index + samples_length; - if (data.size() < end_index) { - data.resize(end_index); - } + size_t end_index = start_index + samples_length; + if (data.size() < end_index) { + data.resize(end_index); + } - double chunk_size = double(sample_rate) / double(target_rate); + double chunk_size = double(sample_rate) / double(target_rate); - for (size_t i=0; i(input_length / channels_) / input_sample_rate, output_rate); + size_t start_index = time_to_samples(start, output_rate); + size_t samples_length = time_to_samples( + static_cast(input_length / channels_) / input_sample_rate, + output_rate); - size_t end_index = start_index + samples_length; - if (output_data.size() < end_index) { - output_data.resize(end_index); - } + size_t end_index = start_index + samples_length; + if (output_data.size() < end_index) { + output_data.resize(end_index); + } - // We guarantee mipmaps are powers of two so integer division should be perfectly accurate here - size_t chunk_size = input_sample_rate / output_rate; + // We guarantee mipmaps are powers of two so integer division should be perfectly accurate here + size_t chunk_size = input_sample_rate / output_rate; - for (size_t i=0; i new_start) { - TrimIn(new_start - virtual_start_); - } + if (length_ == 0) { + virtual_start_ = new_start; + } else if (virtual_start_ > new_start) { + TrimIn(new_start - virtual_start_); + } } -void AudioVisualWaveform::OverwriteSamples(const SampleBuffer &samples, int sample_rate, const rational &start) +void AudioVisualWaveform::OverwriteSamples(const SampleBuffer &samples, + int sample_rate, + const rational &start) { - if (!channels_) { - qWarning() << "Failed to write samples - channel count is zero"; - return; - } + if (!channels_) { + qWarning() << "Failed to write samples - channel count is zero"; + return; + } - ValidateVirtualStart(start); + ValidateVirtualStart(start); - // Process the largest mipmap directly for the samples - auto current_mipmap = mipmapped_data_.rbegin(); - size_t input_start, input_length; - OverwriteSamplesFromBuffer(samples, sample_rate, start - virtual_start_, current_mipmap->first.toDouble(), current_mipmap->second, input_start, input_length); + // Process the largest mipmap directly for the samples + auto current_mipmap = mipmapped_data_.rbegin(); + size_t input_start, input_length; + OverwriteSamplesFromBuffer(samples, sample_rate, start - virtual_start_, + current_mipmap->first.toDouble(), + current_mipmap->second, input_start, + input_length); - while (true) { - // For each smaller mipmap, we just process from the mipmap before it, making each one - // exponentially faster to create - auto previous_mipmap = current_mipmap; - current_mipmap++; - if (current_mipmap == mipmapped_data_.rend()) { - break; - } + while (true) { + // For each smaller mipmap, we just process from the mipmap before it, making each one + // exponentially faster to create + auto previous_mipmap = current_mipmap; + current_mipmap++; + if (current_mipmap == mipmapped_data_.rend()) { + break; + } - OverwriteSamplesFromMipmap(previous_mipmap->second, previous_mipmap->first.toDouble(), - input_start, input_length, start - virtual_start_, current_mipmap->first.toDouble(), - current_mipmap->second); - } + OverwriteSamplesFromMipmap( + previous_mipmap->second, previous_mipmap->first.toDouble(), + input_start, input_length, start - virtual_start_, + current_mipmap->first.toDouble(), current_mipmap->second); + } - rational sample_length(samples.sample_count(), sample_rate); - length_ = qMax(length_, start + sample_length); + rational sample_length(samples.sample_count(), sample_rate); + length_ = qMax(length_, start + sample_length); } -void AudioVisualWaveform::OverwriteSums(const AudioVisualWaveform &sums, const rational &dest, const rational& offset, const rational& length) +void AudioVisualWaveform::OverwriteSums(const AudioVisualWaveform &sums, + const rational &dest, + const rational &offset, + const rational &length) { - ValidateVirtualStart(dest); + ValidateVirtualStart(dest); - for (auto it=mipmapped_data_.begin(); it!=mipmapped_data_.end(); it++) { - rational rate = it->first; + for (auto it = mipmapped_data_.begin(); it != mipmapped_data_.end(); it++) { + rational rate = it->first; - Sample& our_arr = it->second; - const Sample& their_arr = sums.mipmapped_data_.at(rate); + Sample &our_arr = it->second; + const Sample &their_arr = sums.mipmapped_data_.at(rate); - double rate_dbl = rate.toDouble(); + double rate_dbl = rate.toDouble(); - // Get our destination sample - size_t our_start_index = time_to_samples(dest - virtual_start_, rate_dbl); + // Get our destination sample + size_t our_start_index = + time_to_samples(dest - virtual_start_, rate_dbl); - // Get our source sample - size_t their_start_index = time_to_samples(offset, rate_dbl); - if (their_start_index >= their_arr.size()) { - continue; - } + // Get our source sample + size_t their_start_index = time_to_samples(offset, rate_dbl); + if (their_start_index >= their_arr.size()) { + continue; + } - // Determine how much we're copying - size_t copy_len = their_arr.size() - their_start_index; - if (!length.isNull()) { - copy_len = qMin(copy_len, time_to_samples(length, rate_dbl)); - if (copy_len == 0) { - continue; - } - } + // Determine how much we're copying + size_t copy_len = their_arr.size() - their_start_index; + if (!length.isNull()) { + copy_len = qMin(copy_len, time_to_samples(length, rate_dbl)); + if (copy_len == 0) { + continue; + } + } - // Determine end index of our array - size_t end_index = our_start_index + copy_len; - if (our_arr.size() < end_index) { - our_arr.resize(end_index); - } + // Determine end index of our array + size_t end_index = our_start_index + copy_len; + if (our_arr.size() < end_index) { + our_arr.resize(end_index); + } - memcpy(reinterpret_cast(our_arr.data()) + our_start_index * sizeof(SamplePerChannel), - reinterpret_cast(their_arr.data()) + their_start_index * sizeof(SamplePerChannel), - copy_len * sizeof(SamplePerChannel)); - } + memcpy(reinterpret_cast(our_arr.data()) + + our_start_index * sizeof(SamplePerChannel), + reinterpret_cast(their_arr.data()) + + their_start_index * sizeof(SamplePerChannel), + copy_len * sizeof(SamplePerChannel)); + } - length_ = qMax(length_, dest + ((length.isNull()) ? sums.length() - offset : length)); + length_ = qMax(length_, dest + ((length.isNull()) ? sums.length() - offset : + length)); } -void AudioVisualWaveform::OverwriteSilence(const rational &start, const rational &length) +void AudioVisualWaveform::OverwriteSilence(const rational &start, + const rational &length) { - ValidateVirtualStart(start); + ValidateVirtualStart(start); - for (auto it=mipmapped_data_.begin(); it!=mipmapped_data_.end(); it++) { - rational rate = it->first; + for (auto it = mipmapped_data_.begin(); it != mipmapped_data_.end(); it++) { + rational rate = it->first; - Sample& our_arr = it->second; + Sample &our_arr = it->second; - double rate_dbl = rate.toDouble(); + double rate_dbl = rate.toDouble(); - // Get our destination sample - size_t our_start_index = time_to_samples(start - virtual_start_, rate_dbl); - size_t our_length_index = time_to_samples(length, rate_dbl); - size_t our_end_index = our_start_index + our_length_index; + // Get our destination sample + size_t our_start_index = + time_to_samples(start - virtual_start_, rate_dbl); + size_t our_length_index = time_to_samples(length, rate_dbl); + size_t our_end_index = our_start_index + our_length_index; - if (our_arr.size() < our_end_index) { - our_arr.resize(our_end_index); - } + if (our_arr.size() < our_end_index) { + our_arr.resize(our_end_index); + } - memset(reinterpret_cast(our_arr.data()) + our_start_index * sizeof(SamplePerChannel), 0, our_length_index * sizeof(SamplePerChannel)); - } + memset(reinterpret_cast(our_arr.data()) + + our_start_index * sizeof(SamplePerChannel), + 0, our_length_index * sizeof(SamplePerChannel)); + } - length_ = qMax(length_, start + length); + length_ = qMax(length_, start + length); } void AudioVisualWaveform::TrimIn(rational length) { - if (length == 0) { - return; - } + if (length == 0) { + return; + } - virtual_start_ += length; + virtual_start_ += length; - bool negative = (length < 0); - if (negative) { - length = -length; - } + bool negative = (length < 0); + if (negative) { + length = -length; + } - for (auto it=mipmapped_data_.begin(); it!=mipmapped_data_.end(); it++) { - rational rate = it->first; - double rate_dbl = rate.toDouble(); - Sample& data = it->second; + for (auto it = mipmapped_data_.begin(); it != mipmapped_data_.end(); it++) { + rational rate = it->first; + double rate_dbl = rate.toDouble(); + Sample &data = it->second; - size_t chop_length = time_to_samples(length, rate_dbl); - if (chop_length == 0) { - continue; - } + size_t chop_length = time_to_samples(length, rate_dbl); + if (chop_length == 0) { + continue; + } - if (!negative) { - data = Sample(data.begin() + chop_length, data.end()); - } else { - data.insert(data.begin(), chop_length, SamplePerChannel()); - } - } + if (!negative) { + data = Sample(data.begin() + chop_length, data.end()); + } else { + data.insert(data.begin(), chop_length, SamplePerChannel()); + } + } - length_ = qMax(rational(0), length_ - length); + length_ = qMax(rational(0), length_ - length); } AudioVisualWaveform AudioVisualWaveform::Mid(const rational &offset) const { - AudioVisualWaveform mid = *this; + AudioVisualWaveform mid = *this; - mid.TrimIn(offset - virtual_start_); + mid.TrimIn(offset - virtual_start_); - return mid; + return mid; } -AudioVisualWaveform AudioVisualWaveform::Mid(const rational &offset, const rational &length) const +AudioVisualWaveform AudioVisualWaveform::Mid(const rational &offset, + const rational &length) const { - AudioVisualWaveform mid = *this; + AudioVisualWaveform mid = *this; - mid.TrimRange(offset - virtual_start_, length); + mid.TrimRange(offset - virtual_start_, length); - return mid; + return mid; } void AudioVisualWaveform::Resize(const rational &length) { - if (length_ == length) { - return; - } + if (length_ == length) { + return; + } - for (auto it=mipmapped_data_.begin(); it!=mipmapped_data_.end(); it++) { - rational rate = it->first; - double rate_dbl = rate.toDouble(); - Sample& data = it->second; + for (auto it = mipmapped_data_.begin(); it != mipmapped_data_.end(); it++) { + rational rate = it->first; + double rate_dbl = rate.toDouble(); + Sample &data = it->second; - size_t chop_length = time_to_samples(length, rate_dbl); + size_t chop_length = time_to_samples(length, rate_dbl); - data.resize(chop_length); - } + data.resize(chop_length); + } - length_ = length; + length_ = length; } void AudioVisualWaveform::TrimRange(const rational &in, const rational &length) { - TrimIn(in); - Resize(length); + TrimIn(in); + Resize(length); } -AudioVisualWaveform::Sample AudioVisualWaveform::GetSummaryFromTime(const rational &start, const rational &length) const +AudioVisualWaveform::Sample +AudioVisualWaveform::GetSummaryFromTime(const rational &start, + const rational &length) const { - // Find mipmap that requires - auto using_mipmap = GetMipmapForScale(length.flipped().toDouble()); + // Find mipmap that requires + auto using_mipmap = GetMipmapForScale(length.flipped().toDouble()); - double rate_dbl = using_mipmap->first.toDouble(); + double rate_dbl = using_mipmap->first.toDouble(); - size_t start_sample = time_to_samples(start - virtual_start_, rate_dbl); - size_t sample_length = time_to_samples(length, rate_dbl); + size_t start_sample = time_to_samples(start - virtual_start_, rate_dbl); + size_t sample_length = time_to_samples(length, rate_dbl); - const Sample &mipmap_data = using_mipmap->second; + const Sample &mipmap_data = using_mipmap->second; - // Determine if the array actually has this sample - sample_length = qMin(sample_length, mipmap_data.size() - start_sample); + // Determine if the array actually has this sample + sample_length = qMin(sample_length, mipmap_data.size() - start_sample); - // Based on the above `min`, if sample length <= 0, that means start_sample >= the size of the - // array and nothing can be returned. - if (sample_length > 0) { - return ReSumSamples(&mipmap_data.data()[start_sample], sample_length, channels_); - } + // Based on the above `min`, if sample length <= 0, that means start_sample >= the size of the + // array and nothing can be returned. + if (sample_length > 0) { + return ReSumSamples(&mipmap_data.data()[start_sample], sample_length, + channels_); + } - // Return null samples - return AudioVisualWaveform::Sample(channel_count(), {0, 0}); + // Return null samples + return AudioVisualWaveform::Sample(channel_count(), { 0, 0 }); } -void ExpandMinMaxChannel(const float *a, size_t length, float &min_val, float &max_val) +void ExpandMinMaxChannel(const float *a, size_t length, float &min_val, + float &max_val) { #if defined(Q_PROCESSOR_X86) || defined(Q_PROCESSOR_ARM) - // SSE optimized + // SSE optimized - // load the first 4 elements of 'a' into min and max (they are 4 * 32 = 128 bits) - __m128 max = _mm_loadu_ps(a); - __m128 min = _mm_loadu_ps(a); + // load the first 4 elements of 'a' into min and max (they are 4 * 32 = 128 bits) + __m128 max = _mm_loadu_ps(a); + __m128 min = _mm_loadu_ps(a); - // loop over 'a' and compare current elements with min and max 4 by 4. - // we need to make sure we don't read out of boundaries should 'a' length be not mod. 4 - for(size_t i = 4; i < length-4; i+=4) { - __m128 cur = _mm_loadu_ps(a + i); - max = _mm_max_ps(max, cur); - min = _mm_min_ps(min, cur); - } - // so we read the last 4 (or less) elements in a safe manner. - __m128 cur = _mm_loadu_ps(a + length - 4); - max = _mm_max_ps(max, cur); - min = _mm_min_ps(min, cur); - // this potentially overlaps up to the last 3 elements but it's not an issue. + // loop over 'a' and compare current elements with min and max 4 by 4. + // we need to make sure we don't read out of boundaries should 'a' length be not mod. 4 + for (size_t i = 4; i < length - 4; i += 4) { + __m128 cur = _mm_loadu_ps(a + i); + max = _mm_max_ps(max, cur); + min = _mm_min_ps(min, cur); + } + // so we read the last 4 (or less) elements in a safe manner. + __m128 cur = _mm_loadu_ps(a + length - 4); + max = _mm_max_ps(max, cur); + min = _mm_min_ps(min, cur); + // this potentially overlaps up to the last 3 elements but it's not an issue. - // min and max will contain 4 min and max. To get the absolute min and max - // we need to compare the 4 values over themselves by shuffling each time. - for (size_t i = 0; i < 3; i++) { - max = _mm_max_ps(max, _mm_shuffle_ps(max, max, 0x93)); - min = _mm_min_ps(min, _mm_shuffle_ps(min, min, 0x93)); - } - // now min and max contain 4 identical items each representing min and max value respectively. + // min and max will contain 4 min and max. To get the absolute min and max + // we need to compare the 4 values over themselves by shuffling each time. + for (size_t i = 0; i < 3; i++) { + max = _mm_max_ps(max, _mm_shuffle_ps(max, max, 0x93)); + min = _mm_min_ps(min, _mm_shuffle_ps(min, min, 0x93)); + } + // now min and max contain 4 identical items each representing min and max value respectively. - // and we store the first one into a float variable. - _mm_store_ss(&max_val, max); - _mm_store_ss(&min_val, min); - // I bet you don't find annotated low level code very often. + // and we store the first one into a float variable. + _mm_store_ss(&max_val, max); + _mm_store_ss(&min_val, min); + // I bet you don't find annotated low level code very often. #else - // Standard unoptimized function - for (size_t i=0; idata(i%channels)[i]); - // } + // for reference: this approximation is n x faster (and less accurate) for a n-tracks clip + // for (size_t i=start_index; idata(i%channels)[i]); + // } - return summed_samples; + return summed_samples; } -AudioVisualWaveform::Sample AudioVisualWaveform::ReSumSamples(const SamplePerChannel* samples, - size_t nb_samples, - int nb_channels) +AudioVisualWaveform::Sample +AudioVisualWaveform::ReSumSamples(const SamplePerChannel *samples, + size_t nb_samples, int nb_channels) { - AudioVisualWaveform::Sample summed_samples(nb_channels); + AudioVisualWaveform::Sample summed_samples(nb_channels); - for (size_t i=0;i summed_samples[j].max) { - summed_samples[j].max = sample.max; - } - } - } + if (sample.max > summed_samples[j].max) { + summed_samples[j].max = sample.max; + } + } + } - return summed_samples; + return summed_samples; } -template -inline int round_away_from_zero(T t) +template inline int round_away_from_zero(T t) { - return (t < 0) ? std::floor(t) : std::ceil(t); + return (t < 0) ? std::floor(t) : std::ceil(t); } -void AudioVisualWaveform::DrawSample(QPainter *painter, const Sample& sample, int x, int y, int height, bool rectified) +void AudioVisualWaveform::DrawSample(QPainter *painter, const Sample &sample, + int x, int y, int height, bool rectified) { - if (sample.empty()) { - return; - } + if (sample.empty()) { + return; + } - int channel_height = height / sample.size(); - int channel_half_height = channel_height / 2; + int channel_height = height / sample.size(); + int channel_half_height = channel_height / 2; - for (size_t i=0;idrawLine(x, - channel_bottom - diff, - x, - channel_bottom); - } else { - int channel_mid = y + channel_height * i + channel_half_height; + painter->drawLine(x, channel_bottom - diff, x, channel_bottom); + } else { + int channel_mid = y + channel_height * i + channel_half_height; - // We subtract the sample so that positive Y values go up on the screen rather than down, - // which is how waveforms are usually rendered - painter->drawLine(x, - channel_mid - round_away_from_zero(min * static_cast(channel_half_height)), - x, - channel_mid - round_away_from_zero(max * static_cast(channel_half_height))); - } - } + // We subtract the sample so that positive Y values go up on the screen rather than down, + // which is how waveforms are usually rendered + painter->drawLine( + x, + channel_mid - + round_away_from_zero( + min * static_cast(channel_half_height)), + x, + channel_mid - + round_away_from_zero( + max * static_cast(channel_half_height))); + } + } } -void AudioVisualWaveform::DrawWaveform(QPainter *painter, const QRect& rect, const double& scale, const AudioVisualWaveform &samples, const rational& start_time) +void AudioVisualWaveform::DrawWaveform(QPainter *painter, const QRect &rect, + const double &scale, + const AudioVisualWaveform &samples, + const rational &start_time) { - if (samples.mipmapped_data_.empty()) { - return; - } + if (samples.mipmapped_data_.empty()) { + return; + } - auto using_mipmap = samples.GetMipmapForScale(scale); + auto using_mipmap = samples.GetMipmapForScale(scale); - rational rate = using_mipmap->first; - double rate_dbl = rate.toDouble(); - const Sample& arr = using_mipmap->second; + rational rate = using_mipmap->first; + double rate_dbl = rate.toDouble(); + const Sample &arr = using_mipmap->second; - size_t start_sample_index = samples.time_to_samples(start_time - samples.virtual_start_, rate_dbl); + size_t start_sample_index = + samples.time_to_samples(start_time - samples.virtual_start_, rate_dbl); - if (start_sample_index >= arr.size()) { - return; - } + if (start_sample_index >= arr.size()) { + return; + } - size_t next_sample_index = start_sample_index; - size_t sample_index; + size_t next_sample_index = start_sample_index; + size_t sample_index; - Sample summary; - size_t summary_index = -1; + Sample summary; + size_t summary_index = -1; - const QRect& viewport = painter->viewport(); - QPoint top_left = painter->transform().map(viewport.topLeft()); + const QRect &viewport = painter->viewport(); + QPoint top_left = painter->transform().map(viewport.topLeft()); - size_t start = qMax(rect.x(), -top_left.x()); - size_t end = qMin(rect.right(), -top_left.x() + viewport.width()); + size_t start = qMax(rect.x(), -top_left.x()); + size_t end = qMin(rect.right(), -top_left.x() + viewport.width()); - bool rectified = OLIVE_CONFIG("RectifiedWaveforms").toBool(); + bool rectified = OLIVE_CONFIG("RectifiedWaveforms").toBool(); - for (size_t i=start;i(i - rect.x() + 1) / scale) * samples.channel_count())); + next_sample_index = std::min( + arr.size(), + size_t(start_sample_index + + std::floor(rate_dbl * static_cast(i - rect.x() + 1) / + scale) * + samples.channel_count())); - if (summary_index != sample_index) { - summary = AudioVisualWaveform::ReSumSamples(&arr.at(sample_index), - qMax(size_t(samples.channel_count()), next_sample_index - sample_index), - samples.channel_count()); - summary_index = sample_index; - } + if (summary_index != sample_index) { + summary = AudioVisualWaveform::ReSumSamples( + &arr.at(sample_index), + qMax(size_t(samples.channel_count()), + next_sample_index - sample_index), + samples.channel_count()); + summary_index = sample_index; + } - DrawSample(painter, summary, i, rect.y(), rect.height(), rectified); - } + DrawSample(painter, summary, i, rect.y(), rect.height(), rectified); + } } -size_t AudioVisualWaveform::time_to_samples(const rational &time, double sample_rate) const +size_t AudioVisualWaveform::time_to_samples(const rational &time, + double sample_rate) const { - return time_to_samples(time.toDouble(), sample_rate); + return time_to_samples(time.toDouble(), sample_rate); } -size_t AudioVisualWaveform::time_to_samples(const double &time, double sample_rate) const +size_t AudioVisualWaveform::time_to_samples(const double &time, + double sample_rate) const { - return std::floor(time * sample_rate) * channels_; + return std::floor(time * sample_rate) * channels_; } -std::map::const_iterator AudioVisualWaveform::GetMipmapForScale(double scale) const +std::map::const_iterator +AudioVisualWaveform::GetMipmapForScale(double scale) const { - // Find largest mipmap for this scale (or the largest if we don't find one sufficient) - for (auto it=mipmapped_data_.cbegin(); it!=mipmapped_data_.cend(); it++) { - if (it->first.toDouble() >= scale) { - return it; - } - } + // Find largest mipmap for this scale (or the largest if we don't find one sufficient) + for (auto it = mipmapped_data_.cbegin(); it != mipmapped_data_.cend(); + it++) { + if (it->first.toDouble() >= scale) { + return it; + } + } - // We don't have a mipmap large enough for this scale, so just return the largest we have - return std::prev(mipmapped_data_.cend()); + // We don't have a mipmap large enough for this scale, so just return the largest we have + return std::prev(mipmapped_data_.cend()); } } diff --git a/app/audio/audiovisualwaveform.h b/app/audio/audiovisualwaveform.h index a75e46a2d..ca5947f3d 100644 --- a/app/audio/audiovisualwaveform.h +++ b/app/audio/audiovisualwaveform.h @@ -25,7 +25,8 @@ #include #include -namespace olive { +namespace olive +{ using namespace core; @@ -37,38 +38,39 @@ using namespace core; */ class AudioVisualWaveform { public: - AudioVisualWaveform(); + AudioVisualWaveform(); - struct SamplePerChannel { - float min; - float max; - }; + struct SamplePerChannel { + float min; + float max; + }; - using Sample = std::vector; + using Sample = std::vector; - int channel_count() const - { - return channels_; - } + int channel_count() const + { + return channels_; + } - void set_channel_count(int channels) - { - channels_ = channels; - } + void set_channel_count(int channels) + { + channels_ = channels; + } - const rational& length() const - { - return length_; - } + const rational &length() const + { + return length_; + } - /** + /** * @brief Writes samples into the visual waveform buffer * * Starting at `start`, writes samples over anything in the buffer, expanding it if necessary. */ - void OverwriteSamples(const SampleBuffer &samples, int sample_rate, const rational& start = 0); + void OverwriteSamples(const SampleBuffer &samples, int sample_rate, + const rational &start = 0); - /** + /** * @brief Replaces sums at a certain range in this visual waveform * * @param sums @@ -87,53 +89,70 @@ public: * * Maximum length of `sums` to overwrite with. */ - void OverwriteSums(const AudioVisualWaveform& sums, const rational& dest, const rational& offset = 0, const rational &length = 0); + void OverwriteSums(const AudioVisualWaveform &sums, const rational &dest, + const rational &offset = 0, const rational &length = 0); - void OverwriteSilence(const rational &start, const rational &length); + void OverwriteSilence(const rational &start, const rational &length); - void TrimIn(rational length); + void TrimIn(rational length); - AudioVisualWaveform Mid(const rational &offset) const; - AudioVisualWaveform Mid(const rational &offset, const rational &length) const; + AudioVisualWaveform Mid(const rational &offset) const; + AudioVisualWaveform Mid(const rational &offset, + const rational &length) const; - void Resize(const rational &length); + void Resize(const rational &length); - void TrimRange(const rational &in, const rational &length); + void TrimRange(const rational &in, const rational &length); - Sample GetSummaryFromTime(const rational& start, const rational& length) const; + Sample GetSummaryFromTime(const rational &start, + const rational &length) const; - static Sample SumSamples(const SampleBuffer &samples, size_t start_index, size_t length); + static Sample SumSamples(const SampleBuffer &samples, size_t start_index, + size_t length); - static Sample ReSumSamples(const SamplePerChannel *samples, size_t nb_samples, int nb_channels); + static Sample ReSumSamples(const SamplePerChannel *samples, + size_t nb_samples, int nb_channels); - static void DrawSample(QPainter* painter, const Sample &sample, int x, int y, int height, bool rectified); + static void DrawSample(QPainter *painter, const Sample &sample, int x, + int y, int height, bool rectified); - static void DrawWaveform(QPainter* painter, const QRect &rect, const double &scale, const AudioVisualWaveform& samples, const rational &start_time); + static void DrawWaveform(QPainter *painter, const QRect &rect, + const double &scale, + const AudioVisualWaveform &samples, + const rational &start_time); - // Must be a power of 2 - static const rational kMinimumSampleRate; - static const rational kMaximumSampleRate; + // Must be a power of 2 + static const rational kMinimumSampleRate; + static const rational kMaximumSampleRate; private: - void OverwriteSamplesFromBuffer(const SampleBuffer &samples, int sample_rate, const rational& start, double target_rate, Sample &data, size_t &start_index, size_t &samples_length); + void OverwriteSamplesFromBuffer(const SampleBuffer &samples, + int sample_rate, const rational &start, + double target_rate, Sample &data, + size_t &start_index, + size_t &samples_length); - void OverwriteSamplesFromMipmap(const Sample& input, double input_sample_rate, size_t &input_start, size_t &input_length, const rational& start, double output_rate, Sample &output_data); + void OverwriteSamplesFromMipmap(const Sample &input, + double input_sample_rate, + size_t &input_start, size_t &input_length, + const rational &start, double output_rate, + Sample &output_data); - size_t time_to_samples(const rational& time, double sample_rate) const; - size_t time_to_samples(const double& time, double sample_rate) const; + size_t time_to_samples(const rational &time, double sample_rate) const; + size_t time_to_samples(const double &time, double sample_rate) const; - std::map::const_iterator GetMipmapForScale(double scale) const; + std::map::const_iterator + GetMipmapForScale(double scale) const; - void ValidateVirtualStart(const rational &new_start); + void ValidateVirtualStart(const rational &new_start); - rational virtual_start_; + rational virtual_start_; - int channels_; + int channels_; - std::map mipmapped_data_; - - rational length_; + std::map mipmapped_data_; + rational length_; }; } diff --git a/app/cli/cliexport/cliexportmanager.cpp b/app/cli/cliexport/cliexportmanager.cpp index 9f9670996..8fe2412d2 100644 --- a/app/cli/cliexport/cliexportmanager.cpp +++ b/app/cli/cliexport/cliexportmanager.cpp @@ -20,11 +20,11 @@ #include "cliexportmanager.h" -namespace olive { +namespace olive +{ CLIExportManager::CLIExportManager() { - } } diff --git a/app/cli/cliexport/cliexportmanager.h b/app/cli/cliexport/cliexportmanager.h index 867bc5493..952b6c791 100644 --- a/app/cli/cliexport/cliexportmanager.h +++ b/app/cli/cliexport/cliexportmanager.h @@ -23,12 +23,12 @@ #include "task/export/export.h" -namespace olive { - -class CLIExportManager : public QObject +namespace olive { + +class CLIExportManager : public QObject { public: - CLIExportManager(); + CLIExportManager(); }; } diff --git a/app/cli/cliprogress/cliprogressdialog.cpp b/app/cli/cliprogress/cliprogressdialog.cpp index 17203e386..3ac2a4346 100644 --- a/app/cli/cliprogress/cliprogressdialog.cpp +++ b/app/cli/cliprogress/cliprogressdialog.cpp @@ -22,85 +22,87 @@ #include -namespace olive { - -CLIProgressDialog::CLIProgressDialog(const QString& title, QObject *parent) : - QObject(parent), - title_(title), - progress_(-1), - drawn_(false) +namespace olive { - SetProgress(0); + +CLIProgressDialog::CLIProgressDialog(const QString &title, QObject *parent) + : QObject(parent) + , title_(title) + , progress_(-1) + , drawn_(false) +{ + SetProgress(0); } void CLIProgressDialog::Update() { - if (drawn_) { - // We've been here before, do a carriage return back to the start of the terminal line - std::cout << "\r"; - } else { - drawn_ = true; - } + if (drawn_) { + // We've been here before, do a carriage return back to the start of the terminal line + std::cout << "\r"; + } else { + drawn_ = true; + } - // FIXME: Get real column count - int columns = 80; + // FIXME: Get real column count + int columns = 80; - int title_columns = columns / 2 - 1; + int title_columns = columns / 2 - 1; - // Print "title" text - QString sized_title = title_; + // Print "title" text + QString sized_title = title_; - if (title_.size() > title_columns) { - sized_title = title_.left(title_columns - 3).append(QStringLiteral("...")); - } else { - sized_title = title_; - } + if (title_.size() > title_columns) { + sized_title = + title_.left(title_columns - 3).append(QStringLiteral("...")); + } else { + sized_title = title_; + } - std::cout << sized_title.toUtf8().constData(); + std::cout << sized_title.toUtf8().constData(); - // Pad out the rest of the title area if necessary - for (int i=sized_title.size(); iGetTitle(), parent), - task_(task) +namespace olive { - connect(task_, &Task::ProgressChanged, this, &CLITaskDialog::SetProgress); + +CLITaskDialog::CLITaskDialog(Task *task, QObject *parent) + : CLIProgressDialog(task->GetTitle(), parent) + , task_(task) +{ + connect(task_, &Task::ProgressChanged, this, &CLITaskDialog::SetProgress); } bool CLITaskDialog::Run() { - return task_->Start(); + return task_->Start(); } } diff --git a/app/cli/clitask/clitaskdialog.h b/app/cli/clitask/clitaskdialog.h index e07ffa6cc..219f1afca 100644 --- a/app/cli/clitask/clitaskdialog.h +++ b/app/cli/clitask/clitaskdialog.h @@ -24,19 +24,18 @@ #include "cli/cliprogress/cliprogressdialog.h" #include "task/task.h" -namespace olive { - -class CLITaskDialog : public CLIProgressDialog +namespace olive { - Q_OBJECT -public: - CLITaskDialog(Task *task, QObject* parent = nullptr); - bool Run(); +class CLITaskDialog : public CLIProgressDialog { + Q_OBJECT +public: + CLITaskDialog(Task *task, QObject *parent = nullptr); + + bool Run(); private: - Task* task_; - + Task *task_; }; } diff --git a/app/codec/conformmanager.cpp b/app/codec/conformmanager.cpp index 8f3acfa33..dd7ebe003 100644 --- a/app/codec/conformmanager.cpp +++ b/app/codec/conformmanager.cpp @@ -4,123 +4,137 @@ #include "task/taskmanager.h" -namespace olive { +namespace olive +{ ConformManager *ConformManager::instance_ = nullptr; -ConformManager::Conform ConformManager::GetConformState(const QString &decoder_id, const QString &cache_path, const Decoder::CodecStream &stream, const AudioParams ¶ms, bool wait) +ConformManager::Conform ConformManager::GetConformState( + const QString &decoder_id, const QString &cache_path, + const Decoder::CodecStream &stream, const AudioParams ¶ms, bool wait) { - // Mutex because we'll need to check the status of a conform task - QMutexLocker locker(&mutex_); + // Mutex because we'll need to check the status of a conform task + QMutexLocker locker(&mutex_); - // Return existing conform if exists - QVector filenames = GetConformedFilename(cache_path, stream, params); - if (AllConformsExist(filenames)) { - return {kConformExists, filenames, nullptr}; - } + // Return existing conform if exists + QVector filenames = + GetConformedFilename(cache_path, stream, params); + if (AllConformsExist(filenames)) { + return { kConformExists, filenames, nullptr }; + } - ConformTask *conforming_task = nullptr; + ConformTask *conforming_task = nullptr; - foreach (const ConformData &data, conforming_) { - if (data.stream == stream && data.params == params) { - // Already creating conform in a task - conforming_task = data.task; - break; - } - } + foreach (const ConformData &data, conforming_) { + if (data.stream == stream && data.params == params) { + // Already creating conform in a task + conforming_task = data.task; + break; + } + } - if (!conforming_task) { - // Not conforming yet, create a task to do so + if (!conforming_task) { + // Not conforming yet, create a task to do so - // We conform to a different filename until it's done to make it clear even across sessions - // whether this conform is ready or not - QVector working_filenames = filenames; - for (int i=0; i working_filenames = filenames; + for (int i = 0; i < working_filenames.size(); i++) { + working_filenames[i].append(QStringLiteral(".working")); + } - conforming_task = new ConformTask(decoder_id, stream, params, working_filenames); - connect(conforming_task, &ConformTask::Finished, this, &ConformManager::ConformTaskFinished); - conforming_task->moveToThread(TaskManager::instance()->thread()); - QMetaObject::invokeMethod(TaskManager::instance(), "AddTask", Qt::QueuedConnection, Q_ARG(Task *, conforming_task)); + conforming_task = + new ConformTask(decoder_id, stream, params, working_filenames); + connect(conforming_task, &ConformTask::Finished, this, + &ConformManager::ConformTaskFinished); + conforming_task->moveToThread(TaskManager::instance()->thread()); + QMetaObject::invokeMethod(TaskManager::instance(), "AddTask", + Qt::QueuedConnection, + Q_ARG(Task *, conforming_task)); - conforming_.append({stream, params, conforming_task, working_filenames, filenames}); - } + conforming_.append( + { stream, params, conforming_task, working_filenames, filenames }); + } - if (wait) { - do { - conform_done_condition_.wait(&mutex_); - } while (!AllConformsExist(filenames)); - return {kConformExists, filenames, nullptr}; - } + if (wait) { + do { + conform_done_condition_.wait(&mutex_); + } while (!AllConformsExist(filenames)); + return { kConformExists, filenames, nullptr }; + } - return {kConformGenerating, QVector(), conforming_task}; + return { kConformGenerating, QVector(), conforming_task }; } -QVector ConformManager::GetConformedFilename(const QString &cache_path, const Decoder::CodecStream &stream, const AudioParams ¶ms) +QVector +ConformManager::GetConformedFilename(const QString &cache_path, + const Decoder::CodecStream &stream, + const AudioParams ¶ms) { - QVector filenames(params.channel_count()); + QVector filenames(params.channel_count()); - for (int i=0; i &filenames) { - foreach (const QString &fn, filenames) { - if (!QFileInfo::exists(fn)) { - return false; - } - } + foreach (const QString &fn, filenames) { + if (!QFileInfo::exists(fn)) { + return false; + } + } - return true; + return true; } void ConformManager::ConformTaskFinished(Task *task, bool succeeded) { - QMutexLocker locker(&mutex_); + QMutexLocker locker(&mutex_); - ConformData data; + ConformData data; - // Remove conform data from list - for (int i=0; i filenames; - ConformTask *task; - }; + struct Conform { + ConformState state; + QVector filenames; + ConformTask *task; + }; - /** - * @brief Get conform state, and start conforming if no conform exists - * - * Thread-safe. - */ - Conform GetConformState(const QString &decoder_id, const QString &cache_path, const Decoder::CodecStream &stream, const AudioParams ¶ms, bool wait); + /** + * @brief Get conform state, and start conforming if no conform exists + * + * Thread-safe. + */ + Conform GetConformState(const QString &decoder_id, + const QString &cache_path, + const Decoder::CodecStream &stream, + const AudioParams ¶ms, bool wait); signals: - void ConformReady(); + void ConformReady(); private: - ConformManager() = default; + ConformManager() = default; - static ConformManager *instance_; + static ConformManager *instance_; - QMutex mutex_; + QMutex mutex_; - QWaitCondition conform_done_condition_; + QWaitCondition conform_done_condition_; - struct ConformData { - Decoder::CodecStream stream; - AudioParams params; - ConformTask *task; - QVector working_filename; - QVector finished_filename; - }; + struct ConformData { + Decoder::CodecStream stream; + AudioParams params; + ConformTask *task; + QVector working_filename; + QVector finished_filename; + }; - QVector conforming_; + QVector conforming_; - /** - * @brief Get the destination filename of an audio stream conformed to a set of parameters - */ - static QVector GetConformedFilename(const QString &cache_path, const Decoder::CodecStream &stream, const AudioParams ¶ms); + /** + * @brief Get the destination filename of an audio stream conformed to a set of parameters + */ + static QVector + GetConformedFilename(const QString &cache_path, + const Decoder::CodecStream &stream, + const AudioParams ¶ms); - static bool AllConformsExist(const QVector &filenames); + static bool AllConformsExist(const QVector &filenames); private slots: - void ConformTaskFinished(Task *task, bool succeeded); - + void ConformTaskFinished(Task *task, bool succeeded); }; -} +} // namespace olive #endif // CONFORMMANAGER_H diff --git a/app/codec/decoder.cpp b/app/codec/decoder.cpp index 185a964bb..b91f102bd 100644 --- a/app/codec/decoder.cpp +++ b/app/codec/decoder.cpp @@ -33,151 +33,162 @@ #include "node/project.h" #include "task/taskmanager.h" -namespace olive { +namespace olive +{ const rational Decoder::kAnyTimecode = RATIONAL_MIN; -Decoder::Decoder() : - cached_texture_(nullptr) +Decoder::Decoder() + : cached_texture_(nullptr) { - UpdateLastAccessed(); + UpdateLastAccessed(); } void Decoder::IncrementAccessTime(qint64 t) { - last_accessed_ += t; + last_accessed_ += t; } bool Decoder::Open(const CodecStream &stream) { - QMutexLocker locker(&mutex_); + QMutexLocker locker(&mutex_); - UpdateLastAccessed(); + UpdateLastAccessed(); - if (stream_.IsValid()) { - // Decoder is already open. Return TRUE if the stream is the stream we have, or FALSE if not. - if (stream_ == stream) { - return true; - } else { - qWarning() << "Tried to open a decoder that was already open with another stream"; - return false; - } - } else { - // Stream was not open, try opening it now - if (!stream.IsValid()) { - // Cannot open null stream - qCritical() << "Decoder attempted to open null stream"; - return false; - } + if (stream_.IsValid()) { + // Decoder is already open. Return TRUE if the stream is the stream we have, or FALSE if not. + if (stream_ == stream) { + return true; + } else { + qWarning() + << "Tried to open a decoder that was already open with another stream"; + return false; + } + } else { + // Stream was not open, try opening it now + if (!stream.IsValid()) { + // Cannot open null stream + qCritical() << "Decoder attempted to open null stream"; + return false; + } - if (!stream.Exists()) { - // Cannot open file that doesn't exist - qCritical() << "Decoder attempted to open file that doesn't exist"; - return false; - } + if (!stream.Exists()) { + // Cannot open file that doesn't exist + qCritical() << "Decoder attempted to open file that doesn't exist"; + return false; + } - // Set stream - stream_ = stream; + // Set stream + stream_ = stream; - // Try open internal - if (OpenInternal()) { - return true; - } else { - // Unset stream - qCritical() << "Failed to open" << stream_.filename() << "stream" << stream_.stream(); - CloseInternal(); - stream_.Reset(); - return false; - } - } + // Try open internal + if (OpenInternal()) { + return true; + } else { + // Unset stream + qCritical() << "Failed to open" << stream_.filename() << "stream" + << stream_.stream(); + CloseInternal(); + stream_.Reset(); + return false; + } + } } TexturePtr Decoder::RetrieveVideo(const RetrieveVideoParams &p) { - QMutexLocker locker(&mutex_); + QMutexLocker locker(&mutex_); - UpdateLastAccessed(); + UpdateLastAccessed(); - if (!stream_.IsValid()) { - qCritical() << "Can't retrieve video on a closed decoder"; - return nullptr; - } + if (!stream_.IsValid()) { + qCritical() << "Can't retrieve video on a closed decoder"; + return nullptr; + } - if (!SupportsVideo()) { - qCritical() << "Decoder doesn't support video"; - return nullptr; - } + if (!SupportsVideo()) { + qCritical() << "Decoder doesn't support video"; + return nullptr; + } - if (p.cancelled && p.cancelled->IsCancelled()) { - return nullptr; - } + if (p.cancelled && p.cancelled->IsCancelled()) { + return nullptr; + } - if (cached_texture_ && cached_time_ == p.time && cached_divider_ == p.divider) { - return cached_texture_; - } + if (cached_texture_ && cached_time_ == p.time && + cached_divider_ == p.divider) { + return cached_texture_; + } - cached_texture_ = RetrieveVideoInternal(p); - cached_time_ = p.time; - cached_divider_ = p.divider; + cached_texture_ = RetrieveVideoInternal(p); + cached_time_ = p.time; + cached_divider_ = p.divider; - return cached_texture_; + return cached_texture_; } -Decoder::RetrieveAudioStatus Decoder::RetrieveAudio(SampleBuffer &dest, const TimeRange &range, const AudioParams ¶ms, const QString& cache_path, LoopMode loop_mode, RenderMode::Mode mode) +Decoder::RetrieveAudioStatus +Decoder::RetrieveAudio(SampleBuffer &dest, const TimeRange &range, + const AudioParams ¶ms, const QString &cache_path, + LoopMode loop_mode, RenderMode::Mode mode) { - QMutexLocker locker(&mutex_); + QMutexLocker locker(&mutex_); - UpdateLastAccessed(); + UpdateLastAccessed(); - if (!stream_.IsValid()) { - qCritical() << "Can't retrieve audio on a closed decoder"; - return kInvalid; - } + if (!stream_.IsValid()) { + qCritical() << "Can't retrieve audio on a closed decoder"; + return kInvalid; + } - if (!SupportsAudio()) { - qCritical() << "Decoder doesn't support audio"; - return kInvalid; - } + if (!SupportsAudio()) { + qCritical() << "Decoder doesn't support audio"; + return kInvalid; + } - // Get conform state from ConformManager - ConformManager::Conform conform = ConformManager::instance()->GetConformState(id(), cache_path, stream_, params, (mode == RenderMode::kOnline)); - if (conform.state == ConformManager::kConformGenerating) { - // If we need the task, it's available in `conform.task` - return kWaitingForConform; - } + // Get conform state from ConformManager + ConformManager::Conform conform = + ConformManager::instance()->GetConformState( + id(), cache_path, stream_, params, (mode == RenderMode::kOnline)); + if (conform.state == ConformManager::kConformGenerating) { + // If we need the task, it's available in `conform.task` + return kWaitingForConform; + } - // See if we got the conform - if (RetrieveAudioFromConform(dest, conform.filenames, range, loop_mode, params)) { - return kOK; - } else { - return kUnknownError; - } + // See if we got the conform + if (RetrieveAudioFromConform(dest, conform.filenames, range, loop_mode, + params)) { + return kOK; + } else { + return kUnknownError; + } } qint64 Decoder::GetLastAccessedTime() { - return last_accessed_; + return last_accessed_; } void Decoder::Close() { - QMutexLocker locker(&mutex_); + QMutexLocker locker(&mutex_); - UpdateLastAccessed(); + UpdateLastAccessed(); - cached_texture_ = nullptr; + cached_texture_ = nullptr; - if (stream_.IsValid()) { - CloseInternal(); - stream_.Reset(); - } else { - qWarning() << "Tried to close a decoder that wasn't open"; - } + if (stream_.IsValid()) { + CloseInternal(); + stream_.Reset(); + } else { + qWarning() << "Tried to close a decoder that wasn't open"; + } } -bool Decoder::ConformAudio(const QVector &output_filenames, const AudioParams ¶ms, CancelAtom *cancelled) +bool Decoder::ConformAudio(const QVector &output_filenames, + const AudioParams ¶ms, CancelAtom *cancelled) { - return ConformAudioInternal(output_filenames, params, cancelled); + return ConformAudioInternal(output_filenames, params, cancelled); } /* @@ -186,159 +197,178 @@ bool Decoder::ConformAudio(const QVector &output_filenames, const Audio QVector Decoder::ReceiveListOfAllDecoders() { - QVector decoders; + QVector decoders; - // The order in which these decoders are added is their priority when probing. Hence FFmpeg should usually be last, - // since it supports so many formats and we presumably want to override those formats with a more specific decoder. - decoders.append(std::make_shared()); - decoders.append(std::make_shared()); + // The order in which these decoders are added is their priority when probing. Hence FFmpeg should usually be last, + // since it supports so many formats and we presumably want to override those formats with a more specific decoder. + decoders.append(std::make_shared()); + decoders.append(std::make_shared()); - return decoders; + return decoders; } DecoderPtr Decoder::CreateFromID(const QString &id) { - if (id.isEmpty()) { - return nullptr; - } + if (id.isEmpty()) { + return nullptr; + } - // Create list to iterate through - QVector decoder_list = ReceiveListOfAllDecoders(); + // Create list to iterate through + QVector decoder_list = ReceiveListOfAllDecoders(); - foreach (DecoderPtr d, decoder_list) { - if (d->id() == id) { - return d; - } - } + foreach (DecoderPtr d, decoder_list) { + if (d->id() == id) { + return d; + } + } - return nullptr; + return nullptr; } void Decoder::SignalProcessingProgress(int64_t ts, int64_t duration) { - if (duration != AV_NOPTS_VALUE && duration != 0) { - emit IndexProgress(static_cast(ts) / static_cast(duration)); - } + if (duration != AV_NOPTS_VALUE && duration != 0) { + emit IndexProgress(static_cast(ts) / + static_cast(duration)); + } } -QString Decoder::TransformImageSequenceFileName(const QString &filename, const int64_t& number) +QString Decoder::TransformImageSequenceFileName(const QString &filename, + const int64_t &number) { - int digit_count = GetImageSequenceDigitCount(filename); + int digit_count = GetImageSequenceDigitCount(filename); - QFileInfo file_info(filename); + QFileInfo file_info(filename); - QString original_basename = file_info.completeBaseName(); + QString original_basename = file_info.completeBaseName(); - QString new_basename = original_basename.left(original_basename.size() - digit_count) - .append(QStringLiteral("%1").arg(number, digit_count, 10, QChar('0'))); + QString new_basename = + original_basename.left(original_basename.size() - digit_count) + .append( + QStringLiteral("%1").arg(number, digit_count, 10, QChar('0'))); - return file_info.dir().filePath(file_info.fileName().replace(original_basename, new_basename)); + return file_info.dir().filePath( + file_info.fileName().replace(original_basename, new_basename)); } int Decoder::GetImageSequenceDigitCount(const QString &filename) { - QString basename = QFileInfo(filename).completeBaseName(); + QString basename = QFileInfo(filename).completeBaseName(); - // See if basename contains a number at the end - int digit_count = 0; + // See if basename contains a number at the end + int digit_count = 0; - for (int i=basename.size()-1;i>=0;i--) { - if (basename.at(i).isDigit()) { - digit_count++; - } else { - break; - } - } + for (int i = basename.size() - 1; i >= 0; i--) { + if (basename.at(i).isDigit()) { + digit_count++; + } else { + break; + } + } - return digit_count; + return digit_count; } int64_t Decoder::GetImageSequenceIndex(const QString &filename) { - int digit_count = GetImageSequenceDigitCount(filename); + int digit_count = GetImageSequenceDigitCount(filename); - QFileInfo file_info(filename); + QFileInfo file_info(filename); - QString original_basename = file_info.completeBaseName(); + QString original_basename = file_info.completeBaseName(); - QString number_only = original_basename.mid(original_basename.size() - digit_count); + QString number_only = + original_basename.mid(original_basename.size() - digit_count); - return number_only.toLongLong(); + return number_only.toLongLong(); } TexturePtr Decoder::RetrieveVideoInternal(const RetrieveVideoParams &p) { - Q_UNUSED(p) - return nullptr; + Q_UNUSED(p) + return nullptr; } -bool Decoder::ConformAudioInternal(const QVector &filenames, const AudioParams ¶ms, CancelAtom *cancelled) +bool Decoder::ConformAudioInternal(const QVector &filenames, + const AudioParams ¶ms, + CancelAtom *cancelled) { - Q_UNUSED(filenames) - Q_UNUSED(cancelled) - Q_UNUSED(params) - return false; + Q_UNUSED(filenames) + Q_UNUSED(cancelled) + Q_UNUSED(params) + return false; } -bool Decoder::RetrieveAudioFromConform(SampleBuffer &sample_buffer, const QVector &conform_filenames, TimeRange range, LoopMode loop_mode, const AudioParams &input_params) +bool Decoder::RetrieveAudioFromConform( + SampleBuffer &sample_buffer, const QVector &conform_filenames, + TimeRange range, LoopMode loop_mode, const AudioParams &input_params) { - PlanarFileDevice input; - if (input.open(conform_filenames, QFile::ReadOnly)) { - // Offset range by audio start offset - range -= GetAudioStartOffset(); + PlanarFileDevice input; + if (input.open(conform_filenames, QFile::ReadOnly)) { + // Offset range by audio start offset + range -= GetAudioStartOffset(); - qint64 read_index = input_params.time_to_bytes(range.in()) / input_params.channel_count(); - qint64 write_index = 0; + qint64 read_index = input_params.time_to_bytes(range.in()) / + input_params.channel_count(); + qint64 write_index = 0; - const qint64 buffer_length_in_bytes = sample_buffer.sample_count() * input_params.bytes_per_sample_per_channel(); + const qint64 buffer_length_in_bytes = + sample_buffer.sample_count() * + input_params.bytes_per_sample_per_channel(); - while (write_index < buffer_length_in_bytes) { - if (loop_mode == LoopMode::kLoopModeLoop) { - while (read_index >= input.size()) { - read_index -= input.size(); - } + while (write_index < buffer_length_in_bytes) { + if (loop_mode == LoopMode::kLoopModeLoop) { + while (read_index >= input.size()) { + read_index -= input.size(); + } - while (read_index < 0) { - read_index += input.size(); - } - } + while (read_index < 0) { + read_index += input.size(); + } + } - qint64 write_count = 0; + qint64 write_count = 0; - if (read_index < 0) { - // Reading before 0, write silence here until audio data would actually start - write_count = qMin(-read_index, buffer_length_in_bytes); - sample_buffer.silence_bytes(write_index, write_index + write_count); - } else if (read_index >= input.size()) { - // Reading after data length, write silence until the end of the buffer - write_count = buffer_length_in_bytes - write_index; - sample_buffer.silence_bytes(write_index, write_index + write_count); - } else { - write_count = qMin(input.size() - read_index, buffer_length_in_bytes - write_index); - input.seek(read_index); - input.read(reinterpret_cast(sample_buffer.to_raw_ptrs().data()), write_count, write_index); - } + if (read_index < 0) { + // Reading before 0, write silence here until audio data would actually start + write_count = qMin(-read_index, buffer_length_in_bytes); + sample_buffer.silence_bytes(write_index, + write_index + write_count); + } else if (read_index >= input.size()) { + // Reading after data length, write silence until the end of the buffer + write_count = buffer_length_in_bytes - write_index; + sample_buffer.silence_bytes(write_index, + write_index + write_count); + } else { + write_count = qMin(input.size() - read_index, + buffer_length_in_bytes - write_index); + input.seek(read_index); + input.read(reinterpret_cast( + sample_buffer.to_raw_ptrs().data()), + write_count, write_index); + } - read_index += write_count; - write_index += write_count; - } + read_index += write_count; + write_index += write_count; + } - input.close(); + input.close(); - return true; - } + return true; + } - return false; + return false; } void Decoder::UpdateLastAccessed() { - last_accessed_ = QDateTime::currentMSecsSinceEpoch(); + last_accessed_ = QDateTime::currentMSecsSinceEpoch(); } uint qHash(Decoder::CodecStream stream, uint seed) { - return qHash(stream.filename(), seed) ^ ::qHash(stream.stream(), seed) ^ qHash(stream.block(), seed); + return qHash(stream.filename(), seed) ^ ::qHash(stream.stream(), seed) ^ + qHash(stream.block(), seed); } } diff --git a/app/codec/decoder.h b/app/codec/decoder.h index de258296d..84efe883f 100644 --- a/app/codec/decoder.h +++ b/app/codec/decoder.h @@ -36,12 +36,17 @@ extern "C" { #include "render/cancelatom.h" #include "render/rendermodes.h" -namespace olive { +namespace olive +{ class Decoder; using DecoderPtr = std::shared_ptr; -#define DECODER_DEFAULT_DESTRUCTOR(x) virtual ~x() override {CloseInternal();} +#define DECODER_DEFAULT_DESTRUCTOR(x) \ + virtual ~x() override \ + { \ + CloseInternal(); \ + } /** * @brief A decoder's is the main class for bringing external media into Olive @@ -59,89 +64,88 @@ using DecoderPtr = std::shared_ptr; * A decoder does NOT perform any pixel/sample format conversion. Frames should pass through the PixelService * to be utilized in the rest of the rendering pipeline. */ -class Decoder : public QObject -{ - Q_OBJECT +class Decoder : public QObject { + Q_OBJECT public: - enum RetrieveState { - kReady, - kFailedToOpen, - kIndexUnavailable - }; + enum RetrieveState { kReady, kFailedToOpen, kIndexUnavailable }; - Decoder(); + Decoder(); - /** + /** * @brief Unique decoder ID */ - virtual QString id() const = 0; + virtual QString id() const = 0; - virtual bool SupportsVideo(){return false;} - virtual bool SupportsAudio(){return false;} + virtual bool SupportsVideo() + { + return false; + } + virtual bool SupportsAudio() + { + return false; + } - void IncrementAccessTime(qint64 t); + void IncrementAccessTime(qint64 t); - class CodecStream - { - public: - CodecStream() : - stream_(-1), - block_(nullptr) - { - } + class CodecStream { + public: + CodecStream() + : stream_(-1) + , block_(nullptr) + { + } - CodecStream(const QString& filename, int stream, Block *block) : - filename_(filename), - stream_(stream), - block_(block) - { - } + CodecStream(const QString &filename, int stream, Block *block) + : filename_(filename) + , stream_(stream) + , block_(block) + { + } - bool IsValid() const - { - return !filename_.isEmpty() && stream_ >= 0; - } + bool IsValid() const + { + return !filename_.isEmpty() && stream_ >= 0; + } - bool Exists() const - { - return QFileInfo::exists(filename_); - } + bool Exists() const + { + return QFileInfo::exists(filename_); + } - void Reset() - { - *this = CodecStream(); - } + void Reset() + { + *this = CodecStream(); + } - bool operator==(const CodecStream& rhs) const - { - return filename_ == rhs.filename_ && stream_ == rhs.stream_; - } + bool operator==(const CodecStream &rhs) const + { + return filename_ == rhs.filename_ && stream_ == rhs.stream_; + } - const QString& filename() const - { - return filename_; - } + const QString &filename() const + { + return filename_; + } - int stream() const - { - return stream_; - } + int stream() const + { + return stream_; + } - Block *block() const - { - return block_; - } + Block *block() const + { + return block_; + } - private: - QString filename_; + private: + QString filename_; - int stream_; + int stream_; - Block *block_; + Block *block_; + }; - }; - - /** + /** * @brief Open stream for decoding * * This function is thread safe. @@ -150,22 +154,21 @@ public: * already open and the stream == the stream provided. Returns FALSE if the stream couldn't * be opened OR if already open and the stream is NOT the same. */ - bool Open(const CodecStream& stream); + bool Open(const CodecStream &stream); - static const rational kAnyTimecode; + static const rational kAnyTimecode; - struct RetrieveVideoParams - { - Renderer *renderer = nullptr; - rational time; - int divider = 1; - PixelFormat maximum_format = PixelFormat::INVALID; - CancelAtom *cancelled = nullptr; - VideoParams::ColorRange force_range = VideoParams::kColorRangeDefault; - VideoParams::Interlacing src_interlacing = VideoParams::kInterlaceNone; - }; + struct RetrieveVideoParams { + Renderer *renderer = nullptr; + rational time; + int divider = 1; + PixelFormat maximum_format = PixelFormat::INVALID; + CancelAtom *cancelled = nullptr; + VideoParams::ColorRange force_range = VideoParams::kColorRangeDefault; + VideoParams::Interlacing src_interlacing = VideoParams::kInterlaceNone; + }; - /** + /** * @brief Retrieves a video frame from footage * * This function will always return a valid frame unless a fatal error occurs (in such case, @@ -175,16 +178,16 @@ public: * * This function is thread safe and can only run while the decoder is open. \see Open() */ - TexturePtr RetrieveVideo(const RetrieveVideoParams& p); + TexturePtr RetrieveVideo(const RetrieveVideoParams &p); - enum RetrieveAudioStatus { - kInvalid = -1, - kOK, - kWaitingForConform, - kUnknownError - }; + enum RetrieveAudioStatus { + kInvalid = -1, + kOK, + kWaitingForConform, + kUnknownError + }; - /** + /** * @brief Retrieve audio data from footage * * This function will always return a sample buffer unless a fatal error occurs (in such case, @@ -192,14 +195,17 @@ public: * * This function is thread safe and can only run while the decoder is open. \see Open() */ - RetrieveAudioStatus RetrieveAudio(SampleBuffer &dest, const TimeRange& range, const AudioParams& params, const QString &cache_path, LoopMode loop_mode, RenderMode::Mode mode); + RetrieveAudioStatus + RetrieveAudio(SampleBuffer &dest, const TimeRange &range, + const AudioParams ¶ms, const QString &cache_path, + LoopMode loop_mode, RenderMode::Mode mode); - /** + /** * @brief Determine the last time this decoder instance was used in any way */ - qint64 GetLastAccessedTime(); + qint64 GetLastAccessedTime(); - /** + /** * @brief Generate a Footage object from a file * * If this decoder is able to parse this file, it will return a valid FootagePtr. Otherwise, it @@ -210,39 +216,43 @@ public: * * This function is re-entrant. */ - virtual FootageDescription Probe(const QString& filename, CancelAtom *cancelled) const = 0; + virtual FootageDescription Probe(const QString &filename, + CancelAtom *cancelled) const = 0; - /** + /** * @brief Closes media/deallocates memory * * This function is thread safe and can only run while the decoder is open. \see Open() */ - void Close(); + void Close(); - /** + /** * @brief Conform audio stream */ - bool ConformAudio(const QVector &output_filenames, const AudioParams ¶ms, CancelAtom *cancelled = nullptr); + bool ConformAudio(const QVector &output_filenames, + const AudioParams ¶ms, + CancelAtom *cancelled = nullptr); - /** + /** * @brief Create a Decoder instance using a Decoder ID * * @return * * A Decoder instance or nullptr if a Decoder with this ID does not exist */ - static DecoderPtr CreateFromID(const QString& id); + static DecoderPtr CreateFromID(const QString &id); - static QString TransformImageSequenceFileName(const QString& filename, const int64_t& number); + static QString TransformImageSequenceFileName(const QString &filename, + const int64_t &number); - static int GetImageSequenceDigitCount(const QString& filename); + static int GetImageSequenceDigitCount(const QString &filename); - static int64_t GetImageSequenceIndex(const QString& filename); + static int64_t GetImageSequenceIndex(const QString &filename); - static QVector ReceiveListOfAllDecoders(); + static QVector ReceiveListOfAllDecoders(); protected: - /** + /** * @brief Internal open function * * Sub-classes must override this function. Function will already be mutexed, so there is no need @@ -254,62 +264,69 @@ protected: * return FALSE. If this function returns false, Decoder will call CloseInternal to clean any * memory allocated during OpenInternal. */ - virtual bool OpenInternal() = 0; + virtual bool OpenInternal() = 0; - /** + /** * @brief Internal close function * * Sub-classes must override this function. Function should be able to safely clear all allocated * memory. It may be called even if Open() didn't complete or RetrieveVideo() was never called. */ - virtual void CloseInternal() = 0; + virtual void CloseInternal() = 0; - /** + /** * @brief Internal frame retrieval function * * Sub-classes must override this function IF they support video. Function is already mutexed * so sub-classes don't need to worry about thread safety. */ - virtual TexturePtr RetrieveVideoInternal(const RetrieveVideoParams& p); + virtual TexturePtr RetrieveVideoInternal(const RetrieveVideoParams &p); - virtual bool ConformAudioInternal(const QVector& filenames, const AudioParams ¶ms, CancelAtom *cancelled); + virtual bool ConformAudioInternal(const QVector &filenames, + const AudioParams ¶ms, + CancelAtom *cancelled); - void SignalProcessingProgress(int64_t ts, int64_t duration); + void SignalProcessingProgress(int64_t ts, int64_t duration); - /** + /** * @brief Return currently open stream * * This function is NOT thread safe and should therefore only be called by thread safe functions. */ - const CodecStream& stream() const - { - return stream_; - } + const CodecStream &stream() const + { + return stream_; + } - virtual rational GetAudioStartOffset() const { return 0; } + virtual rational GetAudioStartOffset() const + { + return 0; + } signals: - /** + /** * @brief While indexing, this signal will provide progress as a percentage (0-100 inclusive) if * available */ - void IndexProgress(double); + void IndexProgress(double); private: - void UpdateLastAccessed(); + void UpdateLastAccessed(); - bool RetrieveAudioFromConform(SampleBuffer &sample_buffer, const QVector &conform_filenames, TimeRange range, LoopMode loop_mode, const AudioParams ¶ms); + bool RetrieveAudioFromConform(SampleBuffer &sample_buffer, + const QVector &conform_filenames, + TimeRange range, LoopMode loop_mode, + const AudioParams ¶ms); - CodecStream stream_; + CodecStream stream_; - QMutex mutex_; + QMutex mutex_; - std::atomic_int64_t last_accessed_; - - TexturePtr cached_texture_; - rational cached_time_; - int cached_divider_; + std::atomic_int64_t last_accessed_; + TexturePtr cached_texture_; + rational cached_time_; + int cached_divider_; }; uint qHash(Decoder::CodecStream stream, uint seed = 0); diff --git a/app/codec/encoder.cpp b/app/codec/encoder.cpp index e405e5323..97b70730a 100644 --- a/app/codec/encoder.cpp +++ b/app/codec/encoder.cpp @@ -26,492 +26,568 @@ #include "ffmpeg/ffmpegencoder.h" #include "oiio/oiioencoder.h" -namespace olive { +namespace olive +{ -const QRegularExpression Encoder::kImageSequenceContainsDigits = QRegularExpression(QStringLiteral("\\[[#]+\\]")); -const QRegularExpression Encoder::kImageSequenceRemoveDigits = QRegularExpression(QStringLiteral("[\\-\\.\\ \\_]?\\[[#]+\\]")); +const QRegularExpression Encoder::kImageSequenceContainsDigits = + QRegularExpression(QStringLiteral("\\[[#]+\\]")); +const QRegularExpression Encoder::kImageSequenceRemoveDigits = + QRegularExpression(QStringLiteral("[\\-\\.\\ \\_]?\\[[#]+\\]")); -Encoder::Encoder(const EncodingParams ¶ms) : - params_(params) +Encoder::Encoder(const EncodingParams ¶ms) + : params_(params) { } const EncodingParams &Encoder::params() const { - return params_; + return params_; } QString Encoder::GetFilenameForFrame(const rational &frame) { - if (params().video_is_image_sequence()) { - // Transform! - int64_t frame_index = Timecode::time_to_timestamp(frame, params().video_params().frame_rate_as_time_base()); - int digits = GetImageSequencePlaceholderDigitCount(params().filename()); - QString frame_index_str = QStringLiteral("%1").arg(frame_index, digits, 10, QChar('0')); + if (params().video_is_image_sequence()) { + // Transform! + int64_t frame_index = Timecode::time_to_timestamp( + frame, params().video_params().frame_rate_as_time_base()); + int digits = GetImageSequencePlaceholderDigitCount(params().filename()); + QString frame_index_str = + QStringLiteral("%1").arg(frame_index, digits, 10, QChar('0')); - QString f = params_.filename(); - f.replace(kImageSequenceContainsDigits, frame_index_str); - return f; - } else { - // Keep filename - return params_.filename(); - } + QString f = params_.filename(); + f.replace(kImageSequenceContainsDigits, frame_index_str); + return f; + } else { + // Keep filename + return params_.filename(); + } } int Encoder::GetImageSequencePlaceholderDigitCount(const QString &filename) { - int start = filename.indexOf(kImageSequenceContainsDigits); - int digit_count = 0; - for (int i=start+1; iname() == QStringLiteral("export")) { - int version = 0; + while (XMLReadNextStartElement(reader)) { + if (reader->name() == QStringLiteral("export")) { + int version = 0; - XMLAttributeLoop(reader, attr) { - if (attr.name() == QStringLiteral("version")) { - version = attr.value().toInt(); - } - } + XMLAttributeLoop(reader, attr) + { + if (attr.name() == QStringLiteral("version")) { + version = attr.value().toInt(); + } + } - switch (version) { - case 1: - return LoadV1(reader); - } - } else { - reader->skipCurrentElement(); - } - } + switch (version) { + case 1: + return LoadV1(reader); + } + } else { + reader->skipCurrentElement(); + } + } - return false; + return false; } bool EncodingParams::Load(QIODevice *device) { - QXmlStreamReader reader(device); - return Load(&reader); + QXmlStreamReader reader(device); + return Load(&reader); } void EncodingParams::Save(QIODevice *device) const { - QXmlStreamWriter writer(device); - Save(&writer); + QXmlStreamWriter writer(device); + Save(&writer); } void EncodingParams::Save(QXmlStreamWriter *writer) const { - writer->writeStartDocument(); + writer->writeStartDocument(); - writer->writeStartElement(QStringLiteral("export")); + writer->writeStartElement(QStringLiteral("export")); - writer->writeAttribute(QStringLiteral("version"), QString::number(kEncoderParamsVersion)); + writer->writeAttribute(QStringLiteral("version"), + QString::number(kEncoderParamsVersion)); - writer->writeTextElement(QStringLiteral("filename"), filename_); - writer->writeTextElement(QStringLiteral("format"), QString::number(format_)); + writer->writeTextElement(QStringLiteral("filename"), filename_); + writer->writeTextElement(QStringLiteral("format"), + QString::number(format_)); - writer->writeTextElement(QStringLiteral("range"), QString::number(has_custom_range_)); - writer->writeTextElement(QStringLiteral("customrangein"), QString::fromStdString(custom_range_.in().toString())); - writer->writeTextElement(QStringLiteral("customrangeout"), QString::fromStdString(custom_range_.out().toString())); + writer->writeTextElement(QStringLiteral("range"), + QString::number(has_custom_range_)); + writer->writeTextElement( + QStringLiteral("customrangein"), + QString::fromStdString(custom_range_.in().toString())); + writer->writeTextElement( + QStringLiteral("customrangeout"), + QString::fromStdString(custom_range_.out().toString())); - writer->writeStartElement(QStringLiteral("video")); + writer->writeStartElement(QStringLiteral("video")); - writer->writeAttribute(QStringLiteral("enabled"), QString::number(video_enabled_)); + writer->writeAttribute(QStringLiteral("enabled"), + QString::number(video_enabled_)); - if (video_enabled_) { - writer->writeTextElement(QStringLiteral("codec"), QString::number(video_codec_)); - writer->writeTextElement(QStringLiteral("width"), QString::number(video_params_.width())); - writer->writeTextElement(QStringLiteral("height"), QString::number(video_params_.height())); - writer->writeTextElement(QStringLiteral("format"), QString::number(video_params_.format())); - writer->writeTextElement(QStringLiteral("pixelaspect"), QString::fromStdString(video_params_.pixel_aspect_ratio().toString())); - writer->writeTextElement(QStringLiteral("timebase"), QString::fromStdString(video_params_.time_base().toString())); - writer->writeTextElement(QStringLiteral("divider"), QString::number(video_params_.divider())); - writer->writeTextElement(QStringLiteral("bitrate"), QString::number(video_bit_rate_)); - writer->writeTextElement(QStringLiteral("minbitrate"), QString::number(video_min_bit_rate_)); - writer->writeTextElement(QStringLiteral("maxbitrate"), QString::number(video_max_bit_rate_)); - writer->writeTextElement(QStringLiteral("bufsize"), QString::number(video_buffer_size_)); - writer->writeTextElement(QStringLiteral("threads"), QString::number(video_threads_)); - writer->writeTextElement(QStringLiteral("pixfmt"), video_pix_fmt_); - writer->writeTextElement(QStringLiteral("imgseq"), QString::number(video_is_image_sequence_)); + if (video_enabled_) { + writer->writeTextElement(QStringLiteral("codec"), + QString::number(video_codec_)); + writer->writeTextElement(QStringLiteral("width"), + QString::number(video_params_.width())); + writer->writeTextElement(QStringLiteral("height"), + QString::number(video_params_.height())); + writer->writeTextElement(QStringLiteral("format"), + QString::number(video_params_.format())); + writer->writeTextElement( + QStringLiteral("pixelaspect"), + QString::fromStdString( + video_params_.pixel_aspect_ratio().toString())); + writer->writeTextElement( + QStringLiteral("timebase"), + QString::fromStdString(video_params_.time_base().toString())); + writer->writeTextElement(QStringLiteral("divider"), + QString::number(video_params_.divider())); + writer->writeTextElement(QStringLiteral("bitrate"), + QString::number(video_bit_rate_)); + writer->writeTextElement(QStringLiteral("minbitrate"), + QString::number(video_min_bit_rate_)); + writer->writeTextElement(QStringLiteral("maxbitrate"), + QString::number(video_max_bit_rate_)); + writer->writeTextElement(QStringLiteral("bufsize"), + QString::number(video_buffer_size_)); + writer->writeTextElement(QStringLiteral("threads"), + QString::number(video_threads_)); + writer->writeTextElement(QStringLiteral("pixfmt"), video_pix_fmt_); + writer->writeTextElement(QStringLiteral("imgseq"), + QString::number(video_is_image_sequence_)); - writer->writeStartElement(QStringLiteral("color")); - writer->writeTextElement(QStringLiteral("output"), color_transform_.output()); - writer->writeEndElement(); // colortransform + writer->writeStartElement(QStringLiteral("color")); + writer->writeTextElement(QStringLiteral("output"), + color_transform_.output()); + writer->writeEndElement(); // colortransform - writer->writeTextElement(QStringLiteral("vscale"), QString::number(video_scaling_method_)); + writer->writeTextElement(QStringLiteral("vscale"), + QString::number(video_scaling_method_)); - if (!video_opts_.isEmpty()) { - writer->writeStartElement(QStringLiteral("opts")); + if (!video_opts_.isEmpty()) { + writer->writeStartElement(QStringLiteral("opts")); - QHash::const_iterator i; - for (i=video_opts_.constBegin(); i!=video_opts_.constEnd(); i++) { - writer->writeStartElement(QStringLiteral("entry")); + QHash::const_iterator i; + for (i = video_opts_.constBegin(); i != video_opts_.constEnd(); + i++) { + writer->writeStartElement(QStringLiteral("entry")); - writer->writeTextElement(QStringLiteral("key"), i.key()); - writer->writeTextElement(QStringLiteral("value"), i.value()); + writer->writeTextElement(QStringLiteral("key"), i.key()); + writer->writeTextElement(QStringLiteral("value"), i.value()); - writer->writeEndElement(); // entry - } + writer->writeEndElement(); // entry + } - writer->writeEndElement(); // opts - } - } + writer->writeEndElement(); // opts + } + } - writer->writeEndElement(); // video + writer->writeEndElement(); // video - writer->writeStartElement(QStringLiteral("audio")); + writer->writeStartElement(QStringLiteral("audio")); - writer->writeAttribute(QStringLiteral("enabled"), QString::number(audio_enabled_)); + writer->writeAttribute(QStringLiteral("enabled"), + QString::number(audio_enabled_)); - if (audio_enabled_) { - writer->writeTextElement(QStringLiteral("codec"), QString::number(audio_codec_)); - writer->writeTextElement(QStringLiteral("samplerate"), QString::number(audio_params_.sample_rate())); + if (audio_enabled_) { + writer->writeTextElement(QStringLiteral("codec"), + QString::number(audio_codec_)); + writer->writeTextElement(QStringLiteral("samplerate"), + QString::number(audio_params_.sample_rate())); - writer->writeTextElement(QStringLiteral("channellayout"), - QString::number(audio_params().channel_layout().u.mask)); - writer->writeTextElement(QStringLiteral("format"), QString::fromStdString(audio_params_.format().to_string())); - writer->writeTextElement(QStringLiteral("bitrate"), QString::number(audio_bit_rate_)); - } + writer->writeTextElement( + QStringLiteral("channellayout"), + QString::number(audio_params().channel_layout().u.mask)); + writer->writeTextElement( + QStringLiteral("format"), + QString::fromStdString(audio_params_.format().to_string())); + writer->writeTextElement(QStringLiteral("bitrate"), + QString::number(audio_bit_rate_)); + } - writer->writeStartElement(QStringLiteral("subtitles")); + writer->writeStartElement(QStringLiteral("subtitles")); - writer->writeAttribute(QStringLiteral("enabled"), QString::number(subtitles_enabled_)); + writer->writeAttribute(QStringLiteral("enabled"), + QString::number(subtitles_enabled_)); - if (subtitles_enabled_) { - writer->writeTextElement(QStringLiteral("sidecar"), QString::number(subtitles_are_sidecar_)); - writer->writeTextElement(QStringLiteral("sidecarformat"), QString::number(subtitle_sidecar_fmt_)); + if (subtitles_enabled_) { + writer->writeTextElement(QStringLiteral("sidecar"), + QString::number(subtitles_are_sidecar_)); + writer->writeTextElement(QStringLiteral("sidecarformat"), + QString::number(subtitle_sidecar_fmt_)); - writer->writeTextElement(QStringLiteral("codec"), QString::number(subtitles_codec_)); - } + writer->writeTextElement(QStringLiteral("codec"), + QString::number(subtitles_codec_)); + } - writer->writeEndElement(); // subtitles + writer->writeEndElement(); // subtitles - writer->writeEndElement(); // audio + writer->writeEndElement(); // audio - writer->writeEndElement(); // export + writer->writeEndElement(); // export - writer->writeEndDocument(); + writer->writeEndDocument(); } -Encoder* Encoder::CreateFromID(Type id, const EncodingParams& params) +Encoder *Encoder::CreateFromID(Type id, const EncodingParams ¶ms) { - switch (id) { - case kEncoderTypeNone: - break; - case kEncoderTypeFFmpeg: - return new FFmpegEncoder(params); - case kEncoderTypeOIIO: - return new OIIOEncoder(params); - } + switch (id) { + case kEncoderTypeNone: + break; + case kEncoderTypeFFmpeg: + return new FFmpegEncoder(params); + case kEncoderTypeOIIO: + return new OIIOEncoder(params); + } - return nullptr; + return nullptr; } Encoder::Type Encoder::GetTypeFromFormat(ExportFormat::Format f) { - switch (f) { - case ExportFormat::kFormatDNxHD: - case ExportFormat::kFormatMatroska: - case ExportFormat::kFormatQuickTime: - case ExportFormat::kFormatMPEG4Video: - case ExportFormat::kFormatMPEG4Audio: - case ExportFormat::kFormatWAV: - case ExportFormat::kFormatAIFF: - case ExportFormat::kFormatMP3: - case ExportFormat::kFormatFLAC: - case ExportFormat::kFormatOgg: - case ExportFormat::kFormatWebM: - case ExportFormat::kFormatSRT: - return kEncoderTypeFFmpeg; - case ExportFormat::kFormatOpenEXR: - case ExportFormat::kFormatPNG: - case ExportFormat::kFormatTIFF: - return kEncoderTypeOIIO; - case ExportFormat::kFormatCount: - break; - } + switch (f) { + case ExportFormat::kFormatDNxHD: + case ExportFormat::kFormatMatroska: + case ExportFormat::kFormatQuickTime: + case ExportFormat::kFormatMPEG4Video: + case ExportFormat::kFormatMPEG4Audio: + case ExportFormat::kFormatWAV: + case ExportFormat::kFormatAIFF: + case ExportFormat::kFormatMP3: + case ExportFormat::kFormatFLAC: + case ExportFormat::kFormatOgg: + case ExportFormat::kFormatWebM: + case ExportFormat::kFormatSRT: + return kEncoderTypeFFmpeg; + case ExportFormat::kFormatOpenEXR: + case ExportFormat::kFormatPNG: + case ExportFormat::kFormatTIFF: + return kEncoderTypeOIIO; + case ExportFormat::kFormatCount: + break; + } - return kEncoderTypeNone; + return kEncoderTypeNone; } -Encoder *Encoder::CreateFromFormat(ExportFormat::Format f, const EncodingParams ¶ms) +Encoder *Encoder::CreateFromFormat(ExportFormat::Format f, + const EncodingParams ¶ms) { - return CreateFromID(GetTypeFromFormat(f), params); + return CreateFromID(GetTypeFromFormat(f), params); } Encoder *Encoder::CreateFromParams(const EncodingParams ¶ms) { - return CreateFromFormat(params.format(), params); + return CreateFromFormat(params.format(), params); } QStringList Encoder::GetPixelFormatsForCodec(ExportCodec::Codec c) const { - return QStringList(); + return QStringList(); } -std::vector Encoder::GetSampleFormatsForCodec(ExportCodec::Codec c) const +std::vector +Encoder::GetSampleFormatsForCodec(ExportCodec::Codec c) const { - return std::vector(); + return std::vector(); } -QMatrix4x4 EncodingParams::GenerateMatrix(EncodingParams::VideoScalingMethod method, - int source_width, int source_height, - int dest_width, int dest_height) +QMatrix4x4 +EncodingParams::GenerateMatrix(EncodingParams::VideoScalingMethod method, + int source_width, int source_height, + int dest_width, int dest_height) { - QMatrix4x4 preview_matrix; + QMatrix4x4 preview_matrix; - if (method == EncodingParams::kStretch) { - return preview_matrix; - } + if (method == EncodingParams::kStretch) { + return preview_matrix; + } - float export_ar = static_cast(dest_width) / static_cast(dest_height); - float source_ar = static_cast(source_width) / static_cast(source_height); + float export_ar = + static_cast(dest_width) / static_cast(dest_height); + float source_ar = + static_cast(source_width) / static_cast(source_height); - if (qFuzzyCompare(export_ar, source_ar)) { - return preview_matrix; - } + if (qFuzzyCompare(export_ar, source_ar)) { + return preview_matrix; + } - if ((export_ar > source_ar) == (method == EncodingParams::kFit)) { - preview_matrix.scale(source_ar / export_ar, 1.0F); - } else { - preview_matrix.scale(1.0F, export_ar / source_ar); - } + if ((export_ar > source_ar) == (method == EncodingParams::kFit)) { + preview_matrix.scale(source_ar / export_ar, 1.0F); + } else { + preview_matrix.scale(1.0F, export_ar / source_ar); + } - return preview_matrix; + return preview_matrix; } bool EncodingParams::LoadV1(QXmlStreamReader *reader) { - rational custom_range_in, custom_range_out; + rational custom_range_in, custom_range_out; - while (XMLReadNextStartElement(reader)) { - if (reader->name() == QStringLiteral("filename")) { - filename_ = reader->readElementText(); - } else if (reader->name() == QStringLiteral("format")) { - format_ = static_cast(reader->readElementText().toInt()); - } else if (reader->name() == QStringLiteral("range")) { - has_custom_range_ = reader->readElementText().toInt(); - } else if (reader->name() == QStringLiteral("customrangein")) { - custom_range_in = rational::fromString(reader->readElementText().toStdString()); - } else if (reader->name() == QStringLiteral("customrangeout")) { - custom_range_out = rational::fromString(reader->readElementText().toStdString()); - } else if (reader->name() == QStringLiteral("video")) { - XMLAttributeLoop(reader, attr) { - if (attr.name() == QStringLiteral("enabled")) { - video_enabled_ = attr.value().toInt(); - } - } + while (XMLReadNextStartElement(reader)) { + if (reader->name() == QStringLiteral("filename")) { + filename_ = reader->readElementText(); + } else if (reader->name() == QStringLiteral("format")) { + format_ = static_cast( + reader->readElementText().toInt()); + } else if (reader->name() == QStringLiteral("range")) { + has_custom_range_ = reader->readElementText().toInt(); + } else if (reader->name() == QStringLiteral("customrangein")) { + custom_range_in = + rational::fromString(reader->readElementText().toStdString()); + } else if (reader->name() == QStringLiteral("customrangeout")) { + custom_range_out = + rational::fromString(reader->readElementText().toStdString()); + } else if (reader->name() == QStringLiteral("video")) { + XMLAttributeLoop(reader, attr) + { + if (attr.name() == QStringLiteral("enabled")) { + video_enabled_ = attr.value().toInt(); + } + } - while (XMLReadNextStartElement(reader)) { - if (reader->name() == QStringLiteral("codec")) { - video_codec_ = static_cast(reader->readElementText().toInt()); - } else if (reader->name() == QStringLiteral("width")) { - video_params_.set_width(reader->readElementText().toInt()); - } else if (reader->name() == QStringLiteral("height")) { - video_params_.set_height(reader->readElementText().toInt()); - } else if (reader->name() == QStringLiteral("format")) { - video_params_.set_format(static_cast(reader->readElementText().toInt())); - } else if (reader->name() == QStringLiteral("pixelaspect")) { - video_params_.set_pixel_aspect_ratio(rational::fromString(reader->readElementText().toStdString())); - } else if (reader->name() == QStringLiteral("timebase")) { - video_params_.set_time_base(rational::fromString(reader->readElementText().toStdString())); - } else if (reader->name() == QStringLiteral("divider")) { - video_params_.set_divider(reader->readElementText().toInt()); - } else if (reader->name() == QStringLiteral("bitrate")) { - video_bit_rate_ = reader->readElementText().toLongLong(); - } else if (reader->name() == QStringLiteral("minbitrate")) { - video_min_bit_rate_ = reader->readElementText().toLongLong(); - } else if (reader->name() == QStringLiteral("maxbitrate")) { - video_max_bit_rate_ = reader->readElementText().toLongLong(); - } else if (reader->name() == QStringLiteral("bufsize")) { - video_buffer_size_ = reader->readElementText().toLongLong(); - } else if (reader->name() == QStringLiteral("threads")) { - video_threads_ = reader->readElementText().toInt(); - } else if (reader->name() == QStringLiteral("pixfmt")) { - video_pix_fmt_ = reader->readElementText(); - } else if (reader->name() == QStringLiteral("imgseq")) { - video_is_image_sequence_ = reader->readElementText().toInt(); - } else if (reader->name() == QStringLiteral("color")) { - while (XMLReadNextStartElement(reader)) { - if (reader->name() == QStringLiteral("output")) { - color_transform_ = reader->readElementText(); - } else { - reader->skipCurrentElement(); - } - } - } else if (reader->name() == QStringLiteral("vscale")) { - video_scaling_method_ = static_cast(reader->readElementText().toInt()); - } else if (reader->name() == QStringLiteral("opts")) { - while (XMLReadNextStartElement(reader)) { - if (reader->name() == QStringLiteral("entry")) { - QString key, value; - while (XMLReadNextStartElement(reader)) { - if (reader->name() == QStringLiteral("key")) { - key = reader->readElementText(); - } else if (reader->name() == QStringLiteral("value")) { - value = reader->readElementText(); - } else { - reader->skipCurrentElement(); - } - } - set_video_option(key, value); - } else { - reader->skipCurrentElement(); - } - } - } else { - reader->skipCurrentElement(); - } - } + while (XMLReadNextStartElement(reader)) { + if (reader->name() == QStringLiteral("codec")) { + video_codec_ = static_cast( + reader->readElementText().toInt()); + } else if (reader->name() == QStringLiteral("width")) { + video_params_.set_width(reader->readElementText().toInt()); + } else if (reader->name() == QStringLiteral("height")) { + video_params_.set_height(reader->readElementText().toInt()); + } else if (reader->name() == QStringLiteral("format")) { + video_params_.set_format(static_cast( + reader->readElementText().toInt())); + } else if (reader->name() == QStringLiteral("pixelaspect")) { + video_params_.set_pixel_aspect_ratio(rational::fromString( + reader->readElementText().toStdString())); + } else if (reader->name() == QStringLiteral("timebase")) { + video_params_.set_time_base(rational::fromString( + reader->readElementText().toStdString())); + } else if (reader->name() == QStringLiteral("divider")) { + video_params_.set_divider( + reader->readElementText().toInt()); + } else if (reader->name() == QStringLiteral("bitrate")) { + video_bit_rate_ = reader->readElementText().toLongLong(); + } else if (reader->name() == QStringLiteral("minbitrate")) { + video_min_bit_rate_ = + reader->readElementText().toLongLong(); + } else if (reader->name() == QStringLiteral("maxbitrate")) { + video_max_bit_rate_ = + reader->readElementText().toLongLong(); + } else if (reader->name() == QStringLiteral("bufsize")) { + video_buffer_size_ = reader->readElementText().toLongLong(); + } else if (reader->name() == QStringLiteral("threads")) { + video_threads_ = reader->readElementText().toInt(); + } else if (reader->name() == QStringLiteral("pixfmt")) { + video_pix_fmt_ = reader->readElementText(); + } else if (reader->name() == QStringLiteral("imgseq")) { + video_is_image_sequence_ = + reader->readElementText().toInt(); + } else if (reader->name() == QStringLiteral("color")) { + while (XMLReadNextStartElement(reader)) { + if (reader->name() == QStringLiteral("output")) { + color_transform_ = reader->readElementText(); + } else { + reader->skipCurrentElement(); + } + } + } else if (reader->name() == QStringLiteral("vscale")) { + video_scaling_method_ = static_cast( + reader->readElementText().toInt()); + } else if (reader->name() == QStringLiteral("opts")) { + while (XMLReadNextStartElement(reader)) { + if (reader->name() == QStringLiteral("entry")) { + QString key, value; + while (XMLReadNextStartElement(reader)) { + if (reader->name() == QStringLiteral("key")) { + key = reader->readElementText(); + } else if (reader->name() == + QStringLiteral("value")) { + value = reader->readElementText(); + } else { + reader->skipCurrentElement(); + } + } + set_video_option(key, value); + } else { + reader->skipCurrentElement(); + } + } + } else { + reader->skipCurrentElement(); + } + } - // HACK: Resolve bug where I forgot to serialize pixel aspect ratio - if (video_params_.pixel_aspect_ratio().isNull()) { - video_params_.set_pixel_aspect_ratio(1); - } - } else if (reader->name() == QStringLiteral("audio")) { - XMLAttributeLoop(reader, attr) { - if (attr.name() == QStringLiteral("enabled")) { - audio_enabled_ = attr.value().toInt(); - } - } + // HACK: Resolve bug where I forgot to serialize pixel aspect ratio + if (video_params_.pixel_aspect_ratio().isNull()) { + video_params_.set_pixel_aspect_ratio(1); + } + } else if (reader->name() == QStringLiteral("audio")) { + XMLAttributeLoop(reader, attr) + { + if (attr.name() == QStringLiteral("enabled")) { + audio_enabled_ = attr.value().toInt(); + } + } - while (XMLReadNextStartElement(reader)) { - if (reader->name() == QStringLiteral("codec")) { - audio_codec_ = static_cast(reader->readElementText().toInt()); - } else if (reader->name() == QStringLiteral("samplerate")) { - audio_params_.set_sample_rate(reader->readElementText().toInt()); - } else if (reader->name() == QStringLiteral("channellayout")) { - AVChannelLayout av_channel_layout; - av_channel_layout_from_mask(&av_channel_layout, reader->readElementText().toLongLong()); - audio_params_.set_channel_layout(av_channel_layout); - av_channel_layout_uninit(&av_channel_layout); - } else if (reader->name() == QStringLiteral("format")) { - audio_params_.set_format(SampleFormat::from_string(reader->readElementText().toStdString())); - } else if (reader->name() == QStringLiteral("bitrate")) { - audio_bit_rate_ = reader->readElementText().toLongLong(); - } else { - reader->skipCurrentElement(); - } - } + while (XMLReadNextStartElement(reader)) { + if (reader->name() == QStringLiteral("codec")) { + audio_codec_ = static_cast( + reader->readElementText().toInt()); + } else if (reader->name() == QStringLiteral("samplerate")) { + audio_params_.set_sample_rate( + reader->readElementText().toInt()); + } else if (reader->name() == QStringLiteral("channellayout")) { + AVChannelLayout av_channel_layout; + av_channel_layout_from_mask( + &av_channel_layout, + reader->readElementText().toLongLong()); + audio_params_.set_channel_layout(av_channel_layout); + av_channel_layout_uninit(&av_channel_layout); + } else if (reader->name() == QStringLiteral("format")) { + audio_params_.set_format(SampleFormat::from_string( + reader->readElementText().toStdString())); + } else if (reader->name() == QStringLiteral("bitrate")) { + audio_bit_rate_ = reader->readElementText().toLongLong(); + } else { + reader->skipCurrentElement(); + } + } - // HACK: Resolve bug where I forgot to serialize the audio bit rate - if (!audio_bit_rate_) { - audio_bit_rate_ = 320000; - } - } else if (reader->name() == QStringLiteral("subtitles")) { - XMLAttributeLoop(reader, attr) { - if (attr.name() == QStringLiteral("enabled")) { - subtitles_enabled_ = attr.value().toInt(); - } - } + // HACK: Resolve bug where I forgot to serialize the audio bit rate + if (!audio_bit_rate_) { + audio_bit_rate_ = 320000; + } + } else if (reader->name() == QStringLiteral("subtitles")) { + XMLAttributeLoop(reader, attr) + { + if (attr.name() == QStringLiteral("enabled")) { + subtitles_enabled_ = attr.value().toInt(); + } + } - while (XMLReadNextStartElement(reader)) { - if (reader->name() == QStringLiteral("sidecar")) { - subtitles_are_sidecar_ = reader->readElementText().toInt(); - } else if (reader->name() == QStringLiteral("sidecarformat")) { - subtitle_sidecar_fmt_ = static_cast(reader->readElementText().toInt()); - } else if (reader->name() == QStringLiteral("codec")) { - subtitles_codec_ = static_cast(reader->readElementText().toInt()); - } else { - reader->skipCurrentElement(); - } - } - } else { - reader->skipCurrentElement(); - } - } + while (XMLReadNextStartElement(reader)) { + if (reader->name() == QStringLiteral("sidecar")) { + subtitles_are_sidecar_ = reader->readElementText().toInt(); + } else if (reader->name() == QStringLiteral("sidecarformat")) { + subtitle_sidecar_fmt_ = static_cast( + reader->readElementText().toInt()); + } else if (reader->name() == QStringLiteral("codec")) { + subtitles_codec_ = static_cast( + reader->readElementText().toInt()); + } else { + reader->skipCurrentElement(); + } + } + } else { + reader->skipCurrentElement(); + } + } - return true; + return true; } } diff --git a/app/codec/encoder.h b/app/codec/encoder.h index ea66ed562..90e141d96 100644 --- a/app/codec/encoder.h +++ b/app/codec/encoder.h @@ -34,218 +34,340 @@ #include "render/subtitleparams.h" #include "render/videoparams.h" //这个代码也许是导出编码视频用的? -namespace olive { +namespace olive +{ class Encoder; using EncoderPtr = std::shared_ptr; -class EncodingParams -{ +class EncodingParams { public: - enum VideoScalingMethod { - kFit, - kStretch, - kCrop - }; + enum VideoScalingMethod { kFit, kStretch, kCrop }; - EncodingParams(); + EncodingParams(); - static QDir GetPresetPath(); - static QStringList GetListOfPresets(); + static QDir GetPresetPath(); + static QStringList GetListOfPresets(); - bool IsValid() const - { - return video_enabled_ || audio_enabled_ || subtitles_enabled_; - } + bool IsValid() const + { + return video_enabled_ || audio_enabled_ || subtitles_enabled_; + } - void SetFilename(const QString& filename) { filename_ = filename; } + void SetFilename(const QString &filename) + { + filename_ = filename; + } - void EnableVideo(const VideoParams& video_params, const ExportCodec::Codec& vcodec); - void EnableAudio(const AudioParams& audio_params, const ExportCodec::Codec &acodec); - void EnableSubtitles(const ExportCodec::Codec &scodec); - void EnableSidecarSubtitles(const ExportFormat::Format &sfmt, const ExportCodec::Codec &scodec); + void EnableVideo(const VideoParams &video_params, + const ExportCodec::Codec &vcodec); + void EnableAudio(const AudioParams &audio_params, + const ExportCodec::Codec &acodec); + void EnableSubtitles(const ExportCodec::Codec &scodec); + void EnableSidecarSubtitles(const ExportFormat::Format &sfmt, + const ExportCodec::Codec &scodec); - void DisableVideo(); - void DisableAudio(); - void DisableSubtitles(); + void DisableVideo(); + void DisableAudio(); + void DisableSubtitles(); - const ExportFormat::Format &format() const { return format_; } - void set_format(const ExportFormat::Format &format) { format_ = format; } + const ExportFormat::Format &format() const + { + return format_; + } + void set_format(const ExportFormat::Format &format) + { + format_ = format; + } - void set_video_option(const QString& key, const QString& value) { video_opts_.insert(key, value); } - void set_video_bit_rate(const int64_t& rate) { video_bit_rate_ = rate; } - void set_video_min_bit_rate(const int64_t& rate) { video_min_bit_rate_ = rate; } - void set_video_max_bit_rate(const int64_t& rate) { video_max_bit_rate_ = rate; } - void set_video_buffer_size(const int64_t& sz) { video_buffer_size_ = sz; } - void set_video_threads(const int& threads) { video_threads_ = threads; } - void set_video_pix_fmt(const QString& s) { video_pix_fmt_ = s; } - void set_video_is_image_sequence(bool s) { video_is_image_sequence_ = s; } - void set_color_transform(const ColorTransform& color_transform) { color_transform_ = color_transform; } + void set_video_option(const QString &key, const QString &value) + { + video_opts_.insert(key, value); + } + void set_video_bit_rate(const int64_t &rate) + { + video_bit_rate_ = rate; + } + void set_video_min_bit_rate(const int64_t &rate) + { + video_min_bit_rate_ = rate; + } + void set_video_max_bit_rate(const int64_t &rate) + { + video_max_bit_rate_ = rate; + } + void set_video_buffer_size(const int64_t &sz) + { + video_buffer_size_ = sz; + } + void set_video_threads(const int &threads) + { + video_threads_ = threads; + } + void set_video_pix_fmt(const QString &s) + { + video_pix_fmt_ = s; + } + void set_video_is_image_sequence(bool s) + { + video_is_image_sequence_ = s; + } + void set_color_transform(const ColorTransform &color_transform) + { + color_transform_ = color_transform; + } - const QString& filename() const { return filename_; } + const QString &filename() const + { + return filename_; + } - bool video_enabled() const { return video_enabled_; } - const ExportCodec::Codec& video_codec() const { return video_codec_; } - const VideoParams& video_params() const { return video_params_; } - const QHash& video_opts() const { return video_opts_; } - QString video_option(const QString &key) const { return video_opts_.value(key); } - bool has_video_opt(const QString &key) const { return video_opts_.contains(key); } - const int64_t& video_bit_rate() const { return video_bit_rate_; } - const int64_t& video_min_bit_rate() const { return video_min_bit_rate_; } - const int64_t& video_max_bit_rate() const { return video_max_bit_rate_; } - const int64_t& video_buffer_size() const { return video_buffer_size_; } - const int& video_threads() const { return video_threads_; } - const QString& video_pix_fmt() const { return video_pix_fmt_; } - bool video_is_image_sequence() const { return video_is_image_sequence_; } - const ColorTransform& color_transform() const { return color_transform_; } + bool video_enabled() const + { + return video_enabled_; + } + const ExportCodec::Codec &video_codec() const + { + return video_codec_; + } + const VideoParams &video_params() const + { + return video_params_; + } + const QHash &video_opts() const + { + return video_opts_; + } + QString video_option(const QString &key) const + { + return video_opts_.value(key); + } + bool has_video_opt(const QString &key) const + { + return video_opts_.contains(key); + } + const int64_t &video_bit_rate() const + { + return video_bit_rate_; + } + const int64_t &video_min_bit_rate() const + { + return video_min_bit_rate_; + } + const int64_t &video_max_bit_rate() const + { + return video_max_bit_rate_; + } + const int64_t &video_buffer_size() const + { + return video_buffer_size_; + } + const int &video_threads() const + { + return video_threads_; + } + const QString &video_pix_fmt() const + { + return video_pix_fmt_; + } + bool video_is_image_sequence() const + { + return video_is_image_sequence_; + } + const ColorTransform &color_transform() const + { + return color_transform_; + } - bool audio_enabled() const { return audio_enabled_; } - const ExportCodec::Codec &audio_codec() const { return audio_codec_; } - const AudioParams& audio_params() const { return audio_params_; } - const int64_t& audio_bit_rate() const { return audio_bit_rate_; } + bool audio_enabled() const + { + return audio_enabled_; + } + const ExportCodec::Codec &audio_codec() const + { + return audio_codec_; + } + const AudioParams &audio_params() const + { + return audio_params_; + } + const int64_t &audio_bit_rate() const + { + return audio_bit_rate_; + } - void set_audio_bit_rate(const int64_t& b) { audio_bit_rate_ = b; } + void set_audio_bit_rate(const int64_t &b) + { + audio_bit_rate_ = b; + } - bool subtitles_enabled() const { return subtitles_enabled_; } - bool subtitles_are_sidecar() const { return subtitles_are_sidecar_; } - ExportFormat::Format subtitle_sidecar_fmt() const { return subtitle_sidecar_fmt_; } - ExportCodec::Codec subtitles_codec() const { return subtitles_codec_; } + bool subtitles_enabled() const + { + return subtitles_enabled_; + } + bool subtitles_are_sidecar() const + { + return subtitles_are_sidecar_; + } + ExportFormat::Format subtitle_sidecar_fmt() const + { + return subtitle_sidecar_fmt_; + } + ExportCodec::Codec subtitles_codec() const + { + return subtitles_codec_; + } - const rational& GetExportLength() const { return export_length_; } - void SetExportLength(const rational& export_length) { export_length_ = export_length; } + const rational &GetExportLength() const + { + return export_length_; + } + void SetExportLength(const rational &export_length) + { + export_length_ = export_length; + } - bool Load(QIODevice *device); - bool Load(QXmlStreamReader *reader); + bool Load(QIODevice *device); + bool Load(QXmlStreamReader *reader); - void Save(QIODevice *device) const; - void Save(QXmlStreamWriter* writer) const; + void Save(QIODevice *device) const; + void Save(QXmlStreamWriter *writer) const; - bool has_custom_range() const { return has_custom_range_; } - const TimeRange& custom_range() const { return custom_range_; } - void set_custom_range(const TimeRange& custom_range) - { - has_custom_range_ = true; - custom_range_ = custom_range; - } + bool has_custom_range() const + { + return has_custom_range_; + } + const TimeRange &custom_range() const + { + return custom_range_; + } + void set_custom_range(const TimeRange &custom_range) + { + has_custom_range_ = true; + custom_range_ = custom_range; + } - const VideoScalingMethod& video_scaling_method() const { return video_scaling_method_; } - void set_video_scaling_method(const VideoScalingMethod& video_scaling_method) { video_scaling_method_ = video_scaling_method; } + const VideoScalingMethod &video_scaling_method() const + { + return video_scaling_method_; + } + void + set_video_scaling_method(const VideoScalingMethod &video_scaling_method) + { + video_scaling_method_ = video_scaling_method; + } - static QMatrix4x4 GenerateMatrix(VideoScalingMethod method, - int source_width, int source_height, - int dest_width, int dest_height); + static QMatrix4x4 GenerateMatrix(VideoScalingMethod method, + int source_width, int source_height, + int dest_width, int dest_height); private: - static const int kEncoderParamsVersion = 1; + static const int kEncoderParamsVersion = 1; - bool LoadV1(QXmlStreamReader *reader); + bool LoadV1(QXmlStreamReader *reader); - QString filename_; - ExportFormat::Format format_; + QString filename_; + ExportFormat::Format format_; - bool video_enabled_; - ExportCodec::Codec video_codec_; - VideoParams video_params_; - QHash video_opts_; - int64_t video_bit_rate_; - int64_t video_min_bit_rate_; - int64_t video_max_bit_rate_; - int64_t video_buffer_size_; - int video_threads_; - QString video_pix_fmt_; - bool video_is_image_sequence_; - ColorTransform color_transform_; + bool video_enabled_; + ExportCodec::Codec video_codec_; + VideoParams video_params_; + QHash video_opts_; + int64_t video_bit_rate_; + int64_t video_min_bit_rate_; + int64_t video_max_bit_rate_; + int64_t video_buffer_size_; + int video_threads_; + QString video_pix_fmt_; + bool video_is_image_sequence_; + ColorTransform color_transform_; - bool audio_enabled_; - ExportCodec::Codec audio_codec_; - AudioParams audio_params_; - int64_t audio_bit_rate_; + bool audio_enabled_; + ExportCodec::Codec audio_codec_; + AudioParams audio_params_; + int64_t audio_bit_rate_; - bool subtitles_enabled_; - bool subtitles_are_sidecar_; - ExportFormat::Format subtitle_sidecar_fmt_; - ExportCodec::Codec subtitles_codec_; + bool subtitles_enabled_; + bool subtitles_are_sidecar_; + ExportFormat::Format subtitle_sidecar_fmt_; + ExportCodec::Codec subtitles_codec_; - rational export_length_; - VideoScalingMethod video_scaling_method_; - - bool has_custom_range_; - TimeRange custom_range_; + rational export_length_; + VideoScalingMethod video_scaling_method_; + bool has_custom_range_; + TimeRange custom_range_; }; -class Encoder : public QObject -{ - Q_OBJECT +class Encoder : public QObject { + Q_OBJECT public: - Encoder(const EncodingParams& params); + Encoder(const EncodingParams ¶ms); - enum Type { - kEncoderTypeNone = -1, - kEncoderTypeFFmpeg, - kEncoderTypeOIIO - }; + enum Type { kEncoderTypeNone = -1, kEncoderTypeFFmpeg, kEncoderTypeOIIO }; - /** + /** * @brief Create a Encoder instance using a Encoder ID * * @return * * A Encoder instance or nullptr if a Decoder with this ID does not exist */ - static Encoder *CreateFromID(Type id, const EncodingParams ¶ms); + static Encoder *CreateFromID(Type id, const EncodingParams ¶ms); - static Type GetTypeFromFormat(ExportFormat::Format f); + static Type GetTypeFromFormat(ExportFormat::Format f); - static Encoder *CreateFromFormat(ExportFormat::Format f, const EncodingParams ¶ms); + static Encoder *CreateFromFormat(ExportFormat::Format f, + const EncodingParams ¶ms); - static Encoder *CreateFromParams(const EncodingParams ¶ms); + static Encoder *CreateFromParams(const EncodingParams ¶ms); - virtual QStringList GetPixelFormatsForCodec(ExportCodec::Codec c) const; - virtual std::vector GetSampleFormatsForCodec(ExportCodec::Codec c) const; + virtual QStringList GetPixelFormatsForCodec(ExportCodec::Codec c) const; + virtual std::vector + GetSampleFormatsForCodec(ExportCodec::Codec c) const; - const EncodingParams& params() const; + const EncodingParams ¶ms() const; - virtual PixelFormat GetDesiredPixelFormat() const - { - return PixelFormat::INVALID; - } + virtual PixelFormat GetDesiredPixelFormat() const + { + return PixelFormat::INVALID; + } - const QString& GetError() const - { - return error_; - } + const QString &GetError() const + { + return error_; + } - QString GetFilenameForFrame(const rational& frame); + QString GetFilenameForFrame(const rational &frame); - static int GetImageSequencePlaceholderDigitCount(const QString& filename); + static int GetImageSequencePlaceholderDigitCount(const QString &filename); - static bool FilenameContainsDigitPlaceholder(const QString &filename); - static QString FilenameRemoveDigitPlaceholder(QString filename); + static bool FilenameContainsDigitPlaceholder(const QString &filename); + static QString FilenameRemoveDigitPlaceholder(QString filename); - static const QRegularExpression kImageSequenceContainsDigits; - static const QRegularExpression kImageSequenceRemoveDigits; + static const QRegularExpression kImageSequenceContainsDigits; + static const QRegularExpression kImageSequenceRemoveDigits; public slots: - virtual bool Open() = 0; + virtual bool Open() = 0; - virtual bool WriteFrame(olive::FramePtr frame, olive::core::rational time) = 0; - virtual bool WriteAudio(const olive::SampleBuffer &audio) = 0; - virtual bool WriteSubtitle(const SubtitleBlock *sub_block) = 0; + virtual bool WriteFrame(olive::FramePtr frame, + olive::core::rational time) = 0; + virtual bool WriteAudio(const olive::SampleBuffer &audio) = 0; + virtual bool WriteSubtitle(const SubtitleBlock *sub_block) = 0; - virtual void Close() = 0; + virtual void Close() = 0; protected: - void SetError(const QString& err) - { - error_ = err; - } + void SetError(const QString &err) + { + error_ = err; + } private: - EncodingParams params_; - - QString error_; + EncodingParams params_; + QString error_; }; } diff --git a/app/codec/exportcodec.cpp b/app/codec/exportcodec.cpp index 217593d08..69d6725e3 100644 --- a/app/codec/exportcodec.cpp +++ b/app/codec/exportcodec.cpp @@ -25,115 +25,116 @@ extern "C" { #include } -namespace olive { +namespace olive +{ QString ExportCodec::GetCodecName(ExportCodec::Codec c) { - switch (c) { - case kCodecDNxHD: - return tr("DNxHD"); - case kCodecH264: - return tr("H.264"); - case kCodecH264rgb: - return tr("H.264 RGB"); - case kCodecH265: - return tr("H.265"); - case kCodecOpenEXR: - return tr("OpenEXR"); - case kCodecPNG: - return tr("PNG"); - case kCodecProRes: - return tr("ProRes"); - case kCodecCineform: - return tr("Cineform"); - case kCodecTIFF: - return tr("TIFF"); - case kCodecMP2: - return tr("MP2"); - case kCodecMP3: - return tr("MP3"); - case kCodecAAC: - return tr("AAC"); - case kCodecPCM: - return tr("PCM (Uncompressed)"); - case kCodecFLAC: - return tr("FLAC"); - case kCodecOpus: - return tr("Opus"); - case kCodecVorbis: - return tr("Vorbis"); - case kCodecVP9: - return tr("VP9"); - case kCodecAV1: - return tr("AV1"); - case kCodecSRT: - return tr("SubRip SRT"); - case kCodecCount: - break; - } + switch (c) { + case kCodecDNxHD: + return tr("DNxHD"); + case kCodecH264: + return tr("H.264"); + case kCodecH264rgb: + return tr("H.264 RGB"); + case kCodecH265: + return tr("H.265"); + case kCodecOpenEXR: + return tr("OpenEXR"); + case kCodecPNG: + return tr("PNG"); + case kCodecProRes: + return tr("ProRes"); + case kCodecCineform: + return tr("Cineform"); + case kCodecTIFF: + return tr("TIFF"); + case kCodecMP2: + return tr("MP2"); + case kCodecMP3: + return tr("MP3"); + case kCodecAAC: + return tr("AAC"); + case kCodecPCM: + return tr("PCM (Uncompressed)"); + case kCodecFLAC: + return tr("FLAC"); + case kCodecOpus: + return tr("Opus"); + case kCodecVorbis: + return tr("Vorbis"); + case kCodecVP9: + return tr("VP9"); + case kCodecAV1: + return tr("AV1"); + case kCodecSRT: + return tr("SubRip SRT"); + case kCodecCount: + break; + } - return tr("Unknown"); + return tr("Unknown"); } bool ExportCodec::IsCodecAStillImage(ExportCodec::Codec c) { - switch (c) { - case kCodecDNxHD: - case kCodecH264: - case kCodecH264rgb: - case kCodecH265: - case kCodecProRes: - case kCodecCineform: - case kCodecMP2: - case kCodecMP3: - case kCodecAAC: - case kCodecPCM: - case kCodecVorbis: - case kCodecOpus: - case kCodecFLAC: - case kCodecVP9: - case kCodecAV1: - case kCodecSRT: - return false; - case kCodecOpenEXR: - case kCodecPNG: - case kCodecTIFF: - return true; - case kCodecCount: - break; - } + switch (c) { + case kCodecDNxHD: + case kCodecH264: + case kCodecH264rgb: + case kCodecH265: + case kCodecProRes: + case kCodecCineform: + case kCodecMP2: + case kCodecMP3: + case kCodecAAC: + case kCodecPCM: + case kCodecVorbis: + case kCodecOpus: + case kCodecFLAC: + case kCodecVP9: + case kCodecAV1: + case kCodecSRT: + return false; + case kCodecOpenEXR: + case kCodecPNG: + case kCodecTIFF: + return true; + case kCodecCount: + break; + } - return false; + return false; } bool ExportCodec::IsCodecLossless(Codec c) { - switch (c) { - case kCodecPCM: - case kCodecFLAC: - return true; - case kCodecDNxHD: - case kCodecH264: - case kCodecH264rgb: - case kCodecH265: - case kCodecProRes: - case kCodecCineform: - case kCodecMP2: - case kCodecMP3: - case kCodecAAC: - case kCodecVorbis: - case kCodecOpus: - case kCodecVP9: - case kCodecAV1: - case kCodecSRT: - case kCodecOpenEXR: - case kCodecPNG: - case kCodecTIFF: - case kCodecCount: - break; - } + switch (c) { + case kCodecPCM: + case kCodecFLAC: + return true; + case kCodecDNxHD: + case kCodecH264: + case kCodecH264rgb: + case kCodecH265: + case kCodecProRes: + case kCodecCineform: + case kCodecMP2: + case kCodecMP3: + case kCodecAAC: + case kCodecVorbis: + case kCodecOpus: + case kCodecVP9: + case kCodecAV1: + case kCodecSRT: + case kCodecOpenEXR: + case kCodecPNG: + case kCodecTIFF: + case kCodecCount: + break; + } - return false; + return false; } } diff --git a/app/codec/exportcodec.h b/app/codec/exportcodec.h index c78085986..c51711647 100644 --- a/app/codec/exportcodec.h +++ b/app/codec/exportcodec.h @@ -27,43 +27,42 @@ #include "common/define.h" #include "render/subtitleparams.h" -namespace olive { - -class ExportCodec : public QObject +namespace olive { - Q_OBJECT + +class ExportCodec : public QObject { + Q_OBJECT public: - // Only append to this list (never insert) because indexes are used in serialized files - enum Codec { - kCodecDNxHD, - kCodecH264, - kCodecH264rgb, - kCodecH265, - kCodecOpenEXR, - kCodecPNG, - kCodecProRes, - kCodecCineform, - kCodecTIFF, - kCodecVP9, - kCodecMP2, - kCodecMP3, - kCodecAAC, - kCodecPCM, - kCodecOpus, - kCodecVorbis, - kCodecFLAC, - kCodecSRT, - kCodecAV1, + // Only append to this list (never insert) because indexes are used in serialized files + enum Codec { + kCodecDNxHD, + kCodecH264, + kCodecH264rgb, + kCodecH265, + kCodecOpenEXR, + kCodecPNG, + kCodecProRes, + kCodecCineform, + kCodecTIFF, + kCodecVP9, + kCodecMP2, + kCodecMP3, + kCodecAAC, + kCodecPCM, + kCodecOpus, + kCodecVorbis, + kCodecFLAC, + kCodecSRT, + kCodecAV1, - kCodecCount - }; + kCodecCount + }; - static QString GetCodecName(Codec c); + static QString GetCodecName(Codec c); - static bool IsCodecAStillImage(Codec c); - - static bool IsCodecLossless(Codec c); + static bool IsCodecAStillImage(Codec c); + static bool IsCodecLossless(Codec c); }; } diff --git a/app/codec/exportformat.cpp b/app/codec/exportformat.cpp index db8fb8bf8..5eb2b9b8a 100644 --- a/app/codec/exportformat.cpp +++ b/app/codec/exportformat.cpp @@ -22,214 +22,227 @@ #include "encoder.h" -namespace olive { +namespace olive +{ QString ExportFormat::GetName(olive::ExportFormat::Format f) { - switch (f) { - case kFormatDNxHD: - return tr("DNxHD"); - case kFormatMatroska: - return tr("Matroska Video"); - case kFormatMPEG4Video: - return tr("MPEG-4 Video"); - case kFormatMPEG4Audio: - return tr("MPEG-4 Audio"); - case kFormatOpenEXR: - return tr("OpenEXR"); - case kFormatPNG: - return tr("PNG"); - case kFormatTIFF: - return tr("TIFF"); - case kFormatQuickTime: - return tr("QuickTime"); - case kFormatWAV: - return tr("Wave Audio"); - case kFormatAIFF: - return tr("AIFF"); - case kFormatMP3: - return tr("MP3"); - case kFormatFLAC: - return tr("FLAC"); - case kFormatOgg: - return tr("Ogg"); - case kFormatWebM: - return tr("WebM"); - case kFormatSRT: - return tr("SubRip SRT"); + switch (f) { + case kFormatDNxHD: + return tr("DNxHD"); + case kFormatMatroska: + return tr("Matroska Video"); + case kFormatMPEG4Video: + return tr("MPEG-4 Video"); + case kFormatMPEG4Audio: + return tr("MPEG-4 Audio"); + case kFormatOpenEXR: + return tr("OpenEXR"); + case kFormatPNG: + return tr("PNG"); + case kFormatTIFF: + return tr("TIFF"); + case kFormatQuickTime: + return tr("QuickTime"); + case kFormatWAV: + return tr("Wave Audio"); + case kFormatAIFF: + return tr("AIFF"); + case kFormatMP3: + return tr("MP3"); + case kFormatFLAC: + return tr("FLAC"); + case kFormatOgg: + return tr("Ogg"); + case kFormatWebM: + return tr("WebM"); + case kFormatSRT: + return tr("SubRip SRT"); - case kFormatCount: - break; - } + case kFormatCount: + break; + } - return tr("Unknown"); + return tr("Unknown"); } QString ExportFormat::GetExtension(ExportFormat::Format f) { - switch (f) { - case kFormatDNxHD: - return QStringLiteral("mxf"); - case kFormatMatroska: - return QStringLiteral("mkv"); - case kFormatMPEG4Video: - return QStringLiteral("mp4"); - case kFormatMPEG4Audio: - return QStringLiteral("m4a"); - case kFormatOpenEXR: - return QStringLiteral("exr"); - case kFormatPNG: - return QStringLiteral("png"); - case kFormatTIFF: - return QStringLiteral("tiff"); - case kFormatQuickTime: - return QStringLiteral("mov"); - case kFormatWAV: - return QStringLiteral("wav"); - case kFormatAIFF: - return QStringLiteral("aiff"); - case kFormatMP3: - return QStringLiteral("mp3"); - case kFormatFLAC: - return QStringLiteral("flac"); - case kFormatOgg: - return QStringLiteral("ogg"); - case kFormatWebM: - return QStringLiteral("webm"); - case kFormatSRT: - return QStringLiteral("srt"); - case kFormatCount: - break; - } + switch (f) { + case kFormatDNxHD: + return QStringLiteral("mxf"); + case kFormatMatroska: + return QStringLiteral("mkv"); + case kFormatMPEG4Video: + return QStringLiteral("mp4"); + case kFormatMPEG4Audio: + return QStringLiteral("m4a"); + case kFormatOpenEXR: + return QStringLiteral("exr"); + case kFormatPNG: + return QStringLiteral("png"); + case kFormatTIFF: + return QStringLiteral("tiff"); + case kFormatQuickTime: + return QStringLiteral("mov"); + case kFormatWAV: + return QStringLiteral("wav"); + case kFormatAIFF: + return QStringLiteral("aiff"); + case kFormatMP3: + return QStringLiteral("mp3"); + case kFormatFLAC: + return QStringLiteral("flac"); + case kFormatOgg: + return QStringLiteral("ogg"); + case kFormatWebM: + return QStringLiteral("webm"); + case kFormatSRT: + return QStringLiteral("srt"); + case kFormatCount: + break; + } - return QString(); + return QString(); } QList ExportFormat::GetVideoCodecs(ExportFormat::Format f) { - switch (f) { - case kFormatDNxHD: - return {ExportCodec::kCodecDNxHD}; - case kFormatMatroska: - return {ExportCodec::kCodecH264, ExportCodec::kCodecH264rgb, ExportCodec::kCodecH265, ExportCodec::kCodecVP9}; - case kFormatMPEG4Video: - return {ExportCodec::kCodecH264, ExportCodec::kCodecH264rgb, ExportCodec::kCodecH265}; - case kFormatOpenEXR: - return {ExportCodec::kCodecOpenEXR}; - case kFormatPNG: - return {ExportCodec::kCodecPNG}; - case kFormatTIFF: - return {ExportCodec::kCodecTIFF}; - case kFormatQuickTime: - return {ExportCodec::kCodecH264, ExportCodec::kCodecH264rgb, ExportCodec::kCodecH265, ExportCodec::kCodecProRes, ExportCodec::kCodecCineform}; - case kFormatWebM: - return {ExportCodec::kCodecAV1, ExportCodec::kCodecVP9}; - case kFormatOgg: - case kFormatWAV: - case kFormatMPEG4Audio: - case kFormatAIFF: - case kFormatMP3: - case kFormatFLAC: - case kFormatSRT: - case kFormatCount: - break; - } + switch (f) { + case kFormatDNxHD: + return { ExportCodec::kCodecDNxHD }; + case kFormatMatroska: + return { ExportCodec::kCodecH264, ExportCodec::kCodecH264rgb, + ExportCodec::kCodecH265, ExportCodec::kCodecVP9 }; + case kFormatMPEG4Video: + return { ExportCodec::kCodecH264, ExportCodec::kCodecH264rgb, + ExportCodec::kCodecH265 }; + case kFormatOpenEXR: + return { ExportCodec::kCodecOpenEXR }; + case kFormatPNG: + return { ExportCodec::kCodecPNG }; + case kFormatTIFF: + return { ExportCodec::kCodecTIFF }; + case kFormatQuickTime: + return { ExportCodec::kCodecH264, ExportCodec::kCodecH264rgb, + ExportCodec::kCodecH265, ExportCodec::kCodecProRes, + ExportCodec::kCodecCineform }; + case kFormatWebM: + return { ExportCodec::kCodecAV1, ExportCodec::kCodecVP9 }; + case kFormatOgg: + case kFormatWAV: + case kFormatMPEG4Audio: + case kFormatAIFF: + case kFormatMP3: + case kFormatFLAC: + case kFormatSRT: + case kFormatCount: + break; + } - return {}; + return {}; } QList ExportFormat::GetAudioCodecs(ExportFormat::Format f) { - switch (f) { - // Video/audio formats - case kFormatDNxHD: - return {ExportCodec::kCodecPCM}; - case kFormatMatroska: - return {ExportCodec::kCodecAAC, ExportCodec::kCodecMP2, ExportCodec::kCodecMP3, ExportCodec::kCodecPCM, ExportCodec::kCodecVorbis, ExportCodec::kCodecOpus, ExportCodec::kCodecFLAC}; - case kFormatMPEG4Video: - case kFormatMPEG4Audio: - return {ExportCodec::kCodecAAC, ExportCodec::kCodecMP2, ExportCodec::kCodecMP3}; - case kFormatQuickTime: - return {ExportCodec::kCodecAAC, ExportCodec::kCodecMP2, ExportCodec::kCodecMP3, ExportCodec::kCodecPCM}; - case kFormatWebM: - return {ExportCodec::kCodecOpus, ExportCodec::kCodecAAC, ExportCodec::kCodecMP2, ExportCodec::kCodecMP3, ExportCodec::kCodecPCM, ExportCodec::kCodecVorbis}; + switch (f) { + // Video/audio formats + case kFormatDNxHD: + return { ExportCodec::kCodecPCM }; + case kFormatMatroska: + return { ExportCodec::kCodecAAC, ExportCodec::kCodecMP2, + ExportCodec::kCodecMP3, ExportCodec::kCodecPCM, + ExportCodec::kCodecVorbis, ExportCodec::kCodecOpus, + ExportCodec::kCodecFLAC }; + case kFormatMPEG4Video: + case kFormatMPEG4Audio: + return { ExportCodec::kCodecAAC, ExportCodec::kCodecMP2, + ExportCodec::kCodecMP3 }; + case kFormatQuickTime: + return { ExportCodec::kCodecAAC, ExportCodec::kCodecMP2, + ExportCodec::kCodecMP3, ExportCodec::kCodecPCM }; + case kFormatWebM: + return { ExportCodec::kCodecOpus, ExportCodec::kCodecAAC, + ExportCodec::kCodecMP2, ExportCodec::kCodecMP3, + ExportCodec::kCodecPCM, ExportCodec::kCodecVorbis }; - // Audio only formats - case kFormatWAV: - return {ExportCodec::kCodecPCM}; - case kFormatAIFF: - return {ExportCodec::kCodecPCM}; - case kFormatMP3: - return {ExportCodec::kCodecMP3}; - case kFormatFLAC: - return {ExportCodec::kCodecFLAC}; - case kFormatOgg: - return {ExportCodec::kCodecOpus, ExportCodec::kCodecVorbis, ExportCodec::kCodecPCM}; + // Audio only formats + case kFormatWAV: + return { ExportCodec::kCodecPCM }; + case kFormatAIFF: + return { ExportCodec::kCodecPCM }; + case kFormatMP3: + return { ExportCodec::kCodecMP3 }; + case kFormatFLAC: + return { ExportCodec::kCodecFLAC }; + case kFormatOgg: + return { ExportCodec::kCodecOpus, ExportCodec::kCodecVorbis, + ExportCodec::kCodecPCM }; - // Video only formats - case kFormatOpenEXR: - case kFormatPNG: - case kFormatTIFF: - case kFormatSRT: - case kFormatCount: - break; + // Video only formats + case kFormatOpenEXR: + case kFormatPNG: + case kFormatTIFF: + case kFormatSRT: + case kFormatCount: + break; + } - } - - return {}; + return {}; } QList ExportFormat::GetSubtitleCodecs(Format f) { - switch (f) { - case kFormatDNxHD: - case kFormatMPEG4Video: - case kFormatMPEG4Audio: - case kFormatOpenEXR: - case kFormatQuickTime: - case kFormatPNG: - case kFormatTIFF: - case kFormatWAV: - case kFormatAIFF: - case kFormatMP3: - case kFormatFLAC: - case kFormatOgg: - case kFormatWebM: - case kFormatCount: - break; - case kFormatMatroska: - case kFormatSRT: - return {ExportCodec::kCodecSRT}; - } + switch (f) { + case kFormatDNxHD: + case kFormatMPEG4Video: + case kFormatMPEG4Audio: + case kFormatOpenEXR: + case kFormatQuickTime: + case kFormatPNG: + case kFormatTIFF: + case kFormatWAV: + case kFormatAIFF: + case kFormatMP3: + case kFormatFLAC: + case kFormatOgg: + case kFormatWebM: + case kFormatCount: + break; + case kFormatMatroska: + case kFormatSRT: + return { ExportCodec::kCodecSRT }; + } - return {}; + return {}; } -QStringList ExportFormat::GetPixelFormatsForCodec(ExportFormat::Format f, ExportCodec::Codec c) +QStringList ExportFormat::GetPixelFormatsForCodec(ExportFormat::Format f, + ExportCodec::Codec c) { - Encoder* e = Encoder::CreateFromFormat(f, EncodingParams()); - QStringList list; + Encoder *e = Encoder::CreateFromFormat(f, EncodingParams()); + QStringList list; - if (e) { - list = e->GetPixelFormatsForCodec(c); - delete e; - } + if (e) { + list = e->GetPixelFormatsForCodec(c); + delete e; + } - return list; + return list; } -std::vector ExportFormat::GetSampleFormatsForCodec(Format format, ExportCodec::Codec c) +std::vector +ExportFormat::GetSampleFormatsForCodec(Format format, ExportCodec::Codec c) { - std::vector f; - Encoder *e = Encoder::CreateFromFormat(format, EncodingParams()); + std::vector f; + Encoder *e = Encoder::CreateFromFormat(format, EncodingParams()); - if (e) { - f = e->GetSampleFormatsForCodec(c); - delete e; - } + if (e) { + f = e->GetSampleFormatsForCodec(c); + delete e; + } - - return f; + return f; } } diff --git a/app/codec/exportformat.h b/app/codec/exportformat.h index 1ede4ab49..d5af58777 100644 --- a/app/codec/exportformat.h +++ b/app/codec/exportformat.h @@ -27,42 +27,42 @@ #include "common/define.h" #include "exportcodec.h" -namespace olive { - -class ExportFormat : public QObject +namespace olive { - Q_OBJECT + +class ExportFormat : public QObject { + Q_OBJECT public: - // Only append to this list (never insert) because indexes are used in serialized files - enum Format { - kFormatDNxHD, - kFormatMatroska, - kFormatMPEG4Video, - kFormatOpenEXR, - kFormatQuickTime, - kFormatPNG, - kFormatTIFF, - kFormatWAV, - kFormatAIFF, - kFormatMP3, - kFormatFLAC, - kFormatOgg, - kFormatWebM, - kFormatSRT, - kFormatMPEG4Audio, + // Only append to this list (never insert) because indexes are used in serialized files + enum Format { + kFormatDNxHD, + kFormatMatroska, + kFormatMPEG4Video, + kFormatOpenEXR, + kFormatQuickTime, + kFormatPNG, + kFormatTIFF, + kFormatWAV, + kFormatAIFF, + kFormatMP3, + kFormatFLAC, + kFormatOgg, + kFormatWebM, + kFormatSRT, + kFormatMPEG4Audio, - kFormatCount - }; + kFormatCount + }; - static QString GetName(Format f); - static QString GetExtension(Format f); - static QList GetVideoCodecs(ExportFormat::Format f); - static QList GetAudioCodecs(ExportFormat::Format f); - static QList GetSubtitleCodecs(ExportFormat::Format f); - - static QStringList GetPixelFormatsForCodec(Format f, ExportCodec::Codec c); - static std::vector GetSampleFormatsForCodec(Format f, ExportCodec::Codec c); + static QString GetName(Format f); + static QString GetExtension(Format f); + static QList GetVideoCodecs(ExportFormat::Format f); + static QList GetAudioCodecs(ExportFormat::Format f); + static QList GetSubtitleCodecs(ExportFormat::Format f); + static QStringList GetPixelFormatsForCodec(Format f, ExportCodec::Codec c); + static std::vector + GetSampleFormatsForCodec(Format f, ExportCodec::Codec c); }; } diff --git a/app/codec/ffmpeg/ffmpegdecoder.cpp b/app/codec/ffmpeg/ffmpegdecoder.cpp index 035793f11..e963e8e64 100644 --- a/app/codec/ffmpeg/ffmpegdecoder.cpp +++ b/app/codec/ffmpeg/ffmpegdecoder.cpp @@ -45,1153 +45,1229 @@ extern "C" { #include "render/renderer.h" #include "render/subtitleparams.h" -namespace olive { +namespace olive +{ QVariant Yuv2RgbShader; QVariant DeinterlaceShader; -FFmpegDecoder::FFmpegDecoder() : - sws_ctx_(nullptr), - working_packet_(nullptr), - cache_at_zero_(false), - cache_at_eof_(false) +FFmpegDecoder::FFmpegDecoder() + : sws_ctx_(nullptr) + , working_packet_(nullptr) + , cache_at_zero_(false) + , cache_at_eof_(false) { } bool FFmpegDecoder::OpenInternal() { - if (instance_.Open(stream().filename().toUtf8(), stream().stream())) { - AVStream* s = instance_.avstream(); + if (instance_.Open(stream().filename().toUtf8(), stream().stream())) { + AVStream *s = instance_.avstream(); - // Store one second in the source's timebase - second_ts_ = qRound64(av_q2d(av_inv_q(s->time_base))); + // Store one second in the source's timebase + second_ts_ = qRound64(av_q2d(av_inv_q(s->time_base))); - working_packet_ = av_packet_alloc(); - return true; - } + working_packet_ = av_packet_alloc(); + return true; + } - return false; + return false; } -TexturePtr FFmpegDecoder::ProcessFrameIntoTexture(AVFramePtr f, const RetrieveVideoParams &p, const AVFramePtr original) +TexturePtr FFmpegDecoder::ProcessFrameIntoTexture(AVFramePtr f, + const RetrieveVideoParams &p, + const AVFramePtr original) { - // Determine native format - AVPixelFormat ideal_fmt = FFmpegUtils::GetCompatiblePixelFormat(static_cast(f->format)); - PixelFormat native_fmt = GetNativePixelFormat(ideal_fmt); - int native_channels = GetNativeChannelCount(ideal_fmt); + // Determine native format + AVPixelFormat ideal_fmt = FFmpegUtils::GetCompatiblePixelFormat( + static_cast(f->format)); + PixelFormat native_fmt = GetNativePixelFormat(ideal_fmt); + int native_channels = GetNativeChannelCount(ideal_fmt); - // Set up video params - VideoParams vp(original->width, - original->height, - native_fmt, - native_channels, - av_guess_sample_aspect_ratio(instance_.fmt_ctx(), instance_.avstream(), nullptr), - VideoParams::kInterlaceNone, - p.divider); + // Set up video params + VideoParams vp(original->width, original->height, native_fmt, + native_channels, + av_guess_sample_aspect_ratio(instance_.fmt_ctx(), + instance_.avstream(), nullptr), + VideoParams::kInterlaceNone, p.divider); - // Create texture - TexturePtr tex = p.renderer->CreateTexture(vp); + // Create texture + TexturePtr tex = p.renderer->CreateTexture(vp); - switch (f->format) { - case AV_PIX_FMT_YUV420P: - case AV_PIX_FMT_YUV422P: - case AV_PIX_FMT_YUV444P: - case AV_PIX_FMT_YUV420P10LE: - case AV_PIX_FMT_YUV422P10LE: - case AV_PIX_FMT_YUV444P10LE: - case AV_PIX_FMT_YUV420P12LE: - case AV_PIX_FMT_YUV422P12LE: - case AV_PIX_FMT_YUV444P12LE: - { - // Run through YUV to RGB shader - if (Yuv2RgbShader.isNull()) { - // Compile shader - Yuv2RgbShader = p.renderer->CreateNativeShader(ShaderCode(FileFunctions::ReadFileAsString(QStringLiteral(":/shaders/yuv2rgb.frag")))); - if (Yuv2RgbShader.isNull()) { - return nullptr; - } - } + switch (f->format) { + case AV_PIX_FMT_YUV420P: + case AV_PIX_FMT_YUV422P: + case AV_PIX_FMT_YUV444P: + case AV_PIX_FMT_YUV420P10LE: + case AV_PIX_FMT_YUV422P10LE: + case AV_PIX_FMT_YUV444P10LE: + case AV_PIX_FMT_YUV420P12LE: + case AV_PIX_FMT_YUV422P12LE: + case AV_PIX_FMT_YUV444P12LE: { + // Run through YUV to RGB shader + if (Yuv2RgbShader.isNull()) { + // Compile shader + Yuv2RgbShader = p.renderer->CreateNativeShader( + ShaderCode(FileFunctions::ReadFileAsString( + QStringLiteral(":/shaders/yuv2rgb.frag")))); + if (Yuv2RgbShader.isNull()) { + return nullptr; + } + } - int px_size; - int bits_per_pixel; - switch (f->format) { - case AV_PIX_FMT_YUV420P: - case AV_PIX_FMT_YUV422P: - case AV_PIX_FMT_YUV444P: - default: - px_size = 1; - bits_per_pixel = 8; - break; - case AV_PIX_FMT_YUV420P10LE: - case AV_PIX_FMT_YUV422P10LE: - case AV_PIX_FMT_YUV444P10LE: - px_size = 2; - bits_per_pixel = 10; - break; - case AV_PIX_FMT_YUV420P12LE: - case AV_PIX_FMT_YUV422P12LE: - case AV_PIX_FMT_YUV444P12LE: - px_size = 2; - bits_per_pixel = 12; - break; - } + int px_size; + int bits_per_pixel; + switch (f->format) { + case AV_PIX_FMT_YUV420P: + case AV_PIX_FMT_YUV422P: + case AV_PIX_FMT_YUV444P: + default: + px_size = 1; + bits_per_pixel = 8; + break; + case AV_PIX_FMT_YUV420P10LE: + case AV_PIX_FMT_YUV422P10LE: + case AV_PIX_FMT_YUV444P10LE: + px_size = 2; + bits_per_pixel = 10; + break; + case AV_PIX_FMT_YUV420P12LE: + case AV_PIX_FMT_YUV422P12LE: + case AV_PIX_FMT_YUV444P12LE: + px_size = 2; + bits_per_pixel = 12; + break; + } - AVFrame *hw_in = f.get(); + AVFrame *hw_in = f.get(); - VideoParams plane_params = vp; - plane_params.set_channel_count(1); - plane_params.set_format(native_fmt); + VideoParams plane_params = vp; + plane_params.set_channel_count(1); + plane_params.set_format(native_fmt); - TexturePtr y_plane = p.renderer->CreateTexture(plane_params, hw_in->data[0], hw_in->linesize[0] / px_size); + TexturePtr y_plane = p.renderer->CreateTexture( + plane_params, hw_in->data[0], hw_in->linesize[0] / px_size); - switch (f->format) { - case AV_PIX_FMT_YUV420P: - case AV_PIX_FMT_YUV422P: - case AV_PIX_FMT_YUV420P10LE: - case AV_PIX_FMT_YUV422P10LE: - case AV_PIX_FMT_YUV420P12LE: - case AV_PIX_FMT_YUV422P12LE: - plane_params.set_width(plane_params.width()/2); - break; - } + switch (f->format) { + case AV_PIX_FMT_YUV420P: + case AV_PIX_FMT_YUV422P: + case AV_PIX_FMT_YUV420P10LE: + case AV_PIX_FMT_YUV422P10LE: + case AV_PIX_FMT_YUV420P12LE: + case AV_PIX_FMT_YUV422P12LE: + plane_params.set_width(plane_params.width() / 2); + break; + } - switch (f->format) { - case AV_PIX_FMT_YUV420P: - case AV_PIX_FMT_YUV420P10LE: - case AV_PIX_FMT_YUV420P12LE: - plane_params.set_height(plane_params.height()/2); - break; - } + switch (f->format) { + case AV_PIX_FMT_YUV420P: + case AV_PIX_FMT_YUV420P10LE: + case AV_PIX_FMT_YUV420P12LE: + plane_params.set_height(plane_params.height() / 2); + break; + } - TexturePtr u_plane = p.renderer->CreateTexture(plane_params, hw_in->data[1], hw_in->linesize[1] / px_size); - TexturePtr v_plane = p.renderer->CreateTexture(plane_params, hw_in->data[2], hw_in->linesize[2] / px_size); + TexturePtr u_plane = p.renderer->CreateTexture( + plane_params, hw_in->data[1], hw_in->linesize[1] / px_size); + TexturePtr v_plane = p.renderer->CreateTexture( + plane_params, hw_in->data[2], hw_in->linesize[2] / px_size); - ShaderJob job; - job.Insert(QStringLiteral("y_channel"), NodeValue(NodeValue::kTexture, QVariant::fromValue(y_plane))); - job.Insert(QStringLiteral("u_channel"), NodeValue(NodeValue::kTexture, QVariant::fromValue(u_plane))); - job.Insert(QStringLiteral("v_channel"), NodeValue(NodeValue::kTexture, QVariant::fromValue(v_plane))); - job.Insert(QStringLiteral("bits_per_pixel"), NodeValue(NodeValue::kInt, bits_per_pixel)); - job.Insert(QStringLiteral("full_range"), NodeValue(NodeValue::kBoolean, hw_in->color_range == AVCOL_RANGE_JPEG)); + ShaderJob job; + job.Insert(QStringLiteral("y_channel"), + NodeValue(NodeValue::kTexture, + QVariant::fromValue(y_plane))); + job.Insert(QStringLiteral("u_channel"), + NodeValue(NodeValue::kTexture, + QVariant::fromValue(u_plane))); + job.Insert(QStringLiteral("v_channel"), + NodeValue(NodeValue::kTexture, + QVariant::fromValue(v_plane))); + job.Insert(QStringLiteral("bits_per_pixel"), + NodeValue(NodeValue::kInt, bits_per_pixel)); + job.Insert(QStringLiteral("full_range"), + NodeValue(NodeValue::kBoolean, + hw_in->color_range == AVCOL_RANGE_JPEG)); - const int *yuv_coeffs = sws_getCoefficients(FFmpegUtils::GetSwsColorspaceFromAVColorSpace(hw_in->colorspace)); - job.Insert(QStringLiteral("yuv_crv"), NodeValue(NodeValue::kFloat, yuv_coeffs[0]/65536.0)); - job.Insert(QStringLiteral("yuv_cgu"), NodeValue(NodeValue::kFloat, yuv_coeffs[2]/65536.0)); - job.Insert(QStringLiteral("yuv_cgv"), NodeValue(NodeValue::kFloat, yuv_coeffs[3]/65536.0)); - job.Insert(QStringLiteral("yuv_cbu"), NodeValue(NodeValue::kFloat, yuv_coeffs[1]/65536.0)); + const int *yuv_coeffs = sws_getCoefficients( + FFmpegUtils::GetSwsColorspaceFromAVColorSpace(hw_in->colorspace)); + job.Insert(QStringLiteral("yuv_crv"), + NodeValue(NodeValue::kFloat, yuv_coeffs[0] / 65536.0)); + job.Insert(QStringLiteral("yuv_cgu"), + NodeValue(NodeValue::kFloat, yuv_coeffs[2] / 65536.0)); + job.Insert(QStringLiteral("yuv_cgv"), + NodeValue(NodeValue::kFloat, yuv_coeffs[3] / 65536.0)); + job.Insert(QStringLiteral("yuv_cbu"), + NodeValue(NodeValue::kFloat, yuv_coeffs[1] / 65536.0)); - tex = p.renderer->CreateTexture(vp); - p.renderer->BlitToTexture(Yuv2RgbShader, job, tex.get(), false); - break; - } - case AV_PIX_FMT_RGBA: - case AV_PIX_FMT_RGBA64LE: - // RGBA can be uploaded directly to the texture - tex->Upload(f->data[0], f->linesize[0] / vp.GetBytesPerPixel()); - break; - } + tex = p.renderer->CreateTexture(vp); + p.renderer->BlitToTexture(Yuv2RgbShader, job, tex.get(), false); + break; + } + case AV_PIX_FMT_RGBA: + case AV_PIX_FMT_RGBA64LE: + // RGBA can be uploaded directly to the texture + tex->Upload(f->data[0], f->linesize[0] / vp.GetBytesPerPixel()); + break; + } - // Deinterlace if necessary - if (p.src_interlacing != VideoParams::kInterlaceNone) { - if (DeinterlaceShader.isNull()) { - // Compile shader - DeinterlaceShader = p.renderer->CreateNativeShader(ShaderCode(FileFunctions::ReadFileAsString(QStringLiteral(":/shaders/deinterlace2.frag")))); - if (DeinterlaceShader.isNull()) { - return nullptr; - } - } + // Deinterlace if necessary + if (p.src_interlacing != VideoParams::kInterlaceNone) { + if (DeinterlaceShader.isNull()) { + // Compile shader + DeinterlaceShader = p.renderer->CreateNativeShader( + ShaderCode(FileFunctions::ReadFileAsString( + QStringLiteral(":/shaders/deinterlace2.frag")))); + if (DeinterlaceShader.isNull()) { + return nullptr; + } + } - rational frame_rate_tb = av_guess_frame_rate(instance_.fmt_ctx(), instance_.avstream(), original.get()); + rational frame_rate_tb = av_guess_frame_rate( + instance_.fmt_ctx(), instance_.avstream(), original.get()); - // Double frame rate for interlaced fields - frame_rate_tb *= 2; + // Double frame rate for interlaced fields + frame_rate_tb *= 2; - // Flip frame rate so it can be used as a timebase - frame_rate_tb.flip(); + // Flip frame rate so it can be used as a timebase + frame_rate_tb.flip(); - int64_t req = Timecode::time_to_timestamp(p.time + rational(instance_.fmt_ctx()->start_time, AV_TIME_BASE), frame_rate_tb); - int64_t frm = Timecode::rescale_timestamp(original->pts, instance_.avstream()->time_base, frame_rate_tb); + int64_t req = Timecode::time_to_timestamp( + p.time + rational(instance_.fmt_ctx()->start_time, AV_TIME_BASE), + frame_rate_tb); + int64_t frm = Timecode::rescale_timestamp( + original->pts, instance_.avstream()->time_base, frame_rate_tb); - bool first = (req == frm); - bool top_first = (p.src_interlacing == VideoParams::kInterlacedTopFirst); + bool first = (req == frm); + bool top_first = + (p.src_interlacing == VideoParams::kInterlacedTopFirst); - int interlacing = (first == top_first) ? 1 : 2; + int interlacing = (first == top_first) ? 1 : 2; - TexturePtr deinterlaced = p.renderer->CreateTexture(tex->params()); + TexturePtr deinterlaced = p.renderer->CreateTexture(tex->params()); - ShaderJob job; - job.Insert(QStringLiteral("ove_maintex"), NodeValue(NodeValue::kTexture, tex)); - job.Insert(QStringLiteral("interlacing"), NodeValue(NodeValue::kInt, interlacing)); - job.Insert(QStringLiteral("pixel_height"), NodeValue(NodeValue::kInt, original->height)); + ShaderJob job; + job.Insert(QStringLiteral("ove_maintex"), + NodeValue(NodeValue::kTexture, tex)); + job.Insert(QStringLiteral("interlacing"), + NodeValue(NodeValue::kInt, interlacing)); + job.Insert(QStringLiteral("pixel_height"), + NodeValue(NodeValue::kInt, original->height)); - p.renderer->BlitToTexture(DeinterlaceShader, job, deinterlaced.get(), false); + p.renderer->BlitToTexture(DeinterlaceShader, job, deinterlaced.get(), + false); - tex = deinterlaced; - } + tex = deinterlaced; + } - return tex; + return tex; } TexturePtr FFmpegDecoder::RetrieveVideoInternal(const RetrieveVideoParams &p) { - if (AVFramePtr f = RetrieveFrame(p.time, p.cancelled)) { - if (p.cancelled && p.cancelled->IsCancelled()) { - return nullptr; - } + if (AVFramePtr f = RetrieveFrame(p.time, p.cancelled)) { + if (p.cancelled && p.cancelled->IsCancelled()) { + return nullptr; + } - AVFramePtr original = f; + AVFramePtr original = f; - // Disregard "JPEG" pixel formats because we allow the user to override that - f->format = FFmpegUtils::ConvertJPEGSpaceToRegularSpace(static_cast(f->format)); + // Disregard "JPEG" pixel formats because we allow the user to override that + f->format = FFmpegUtils::ConvertJPEGSpaceToRegularSpace( + static_cast(f->format)); - // Force frame's color range to whatever it's set to in Olive - f->color_range = p.force_range == VideoParams::kColorRangeFull ? AVCOL_RANGE_JPEG : AVCOL_RANGE_MPEG; + // Force frame's color range to whatever it's set to in Olive + f->color_range = p.force_range == VideoParams::kColorRangeFull ? + AVCOL_RANGE_JPEG : + AVCOL_RANGE_MPEG; - // Perform any CPU processing required - f = PreProcessFrame(f, p); - if (!f) { - // Error occurred while software scaling - return nullptr; - } + // Perform any CPU processing required + f = PreProcessFrame(f, p); + if (!f) { + // Error occurred while software scaling + return nullptr; + } - // Finally, perform any GPU processing required - return ProcessFrameIntoTexture(f, p, original); - } + // Finally, perform any GPU processing required + return ProcessFrameIntoTexture(f, p, original); + } - return nullptr; + return nullptr; } void FFmpegDecoder::CloseInternal() { - if (working_packet_) { - av_packet_free(&working_packet_); - working_packet_ = nullptr; - } + if (working_packet_) { + av_packet_free(&working_packet_); + working_packet_ = nullptr; + } - ClearFrameCache(); - FreeScaler(); + ClearFrameCache(); + FreeScaler(); - instance_.Close(); + instance_.Close(); } rational FFmpegDecoder::GetAudioStartOffset() const { - auto f = instance_.fmt_ctx(); - if (f) { - rational fmt_start = rational(instance_.fmt_ctx()->start_time, AV_TIME_BASE); - rational str_start = rational(instance_.avstream()->time_base) * instance_.avstream()->start_time; - return str_start - fmt_start; - } else { - return 0; - } + auto f = instance_.fmt_ctx(); + if (f) { + rational fmt_start = + rational(instance_.fmt_ctx()->start_time, AV_TIME_BASE); + rational str_start = rational(instance_.avstream()->time_base) * + instance_.avstream()->start_time; + return str_start - fmt_start; + } else { + return 0; + } } QString FFmpegDecoder::id() const { - return QStringLiteral("ffmpeg"); + return QStringLiteral("ffmpeg"); } -FootageDescription FFmpegDecoder::Probe(const QString &filename, CancelAtom *cancelled) const +FootageDescription FFmpegDecoder::Probe(const QString &filename, + CancelAtom *cancelled) const { - // Return value - FootageDescription desc(id()); + // Return value + FootageDescription desc(id()); - // Variable for receiving errors from FFmpeg - int error_code; + // Variable for receiving errors from FFmpeg + int error_code; - // Convert QString to a C string - QByteArray filename_c = filename.toUtf8(); + // Convert QString to a C string + QByteArray filename_c = filename.toUtf8(); - // Open file in a format context - AVFormatContext* fmt_ctx = nullptr; - error_code = avformat_open_input(&fmt_ctx, filename_c, nullptr, nullptr); + // Open file in a format context + AVFormatContext *fmt_ctx = nullptr; + error_code = avformat_open_input(&fmt_ctx, filename_c, nullptr, nullptr); - // Handle format context error - if (error_code == 0) { + // Handle format context error + if (error_code == 0) { + // Retrieve metadata about the media + avformat_find_stream_info(fmt_ctx, nullptr); - // Retrieve metadata about the media - avformat_find_stream_info(fmt_ctx, nullptr); + int64_t footage_duration = fmt_ctx->duration; - int64_t footage_duration = fmt_ctx->duration; + bool duration_guessed_from_bitrate = + (fmt_ctx->duration_estimation_method == + AVFMT_DURATION_FROM_BITRATE); + if (duration_guessed_from_bitrate) { + qWarning() + << "Unreliable duration detected - we will manually determine it ourselves (this may take some time)"; + } - bool duration_guessed_from_bitrate = (fmt_ctx->duration_estimation_method == AVFMT_DURATION_FROM_BITRATE); - if (duration_guessed_from_bitrate) { - qWarning() << "Unreliable duration detected - we will manually determine it ourselves (this may take some time)"; - } + // Dump it into the Footage object + int video_streams = 0, audio_streams = 0, still_streams = 0; - // Dump it into the Footage object - int video_streams = 0, audio_streams = 0, still_streams = 0; + for (unsigned int i = 0; i < fmt_ctx->nb_streams; i++) { + // FFmpeg AVStream + AVStream *avstream = fmt_ctx->streams[i]; - for (unsigned int i=0;inb_streams;i++) { + // Find decoder for this stream, if it exists we can proceed + const AVCodec *decoder = + avcodec_find_decoder(avstream->codecpar->codec_id); - // FFmpeg AVStream - AVStream* avstream = fmt_ctx->streams[i]; + if (decoder && + (avstream->codecpar->codec_type == AVMEDIA_TYPE_VIDEO || + avstream->codecpar->codec_type == AVMEDIA_TYPE_AUDIO || + avstream->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE)) { + if (avstream->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { + AVPixelFormat compatible_pix_fmt = AV_PIX_FMT_NONE; - // Find decoder for this stream, if it exists we can proceed - const AVCodec* decoder = avcodec_find_decoder(avstream->codecpar->codec_id); + bool image_is_still = false; + rational pixel_aspect_ratio; + rational frame_rate; + VideoParams::Interlacing interlacing = + VideoParams::kInterlaceNone; - if (decoder - && (avstream->codecpar->codec_type == AVMEDIA_TYPE_VIDEO - || avstream->codecpar->codec_type == AVMEDIA_TYPE_AUDIO - || avstream->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE)) { + { + // Read at least two frames to get more information about this video stream + AVPacket *pkt = av_packet_alloc(); + AVFrame *frame = av_frame_alloc(); - if (avstream->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { + { + Instance instance; + instance.Open(filename_c, avstream->index); - AVPixelFormat compatible_pix_fmt = AV_PIX_FMT_NONE; + // Read first frame and retrieve some metadata + if (instance.GetFrame(pkt, frame) >= 0) { + // Check if video is interlaced and what field dominance it has if so + if (frame->interlaced_frame) { + if (frame->top_field_first) { + interlacing = + VideoParams::kInterlacedTopFirst; + } else { + interlacing = + VideoParams::kInterlacedBottomFirst; + } + } - bool image_is_still = false; - rational pixel_aspect_ratio; - rational frame_rate; - VideoParams::Interlacing interlacing = VideoParams::kInterlaceNone; + pixel_aspect_ratio = + av_guess_sample_aspect_ratio( + instance.fmt_ctx(), instance.avstream(), + frame); - { - // Read at least two frames to get more information about this video stream - AVPacket* pkt = av_packet_alloc(); - AVFrame* frame = av_frame_alloc(); + frame_rate = av_guess_frame_rate( + instance.fmt_ctx(), instance.avstream(), + frame); - { - Instance instance; - instance.Open(filename_c, avstream->index); + compatible_pix_fmt = + FFmpegUtils::GetCompatiblePixelFormat( + static_cast( + avstream->codecpar->format)); + } - // Read first frame and retrieve some metadata - if (instance.GetFrame(pkt, frame) >= 0) { - // Check if video is interlaced and what field dominance it has if so - if (frame->interlaced_frame) { - if (frame->top_field_first) { - interlacing = VideoParams::kInterlacedTopFirst; - } else { - interlacing = VideoParams::kInterlacedBottomFirst; - } - } + // Read second frame + int ret = instance.GetFrame(pkt, frame); - pixel_aspect_ratio = av_guess_sample_aspect_ratio(instance.fmt_ctx(), - instance.avstream(), - frame); + if (ret >= 0) { + // Check if we need a manual duration + if (avstream->duration == AV_NOPTS_VALUE || + duration_guessed_from_bitrate) { + if (footage_duration == AV_NOPTS_VALUE || + duration_guessed_from_bitrate) { + // Manually read through file for duration + int64_t new_dur; - frame_rate = av_guess_frame_rate(instance.fmt_ctx(), - instance.avstream(), - frame); + do { + new_dur = + frame->best_effort_timestamp; + } while (instance.GetFrame( + pkt, frame) >= 0 && + (!cancelled || + !cancelled->IsCancelled())); - compatible_pix_fmt = FFmpegUtils::GetCompatiblePixelFormat(static_cast(avstream->codecpar->format)); - } + avstream->duration = new_dur; - // Read second frame - int ret = instance.GetFrame(pkt, frame); + } else { + // Fallback to footage duration + avstream->duration = + Timecode::rescale_timestamp_ceil( + footage_duration, + rational(1, AV_TIME_BASE), + avstream->time_base); + } + } + } else if (ret == AVERROR_EOF) { + // Video has only one frame in it, treat it like a still image + image_is_still = true; + } - if (ret >= 0) { - // Check if we need a manual duration - if (avstream->duration == AV_NOPTS_VALUE || duration_guessed_from_bitrate) { - if (footage_duration == AV_NOPTS_VALUE || duration_guessed_from_bitrate) { + instance.Close(); + } - // Manually read through file for duration - int64_t new_dur; + av_frame_free(&frame); + av_packet_free(&pkt); + } - do { - new_dur = frame->best_effort_timestamp; - } while (instance.GetFrame(pkt, frame) >= 0 && (!cancelled || !cancelled->IsCancelled())); + VideoParams stream; + stream.set_stream_index(i); + stream.set_width(avstream->codecpar->width); + stream.set_height(avstream->codecpar->height); + stream.set_video_type((image_is_still) ? + VideoParams::kVideoTypeStill : + VideoParams::kVideoTypeVideo); + stream.set_format(GetNativePixelFormat(compatible_pix_fmt)); + stream.set_channel_count( + GetNativeChannelCount(compatible_pix_fmt)); + stream.set_interlacing(interlacing); + stream.set_pixel_aspect_ratio(pixel_aspect_ratio); + stream.set_frame_rate(frame_rate); + stream.set_start_time(avstream->start_time); + stream.set_time_base(avstream->time_base); + stream.set_duration(avstream->duration); + stream.set_color_range(avstream->codecpar->color_range == + AVCOL_RANGE_JPEG ? + VideoParams::kColorRangeFull : + VideoParams::kColorRangeLimited); - avstream->duration = new_dur; + // Defaults to false, requires user intervention if incorrect + stream.set_premultiplied_alpha(false); - } else { + desc.AddVideoStream(stream); - // Fallback to footage duration - avstream->duration = Timecode::rescale_timestamp_ceil(footage_duration, rational(1, AV_TIME_BASE), avstream->time_base); + if (image_is_still) { + still_streams++; + } else { + video_streams++; + } - } - } - } else if (ret == AVERROR_EOF) { - // Video has only one frame in it, treat it like a still image - image_is_still = true; - } + } else if (avstream->codecpar->codec_type == + AVMEDIA_TYPE_AUDIO) { + // Create an audio stream object + AVChannelLayout &channel_layout = + avstream->codecpar->ch_layout; + if (!av_channel_layout_check(&channel_layout)) { + av_channel_layout_default( + &channel_layout, + avstream->codecpar->ch_layout.nb_channels); + } - instance.Close(); - } + if (avstream->duration == AV_NOPTS_VALUE || + duration_guessed_from_bitrate) { + // Loop through stream until we get the whole duration + if (footage_duration == AV_NOPTS_VALUE || + duration_guessed_from_bitrate) { + Instance instance; + instance.Open(filename_c, avstream->index); - av_frame_free(&frame); - av_packet_free(&pkt); - } + AVPacket *pkt = av_packet_alloc(); + AVFrame *frame = av_frame_alloc(); - VideoParams stream; - stream.set_stream_index(i); - stream.set_width(avstream->codecpar->width); - stream.set_height(avstream->codecpar->height); - stream.set_video_type((image_is_still) ? VideoParams::kVideoTypeStill : VideoParams::kVideoTypeVideo); - stream.set_format(GetNativePixelFormat(compatible_pix_fmt)); - stream.set_channel_count(GetNativeChannelCount(compatible_pix_fmt)); - stream.set_interlacing(interlacing); - stream.set_pixel_aspect_ratio(pixel_aspect_ratio); - stream.set_frame_rate(frame_rate); - stream.set_start_time(avstream->start_time); - stream.set_time_base(avstream->time_base); - stream.set_duration(avstream->duration); - stream.set_color_range(avstream->codecpar->color_range == AVCOL_RANGE_JPEG ? VideoParams::kColorRangeFull : VideoParams::kColorRangeLimited); + int64_t new_dur; - // Defaults to false, requires user intervention if incorrect - stream.set_premultiplied_alpha(false); + do { + new_dur = frame->best_effort_timestamp; + } while (instance.GetFrame(pkt, frame) >= 0 && + (!cancelled || !cancelled->IsCancelled())); - desc.AddVideoStream(stream); + avstream->duration = new_dur; - if (image_is_still) { - still_streams++; - } else { - video_streams++; - } + av_frame_free(&frame); + av_packet_free(&pkt); - } else if (avstream->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { + instance.Close(); + } else { + avstream->duration = + Timecode::rescale_timestamp_ceil( + footage_duration, rational(1, AV_TIME_BASE), + avstream->time_base); + } + } - // Create an audio stream object - AVChannelLayout &channel_layout = avstream->codecpar->ch_layout; - if (!av_channel_layout_check(&channel_layout)) { - av_channel_layout_default(&channel_layout,avstream->codecpar->ch_layout.nb_channels); - } + AudioParams stream; + stream.set_stream_index(i); + stream.set_channel_layout(channel_layout); + stream.set_sample_rate(avstream->codecpar->sample_rate); + stream.set_format(FFmpegUtils::GetNativeSampleFormat( + static_cast( + avstream->codecpar->format))); + stream.set_time_base(avstream->time_base); + stream.set_duration(avstream->duration); + desc.AddAudioStream(stream); - if (avstream->duration == AV_NOPTS_VALUE || duration_guessed_from_bitrate) { - // Loop through stream until we get the whole duration - if (footage_duration == AV_NOPTS_VALUE || duration_guessed_from_bitrate) { - Instance instance; - instance.Open(filename_c, avstream->index); + audio_streams++; - AVPacket* pkt = av_packet_alloc(); - AVFrame* frame = av_frame_alloc(); + } else if (avstream->codecpar->codec_type == + AVMEDIA_TYPE_SUBTITLE) { + // Limit to SRT for now... + if (avstream->codecpar->codec_id == AV_CODEC_ID_SUBRIP) { + SubtitleParams sub; - int64_t new_dur; + AVPacket *pkt = av_packet_alloc(); + { + Instance instance; + instance.Open(filename_c, avstream->index); - do { - new_dur = frame->best_effort_timestamp; - } while (instance.GetFrame(pkt, frame) >= 0 && (!cancelled || !cancelled->IsCancelled())); + while (instance.GetPacket(pkt) >= 0) { + TimeRange time(Timecode::timestamp_to_time( + pkt->pts, + avstream->time_base), + Timecode::timestamp_to_time( + pkt->pts + pkt->duration, + avstream->time_base)); - avstream->duration = new_dur; + QString text = QString::fromUtf8( + (const char *)pkt->data, pkt->size); - av_frame_free(&frame); - av_packet_free(&pkt); + sub.push_back(Subtitle(time, text)); + } - instance.Close(); - } else { + instance.Close(); + } + av_packet_free(&pkt); - avstream->duration = Timecode::rescale_timestamp_ceil(footage_duration, rational(1, AV_TIME_BASE), avstream->time_base); + desc.AddSubtitleStream(sub); + } + } + } + } - } - } + desc.SetStreamCount(fmt_ctx->nb_streams); - AudioParams stream; - stream.set_stream_index(i); - stream.set_channel_layout(channel_layout); - stream.set_sample_rate(avstream->codecpar->sample_rate); - stream.set_format(FFmpegUtils::GetNativeSampleFormat(static_cast(avstream->codecpar->format))); - stream.set_time_base(avstream->time_base); - stream.set_duration(avstream->duration); - desc.AddAudioStream(stream); + if (video_streams == 0 && audio_streams > 0 && still_streams > 0) { + // This footage has no video streams, but has audio and image streams. We've probably + // imported a song with embedded album art that most people don't care about. We'll keep the + // stills referenced in case users do, but we'll default them to disabled so they're + // easier to work with. + for (VideoParams &vp : desc.GetVideoStreams()) { + vp.set_enabled(false); + } + } + } - audio_streams++; + // Free all memory + avformat_close_input(&fmt_ctx); - } else if (avstream->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE) { - - // Limit to SRT for now... - if (avstream->codecpar->codec_id == AV_CODEC_ID_SUBRIP) { - SubtitleParams sub; - - AVPacket* pkt = av_packet_alloc(); - { - Instance instance; - instance.Open(filename_c, avstream->index); - - while (instance.GetPacket(pkt) >= 0) { - TimeRange time(Timecode::timestamp_to_time(pkt->pts, avstream->time_base), - Timecode::timestamp_to_time(pkt->pts + pkt->duration, avstream->time_base)); - - QString text = QString::fromUtf8((const char *) pkt->data, pkt->size); - - sub.push_back(Subtitle(time, text)); - } - - instance.Close(); - } - av_packet_free(&pkt); - - desc.AddSubtitleStream(sub); - } - - } - - } - - } - - desc.SetStreamCount(fmt_ctx->nb_streams); - - if (video_streams == 0 && audio_streams > 0 && still_streams > 0) { - // This footage has no video streams, but has audio and image streams. We've probably - // imported a song with embedded album art that most people don't care about. We'll keep the - // stills referenced in case users do, but we'll default them to disabled so they're - // easier to work with. - for (VideoParams &vp : desc.GetVideoStreams()) { - vp.set_enabled(false); - } - } - - } - - // Free all memory - avformat_close_input(&fmt_ctx); - - return desc; + return desc; } QString FFmpegDecoder::FFmpegError(int error_code) { - char err[1024]; - av_strerror(error_code, err, 512); - return QStringLiteral("%1 %2").arg(QString::number(error_code), err); + char err[1024]; + av_strerror(error_code, err, 512); + return QStringLiteral("%1 %2").arg(QString::number(error_code), err); } -bool FFmpegDecoder::ConformAudioInternal(const QVector &filenames, const AudioParams ¶ms, CancelAtom *cancelled) +bool FFmpegDecoder::ConformAudioInternal(const QVector &filenames, + const AudioParams ¶ms, + CancelAtom *cancelled) { - // Iterate through each audio frame and extract the PCM data + // Iterate through each audio frame and extract the PCM data - // Seek to starting point - instance_.Seek(0); + // Seek to starting point + instance_.Seek(0); - // Handle NULL channel layout - AVChannelLayout channel_layout = ValidateChannelLayout(instance_.avstream()); - if (!av_channel_layout_check(&channel_layout)) { - qCritical() << "Failed to determine channel layout of audio file, could not conform"; - return false; - } - // Create resampling context - AVChannelLayout layout=params.channel_layout(); - SwrContext* resampler; - swr_alloc_set_opts2(&resampler, - &layout, - FFmpegUtils::GetFFmpegSampleFormat(params.format()), - params.sample_rate(), - &channel_layout, - static_cast(instance_.avstream()->codecpar->format), - instance_.avstream()->codecpar->sample_rate, - 0, - nullptr); - av_channel_layout_uninit(&layout); - swr_init(resampler); + // Handle NULL channel layout + AVChannelLayout channel_layout = + ValidateChannelLayout(instance_.avstream()); + if (!av_channel_layout_check(&channel_layout)) { + qCritical() + << "Failed to determine channel layout of audio file, could not conform"; + return false; + } + // Create resampling context + AVChannelLayout layout = params.channel_layout(); + SwrContext *resampler; + swr_alloc_set_opts2( + &resampler, &layout, + FFmpegUtils::GetFFmpegSampleFormat(params.format()), + params.sample_rate(), &channel_layout, + static_cast(instance_.avstream()->codecpar->format), + instance_.avstream()->codecpar->sample_rate, 0, nullptr); + av_channel_layout_uninit(&layout); + swr_init(resampler); - AVPacket* pkt = av_packet_alloc(); - AVFrame* frame = av_frame_alloc(); - int ret; + AVPacket *pkt = av_packet_alloc(); + AVFrame *frame = av_frame_alloc(); + int ret; - bool success = false; + bool success = false; - int64_t duration = instance_.avstream()->duration; - if (duration == 0 || duration == AV_NOPTS_VALUE) { - duration = instance_.fmt_ctx()->duration; - if (!(duration == 0 || duration == AV_NOPTS_VALUE)) { - // Rescale from AVFormatContext timebase to AVStream timebase - duration = av_rescale_q_rnd(duration, {1, AV_TIME_BASE}, instance_.avstream()->time_base, AV_ROUND_UP); - } - } + int64_t duration = instance_.avstream()->duration; + if (duration == 0 || duration == AV_NOPTS_VALUE) { + duration = instance_.fmt_ctx()->duration; + if (!(duration == 0 || duration == AV_NOPTS_VALUE)) { + // Rescale from AVFormatContext timebase to AVStream timebase + duration = av_rescale_q_rnd(duration, { 1, AV_TIME_BASE }, + instance_.avstream()->time_base, + AV_ROUND_UP); + } + } - PlanarFileDevice wave_out; - if (wave_out.open(filenames, QFile::WriteOnly)) { - int nb_channels = params.channel_count(); - SampleBuffer data; - data.set_audio_params(params); + PlanarFileDevice wave_out; + if (wave_out.open(filenames, QFile::WriteOnly)) { + int nb_channels = params.channel_count(); + SampleBuffer data; + data.set_audio_params(params); - while (true) { - // Check if we have a `cancelled` ptr and its value - if (cancelled && cancelled->IsCancelled()) { - break; - } + while (true) { + // Check if we have a `cancelled` ptr and its value + if (cancelled && cancelled->IsCancelled()) { + break; + } - ret = instance_.GetFrame(pkt, frame); + ret = instance_.GetFrame(pkt, frame); - if (ret < 0) { + if (ret < 0) { + if (ret == AVERROR_EOF) { + success = true; + } else { + char err_str[512]; + av_strerror(ret, err_str, 512); + qWarning() << "Failed to conform:" << ret << err_str; + } + break; + } - if (ret == AVERROR_EOF) { - success = true; - } else { - char err_str[512]; - av_strerror(ret, err_str, 512); - qWarning() << "Failed to conform:" << ret << err_str; - } - break; + // Allocate buffers + int nb_samples = swr_get_out_samples(resampler, frame->nb_samples); + int nb_bytes_per_channel = + params.samples_to_bytes(nb_samples) / nb_channels; + data.set_sample_count(nb_bytes_per_channel); + data.allocate(); - } + // Resample audio to our destination parameters + nb_samples = swr_convert( + resampler, + reinterpret_cast(data.to_raw_ptrs().data()), + nb_samples, const_cast(frame->data), + frame->nb_samples); - // Allocate buffers - int nb_samples = swr_get_out_samples(resampler, frame->nb_samples); - int nb_bytes_per_channel = params.samples_to_bytes(nb_samples) / nb_channels; - data.set_sample_count(nb_bytes_per_channel); - data.allocate(); + // If no error, write to files + if (nb_samples > 0) { + // Update byte count for the number of samples we actually received + nb_bytes_per_channel = + params.samples_to_bytes(nb_samples) / nb_channels; - // Resample audio to our destination parameters - nb_samples = swr_convert(resampler, - reinterpret_cast(data.to_raw_ptrs().data()), - nb_samples, - const_cast(frame->data), - frame->nb_samples); + // Write to files + wave_out.write( + const_cast( + reinterpret_cast(data.to_raw_ptrs().data())), + nb_bytes_per_channel); + } - // If no error, write to files - if (nb_samples > 0) { - // Update byte count for the number of samples we actually received - nb_bytes_per_channel = params.samples_to_bytes(nb_samples) / nb_channels; + // Free buffer + data.destroy(); - // Write to files - wave_out.write(const_cast(reinterpret_cast(data.to_raw_ptrs().data())), nb_bytes_per_channel); - } + // Handle error now after freeing + if (nb_samples < 0) { + char err_str[512]; + av_strerror(nb_samples, err_str, 512); + qWarning() << "libswresample failed with error:" << nb_samples + << err_str; + break; + } - // Free buffer - data.destroy(); + SignalProcessingProgress(frame->best_effort_timestamp, duration); + } - // Handle error now after freeing - if (nb_samples < 0) { - char err_str[512]; - av_strerror(nb_samples, err_str, 512); - qWarning() << "libswresample failed with error:" << nb_samples << err_str; - break; - } + wave_out.close(); + } else { + qWarning() << "Failed to open WAVE output for indexing"; + } - SignalProcessingProgress(frame->best_effort_timestamp, duration); - } + swr_free(&resampler); - wave_out.close(); - } else { - qWarning() << "Failed to open WAVE output for indexing"; - } + av_frame_free(&frame); + av_packet_free(&pkt); - swr_free(&resampler); - - av_frame_free(&frame); - av_packet_free(&pkt); - - return success; + return success; } PixelFormat FFmpegDecoder::GetNativePixelFormat(AVPixelFormat pix_fmt) { - switch (pix_fmt) { - case AV_PIX_FMT_RGB24: - case AV_PIX_FMT_RGBA: - return PixelFormat::U8; - case AV_PIX_FMT_RGB48: - case AV_PIX_FMT_RGBA64: - return PixelFormat::U16; - default: - return PixelFormat::INVALID; - } + switch (pix_fmt) { + case AV_PIX_FMT_RGB24: + case AV_PIX_FMT_RGBA: + return PixelFormat::U8; + case AV_PIX_FMT_RGB48: + case AV_PIX_FMT_RGBA64: + return PixelFormat::U16; + default: + return PixelFormat::INVALID; + } } int FFmpegDecoder::GetNativeChannelCount(AVPixelFormat pix_fmt) { - switch (pix_fmt) { - case AV_PIX_FMT_RGB24: - case AV_PIX_FMT_RGB48: - return VideoParams::kRGBChannelCount; - case AV_PIX_FMT_RGBA: - case AV_PIX_FMT_RGBA64: - return VideoParams::kRGBAChannelCount; - default: - return 0; - } + switch (pix_fmt) { + case AV_PIX_FMT_RGB24: + case AV_PIX_FMT_RGB48: + return VideoParams::kRGBChannelCount; + case AV_PIX_FMT_RGBA: + case AV_PIX_FMT_RGBA64: + return VideoParams::kRGBAChannelCount; + default: + return 0; + } } -AVChannelLayout FFmpegDecoder::ValidateChannelLayout(AVStream* stream) +AVChannelLayout FFmpegDecoder::ValidateChannelLayout(AVStream *stream) { - if (av_channel_layout_check(&stream->codecpar->ch_layout)) { - return stream->codecpar->ch_layout; - } - AVChannelLayout layout; - av_channel_layout_default(&layout,stream->codecpar->ch_layout.nb_channels); - return layout; + if (av_channel_layout_check(&stream->codecpar->ch_layout)) { + return stream->codecpar->ch_layout; + } + AVChannelLayout layout; + av_channel_layout_default(&layout, stream->codecpar->ch_layout.nb_channels); + return layout; } -const char *FFmpegDecoder::GetInterlacingModeInFFmpeg(VideoParams::Interlacing interlacing) +const char * +FFmpegDecoder::GetInterlacingModeInFFmpeg(VideoParams::Interlacing interlacing) { - if (interlacing == VideoParams::kInterlacedTopFirst) { - return "tff"; - } else { - return "bff"; - } + if (interlacing == VideoParams::kInterlacedTopFirst) { + return "tff"; + } else { + return "bff"; + } } bool FFmpegDecoder::IsPixelFormatGLSLCompatible(AVPixelFormat f) { - // NOTE: We don't include RGB24 or RGB48 here because those are slow on the GPU and performance - // should be better if we convert to RGBA on the CPU beforehand - switch (f) { - case AV_PIX_FMT_YUV420P: - case AV_PIX_FMT_YUV422P: - case AV_PIX_FMT_YUV444P: - case AV_PIX_FMT_YUV420P10LE: - case AV_PIX_FMT_YUV422P10LE: - case AV_PIX_FMT_YUV444P10LE: - case AV_PIX_FMT_YUV420P12LE: - case AV_PIX_FMT_YUV422P12LE: - case AV_PIX_FMT_YUV444P12LE: - case AV_PIX_FMT_RGBA: - case AV_PIX_FMT_RGBA64LE: - return true; - default: - return false; - } + // NOTE: We don't include RGB24 or RGB48 here because those are slow on the GPU and performance + // should be better if we convert to RGBA on the CPU beforehand + switch (f) { + case AV_PIX_FMT_YUV420P: + case AV_PIX_FMT_YUV422P: + case AV_PIX_FMT_YUV444P: + case AV_PIX_FMT_YUV420P10LE: + case AV_PIX_FMT_YUV422P10LE: + case AV_PIX_FMT_YUV444P10LE: + case AV_PIX_FMT_YUV420P12LE: + case AV_PIX_FMT_YUV422P12LE: + case AV_PIX_FMT_YUV444P12LE: + case AV_PIX_FMT_RGBA: + case AV_PIX_FMT_RGBA64LE: + return true; + default: + return false; + } } void FFmpegDecoder::ClearFrameCache() { - if (!cached_frames_.empty()) { - cached_frames_.clear(); - cache_at_eof_ = false; - cache_at_zero_ = false; - } + if (!cached_frames_.empty()) { + cached_frames_.clear(); + cache_at_eof_ = false; + cache_at_zero_ = false; + } } -AVFramePtr FFmpegDecoder::PreProcessFrame(AVFramePtr f, const RetrieveVideoParams &p) +AVFramePtr FFmpegDecoder::PreProcessFrame(AVFramePtr f, + const RetrieveVideoParams &p) { - // In pre-processing, we try to achieve the following: - // - If a divider is being used, scale down the image - // - If a pixel format is not compatible with the GLSL shader, convert it to RGBA ourselves + // In pre-processing, we try to achieve the following: + // - If a divider is being used, scale down the image + // - If a pixel format is not compatible with the GLSL shader, convert it to RGBA ourselves - if (p.divider == 1 && IsPixelFormatGLSLCompatible(static_cast(f->format))) { - // No CPU processing required, the user wants this in full resolution and the pixel format can - // be converted on the GPU - return f; - } + if (p.divider == 1 && + IsPixelFormatGLSLCompatible(static_cast(f->format))) { + // No CPU processing required, the user wants this in full resolution and the pixel format can + // be converted on the GPU + return f; + } - // Some scaling and/or format conversion needs to be done - AVFramePtr dest = CreateAVFramePtr(); + // Some scaling and/or format conversion needs to be done + AVFramePtr dest = CreateAVFramePtr(); - dest->width = f->width; - dest->height = f->height; - dest->format = f->format; - dest->color_range = f->color_range; - dest->colorspace = f->colorspace; + dest->width = f->width; + dest->height = f->height; + dest->format = f->format; + dest->color_range = f->color_range; + dest->colorspace = f->colorspace; - if (p.divider > 1) { - dest->width = VideoParams::GetScaledDimension(dest->width, p.divider); - dest->height = VideoParams::GetScaledDimension(dest->height, p.divider); - } + if (p.divider > 1) { + dest->width = VideoParams::GetScaledDimension(dest->width, p.divider); + dest->height = VideoParams::GetScaledDimension(dest->height, p.divider); + } - if (!IsPixelFormatGLSLCompatible(static_cast(dest->format))) { - dest->format = FFmpegUtils::GetCompatiblePixelFormat(static_cast(dest->format), p.maximum_format); - } + if (!IsPixelFormatGLSLCompatible( + static_cast(dest->format))) { + dest->format = FFmpegUtils::GetCompatiblePixelFormat( + static_cast(dest->format), p.maximum_format); + } - int r = av_frame_get_buffer(dest.get(), 0); - if (r < 0) { - FFmpegError(r); - return nullptr; - } + int r = av_frame_get_buffer(dest.get(), 0); + if (r < 0) { + FFmpegError(r); + return nullptr; + } - if (!sws_ctx_ - || sws_src_width_ != f->width - || sws_src_height_ != f->height - || sws_src_format_ != f->format - || sws_dst_width_ != dest->width - || sws_dst_height_ != dest->height - || sws_dst_format_ != dest->format - || sws_colrange_ != dest->color_range - || sws_colspace_ != dest->colorspace) { - // SwsContext must be recreated, destroy current if it exists - FreeScaler(); + if (!sws_ctx_ || sws_src_width_ != f->width || + sws_src_height_ != f->height || sws_src_format_ != f->format || + sws_dst_width_ != dest->width || sws_dst_height_ != dest->height || + sws_dst_format_ != dest->format || sws_colrange_ != dest->color_range || + sws_colspace_ != dest->colorspace) { + // SwsContext must be recreated, destroy current if it exists + FreeScaler(); - // Cache info - sws_src_width_ = f->width; - sws_src_height_ = f->height; - sws_src_format_ = static_cast(f->format); - sws_dst_width_ = dest->width; - sws_dst_height_ = dest->height; - sws_dst_format_ = static_cast(dest->format); - sws_colrange_ = dest->color_range; - sws_colspace_ = dest->colorspace; + // Cache info + sws_src_width_ = f->width; + sws_src_height_ = f->height; + sws_src_format_ = static_cast(f->format); + sws_dst_width_ = dest->width; + sws_dst_height_ = dest->height; + sws_dst_format_ = static_cast(dest->format); + sws_colrange_ = dest->color_range; + sws_colspace_ = dest->colorspace; - // Create new scaler - sws_ctx_ = sws_getContext(sws_src_width_, - sws_src_height_, - sws_src_format_, - sws_dst_width_, - sws_dst_height_, - sws_dst_format_, - SWS_POINT, - nullptr, - nullptr, - nullptr); + // Create new scaler + sws_ctx_ = sws_getContext(sws_src_width_, sws_src_height_, + sws_src_format_, sws_dst_width_, + sws_dst_height_, sws_dst_format_, SWS_POINT, + nullptr, nullptr, nullptr); - // Set swscale's colorspace details - sws_setColorspaceDetails(sws_ctx_, - sws_getCoefficients(FFmpegUtils::GetSwsColorspaceFromAVColorSpace(dest->colorspace)), - dest->color_range == AVCOL_RANGE_JPEG ? 1 : 0, - sws_getCoefficients(FFmpegUtils::GetSwsColorspaceFromAVColorSpace(dest->colorspace)), - dest->color_range == AVCOL_RANGE_JPEG ? 1 : 0, - 0, 0x10000, 0x10000); - } + // Set swscale's colorspace details + sws_setColorspaceDetails( + sws_ctx_, + sws_getCoefficients(FFmpegUtils::GetSwsColorspaceFromAVColorSpace( + dest->colorspace)), + dest->color_range == AVCOL_RANGE_JPEG ? 1 : 0, + sws_getCoefficients(FFmpegUtils::GetSwsColorspaceFromAVColorSpace( + dest->colorspace)), + dest->color_range == AVCOL_RANGE_JPEG ? 1 : 0, 0, 0x10000, 0x10000); + } - r = sws_scale(sws_ctx_, f->data, f->linesize, 0, f->height, dest->data, dest->linesize); - if (r < 0) { - FFmpegError(r); - return nullptr; - } + r = sws_scale(sws_ctx_, f->data, f->linesize, 0, f->height, dest->data, + dest->linesize); + if (r < 0) { + FFmpegError(r); + return nullptr; + } - return dest; + return dest; } -AVFramePtr FFmpegDecoder::RetrieveFrame(const rational& time, CancelAtom *cancelled) +AVFramePtr FFmpegDecoder::RetrieveFrame(const rational &time, + CancelAtom *cancelled) { - int64_t target_ts = Timecode::time_to_timestamp(time, instance_.avstream()->time_base); + int64_t target_ts = + Timecode::time_to_timestamp(time, instance_.avstream()->time_base); - if (instance_.fmt_ctx()->start_time != AV_NOPTS_VALUE) { - target_ts += av_rescale_q(instance_.fmt_ctx()->start_time, {1, AV_TIME_BASE}, instance_.avstream()->time_base); - } + if (instance_.fmt_ctx()->start_time != AV_NOPTS_VALUE) { + target_ts += av_rescale_q(instance_.fmt_ctx()->start_time, + { 1, AV_TIME_BASE }, + instance_.avstream()->time_base); + } - const int64_t min_seek = 0; - int64_t seek_ts = std::max(min_seek, target_ts - MaximumQueueSize()); - bool still_seeking = false; + const int64_t min_seek = 0; + int64_t seek_ts = std::max(min_seek, target_ts - MaximumQueueSize()); + bool still_seeking = false; - if (time != kAnyTimecode) { - // If the frame wasn't in the frame cache, see if this frame cache is too old to use - if (cached_frames_.empty() - || (target_ts < cached_frames_.front()->pts || target_ts > cached_frames_.back()->pts + 2*second_ts_)) { - ClearFrameCache(); + if (time != kAnyTimecode) { + // If the frame wasn't in the frame cache, see if this frame cache is too old to use + if (cached_frames_.empty() || + (target_ts < cached_frames_.front()->pts || + target_ts > cached_frames_.back()->pts + 2 * second_ts_)) { + ClearFrameCache(); - instance_.Seek(seek_ts); - if (seek_ts == min_seek) { - cache_at_zero_ = true; - } + instance_.Seek(seek_ts); + if (seek_ts == min_seek) { + cache_at_zero_ = true; + } - still_seeking = true; - } else { - // Search cache for frame - AVFramePtr cached_frame = GetFrameFromCache(target_ts); - if (cached_frame) { - return cached_frame; - } - } - } + still_seeking = true; + } else { + // Search cache for frame + AVFramePtr cached_frame = GetFrameFromCache(target_ts); + if (cached_frame) { + return cached_frame; + } + } + } - int ret; - AVFramePtr return_frame = nullptr; - AVFramePtr filtered = nullptr; + int ret; + AVFramePtr return_frame = nullptr; + AVFramePtr filtered = nullptr; - while (true) { - // Break out of loop if we've cancelled - if (cancelled && cancelled->IsCancelled()) { - break; - } + while (true) { + // Break out of loop if we've cancelled + if (cancelled && cancelled->IsCancelled()) { + break; + } - if (!filtered) { - filtered = CreateAVFramePtr(); - } + if (!filtered) { + filtered = CreateAVFramePtr(); + } - // Pull from the decoder - ret = instance_.GetFrame(working_packet_, filtered.get()); + // Pull from the decoder + ret = instance_.GetFrame(working_packet_, filtered.get()); - if (cancelled && cancelled->IsCancelled()) { - break; - } + if (cancelled && cancelled->IsCancelled()) { + break; + } - // Handle any errors that aren't EOF (EOF is handled later on) - if (ret < 0 && ret != AVERROR_EOF) { - qCritical() << "Failed to retrieve frame:" << ret; - break; - } + // Handle any errors that aren't EOF (EOF is handled later on) + if (ret < 0 && ret != AVERROR_EOF) { + qCritical() << "Failed to retrieve frame:" << ret; + break; + } - if (still_seeking) { - // Handle a failure to seek (occurs on some media) - // We'll only be here if the frame cache was emptied earlier - if (!cache_at_zero_ && (ret == AVERROR_EOF || filtered->best_effort_timestamp > target_ts)) { + if (still_seeking) { + // Handle a failure to seek (occurs on some media) + // We'll only be here if the frame cache was emptied earlier + if (!cache_at_zero_ && + (ret == AVERROR_EOF || + filtered->best_effort_timestamp > target_ts)) { + seek_ts = qMax(min_seek, seek_ts - second_ts_); + instance_.Seek(seek_ts); + if (seek_ts == min_seek) { + cache_at_zero_ = true; + } + continue; - seek_ts = qMax(min_seek, seek_ts - second_ts_); - instance_.Seek(seek_ts); - if (seek_ts == min_seek) { - cache_at_zero_ = true; - } - continue; + } else { + still_seeking = false; + } + } - } else { + if (ret == AVERROR_EOF) { + // Handle an "expected" EOF by using the last frame of our cache + cache_at_eof_ = true; - still_seeking = false; + if (cached_frames_.empty()) { + qCritical() + << "Unexpected codec EOF - unable to retrieve frame"; + } else { + return_frame = cached_frames_.back(); + } - } - } + break; - if (ret == AVERROR_EOF) { + } else { + // Cut down to thread count - 1 before we acquire a new frame + if (cached_frames_.size() > size_t(MaximumQueueSize())) { + RemoveFirstFrame(); + } - // Handle an "expected" EOF by using the last frame of our cache - cache_at_eof_ = true; + // Store frame before just in case + AVFramePtr previous; + if (cached_frames_.empty()) { + previous = nullptr; + } else { + previous = cached_frames_.back(); + } - if (cached_frames_.empty()) { - qCritical() << "Unexpected codec EOF - unable to retrieve frame"; - } else { - return_frame = cached_frames_.back(); - } + // Append this frame and signal to other threads that a new frame has arrived + cached_frames_.push_back(filtered); - break; + // If this is a valid frame, see if this or the frame before it are the one we need + if (filtered->pts == target_ts || time == kAnyTimecode) { + return_frame = filtered; + break; + } else if (filtered->pts > target_ts) { + if (!previous && cache_at_zero_) { + return_frame = filtered; + break; + } else { + return_frame = previous; + break; + } + } + } - } else { + filtered = nullptr; + } - // Cut down to thread count - 1 before we acquire a new frame - if (cached_frames_.size() > size_t(MaximumQueueSize())) { - RemoveFirstFrame(); - } + av_packet_unref(working_packet_); - // Store frame before just in case - AVFramePtr previous; - if (cached_frames_.empty()) { - previous = nullptr; - } else { - previous = cached_frames_.back(); - } - - // Append this frame and signal to other threads that a new frame has arrived - cached_frames_.push_back(filtered); - - // If this is a valid frame, see if this or the frame before it are the one we need - if (filtered->pts == target_ts || time == kAnyTimecode) { - return_frame = filtered; - break; - } else if (filtered->pts > target_ts) { - if (!previous && cache_at_zero_) { - return_frame = filtered; - break; - } else { - return_frame = previous; - break; - } - } - } - - filtered = nullptr; - } - - av_packet_unref(working_packet_); - - return return_frame; + return return_frame; } void FFmpegDecoder::FreeScaler() { - if (sws_ctx_) { - sws_freeContext(sws_ctx_); - sws_ctx_ = nullptr; - } + if (sws_ctx_) { + sws_freeContext(sws_ctx_); + sws_ctx_ = nullptr; + } } AVFramePtr FFmpegDecoder::GetFrameFromCache(const int64_t &t) const { - if (t < cached_frames_.front()->pts) { + if (t < cached_frames_.front()->pts) { + if (cache_at_zero_) { + return cached_frames_.front(); + } - if (cache_at_zero_) { - return cached_frames_.front(); - } + } else if (t > cached_frames_.back()->pts) { + if (cache_at_eof_) { + return cached_frames_.back(); + } - } else if (t > cached_frames_.back()->pts) { + } else { + // We already have this frame in the cache, find it + for (auto it = cached_frames_.cbegin(); it != cached_frames_.cend(); + it++) { + AVFramePtr this_frame = *it; - if (cache_at_eof_) { - return cached_frames_.back(); - } + auto next = it; + next++; - } else { + if (this_frame->pts == t // Test for an exact match + || + (next != cached_frames_.cend() && + (*next)->pts > t)) { // Or for this frame to be the "closest" - // We already have this frame in the cache, find it - for (auto it=cached_frames_.cbegin(); it!=cached_frames_.cend(); it++) { - AVFramePtr this_frame = *it; + return this_frame; + } + } + } - auto next = it; - next++; - - if (this_frame->pts == t // Test for an exact match - || (next != cached_frames_.cend() && (*next)->pts > t)) { // Or for this frame to be the "closest" - - return this_frame; - - } - } - } - - return nullptr; + return nullptr; } void FFmpegDecoder::RemoveFirstFrame() { - cached_frames_.pop_front(); - cache_at_zero_ = false; + cached_frames_.pop_front(); + cache_at_zero_ = false; } int FFmpegDecoder::MaximumQueueSize() { - // Fairly arbitrary size. This used to need to be the number of current threads to ensure any - // thread that arrived would have its frame available, but if we only have one render thread, - // that's no longer a concern. Now, this value could technically be 1, but some memory cache - // may be useful for reversing. This value may be tweaked over time. - return 2; + // Fairly arbitrary size. This used to need to be the number of current threads to ensure any + // thread that arrived would have its frame available, but if we only have one render thread, + // that's no longer a concern. Now, this value could technically be 1, but some memory cache + // may be useful for reversing. This value may be tweaked over time. + return 2; } -FFmpegDecoder::Instance::Instance() : - fmt_ctx_(nullptr), - codec_ctx_(nullptr), - avstream_(nullptr), - opts_(nullptr) +FFmpegDecoder::Instance::Instance() + : fmt_ctx_(nullptr) + , codec_ctx_(nullptr) + , avstream_(nullptr) + , opts_(nullptr) { } bool FFmpegDecoder::Instance::Open(const char *filename, int stream_index) { - // Open file in a format context - int error_code = avformat_open_input(&fmt_ctx_, filename, nullptr, nullptr); + // Open file in a format context + int error_code = avformat_open_input(&fmt_ctx_, filename, nullptr, nullptr); - // Handle format context error - if (error_code != 0) { - qCritical() << "Failed to open input:" << filename << FFmpegError(error_code); - return false; - } + // Handle format context error + if (error_code != 0) { + qCritical() + << "Failed to open input:" << filename << FFmpegError(error_code); + return false; + } - // Get stream information from format - error_code = avformat_find_stream_info(fmt_ctx_, nullptr); + // Get stream information from format + error_code = avformat_find_stream_info(fmt_ctx_, nullptr); - // Handle get stream information error - if (error_code < 0) { - qCritical() << "Failed to find stream info:" << FFmpegError(error_code); - return false; - } + // Handle get stream information error + if (error_code < 0) { + qCritical() << "Failed to find stream info:" << FFmpegError(error_code); + return false; + } - // Get reference to correct AVStream - avstream_ = fmt_ctx_->streams[stream_index]; + // Get reference to correct AVStream + avstream_ = fmt_ctx_->streams[stream_index]; - // Find decoder - const AVCodec* codec = avcodec_find_decoder(avstream_->codecpar->codec_id); + // Find decoder + const AVCodec *codec = avcodec_find_decoder(avstream_->codecpar->codec_id); - // Handle failure to find decoder - if (codec == nullptr) { - qCritical() << "Failed to find appropriate decoder for this codec:" - << filename - << stream_index - << avstream_->codecpar->codec_id; - return false; - } + // Handle failure to find decoder + if (codec == nullptr) { + qCritical() + << "Failed to find appropriate decoder for this codec:" << filename + << stream_index << avstream_->codecpar->codec_id; + return false; + } - // Allocate context for the decoder - codec_ctx_ = avcodec_alloc_context3(codec); - if (codec_ctx_ == nullptr) { - qCritical() << "Failed to allocate codec context"; - return false; - } + // Allocate context for the decoder + codec_ctx_ = avcodec_alloc_context3(codec); + if (codec_ctx_ == nullptr) { + qCritical() << "Failed to allocate codec context"; + return false; + } - // Copy parameters from the AVStream to the AVCodecContext - error_code = avcodec_parameters_to_context(codec_ctx_, avstream_->codecpar); + // Copy parameters from the AVStream to the AVCodecContext + error_code = avcodec_parameters_to_context(codec_ctx_, avstream_->codecpar); - // Handle failure to copy parameters - if (error_code < 0) { - qCritical() << "Failed to copy parameters from AVStream to AVCodecContext"; - return false; - } + // Handle failure to copy parameters + if (error_code < 0) { + qCritical() + << "Failed to copy parameters from AVStream to AVCodecContext"; + return false; + } - // Set multithreading setting - error_code = av_dict_set(&opts_, "threads", "auto", 0); + // Set multithreading setting + error_code = av_dict_set(&opts_, "threads", "auto", 0); - // Handle failure to set multithreaded decoding - if (error_code < 0) { - qCritical() << "Failed to set codec options, performance may suffer"; - } + // Handle failure to set multithreaded decoding + if (error_code < 0) { + qCritical() << "Failed to set codec options, performance may suffer"; + } - // Open codec - error_code = avcodec_open2(codec_ctx_, codec, &opts_); - if (error_code < 0) { - char buf[512]; - av_strerror(error_code, buf, 512); - qCritical() << "Failed to open codec" << codec->id << error_code << buf; - return false; - } + // Open codec + error_code = avcodec_open2(codec_ctx_, codec, &opts_); + if (error_code < 0) { + char buf[512]; + av_strerror(error_code, buf, 512); + qCritical() << "Failed to open codec" << codec->id << error_code << buf; + return false; + } - return true; + return true; } void FFmpegDecoder::Instance::Close() { - if (opts_) { - av_dict_free(&opts_); - opts_ = nullptr; - } + if (opts_) { + av_dict_free(&opts_); + opts_ = nullptr; + } - if (codec_ctx_) { - avcodec_free_context(&codec_ctx_); - codec_ctx_ = nullptr; - } + if (codec_ctx_) { + avcodec_free_context(&codec_ctx_); + codec_ctx_ = nullptr; + } - if (fmt_ctx_) { - avformat_close_input(&fmt_ctx_); - fmt_ctx_ = nullptr; - } + if (fmt_ctx_) { + avformat_close_input(&fmt_ctx_); + fmt_ctx_ = nullptr; + } } int FFmpegDecoder::Instance::GetFrame(AVPacket *pkt, AVFrame *frame) { - bool eof = false; + bool eof = false; - int ret; + int ret; - // Clear any previous frames - av_frame_unref(frame); + // Clear any previous frames + av_frame_unref(frame); - while ((ret = avcodec_receive_frame(codec_ctx_, frame)) == AVERROR(EAGAIN) && !eof) { + while ((ret = avcodec_receive_frame(codec_ctx_, frame)) == + AVERROR(EAGAIN) && + !eof) { + // Find next packet in the correct stream index + ret = GetPacket(pkt); - // Find next packet in the correct stream index - ret = GetPacket(pkt); + if (ret == AVERROR_EOF) { + // Don't break so that receive gets called again, but don't try to read again + eof = true; - if (ret == AVERROR_EOF) { - // Don't break so that receive gets called again, but don't try to read again - eof = true; + // Send a null packet to signal end of + avcodec_send_packet(codec_ctx_, nullptr); + } else if (ret < 0) { + // Handle other error by breaking loop and returning the code we received + break; + } else { + // Successful read, send the packet + ret = avcodec_send_packet(codec_ctx_, pkt); - // Send a null packet to signal end of - avcodec_send_packet(codec_ctx_, nullptr); - } else if (ret < 0) { - // Handle other error by breaking loop and returning the code we received - break; - } else { - // Successful read, send the packet - ret = avcodec_send_packet(codec_ctx_, pkt); + // We don't need the packet anymore, so free it + av_packet_unref(pkt); - // We don't need the packet anymore, so free it - av_packet_unref(pkt); + if (ret < 0) { + break; + } + } + } - if (ret < 0) { - break; - } - } - } - - return ret; + return ret; } const char *FFmpegDecoder::Instance::GetSubtitleHeader() const { - return reinterpret_cast(codec_ctx_->subtitle_header); + return reinterpret_cast(codec_ctx_->subtitle_header); } int FFmpegDecoder::Instance::GetSubtitle(AVPacket *pkt, AVSubtitle *sub) { - int ret = GetPacket(pkt); + int ret = GetPacket(pkt); - if (ret >= 0) { - int got_sub; - ret = avcodec_decode_subtitle2(codec_ctx_, sub, &got_sub, pkt); - if (!got_sub) { - ret = -1; - } - } + if (ret >= 0) { + int got_sub; + ret = avcodec_decode_subtitle2(codec_ctx_, sub, &got_sub, pkt); + if (!got_sub) { + ret = -1; + } + } - return ret; + return ret; } int FFmpegDecoder::Instance::GetPacket(AVPacket *pkt) { - int ret; + int ret; - do { - av_packet_unref(pkt); + do { + av_packet_unref(pkt); - ret = av_read_frame(fmt_ctx_, pkt); - } while (pkt->stream_index != avstream_->index && ret >= 0); + ret = av_read_frame(fmt_ctx_, pkt); + } while (pkt->stream_index != avstream_->index && ret >= 0); - return ret; + return ret; } void FFmpegDecoder::Instance::Seek(int64_t timestamp) { - avcodec_flush_buffers(codec_ctx_); - av_seek_frame(fmt_ctx_, avstream_->index, timestamp, AVSEEK_FLAG_BACKWARD); + avcodec_flush_buffers(codec_ctx_); + av_seek_frame(fmt_ctx_, avstream_->index, timestamp, AVSEEK_FLAG_BACKWARD); } } diff --git a/app/codec/ffmpeg/ffmpegdecoder.h b/app/codec/ffmpeg/ffmpegdecoder.h index 52be8154f..e904ef2f9 100644 --- a/app/codec/ffmpeg/ffmpegdecoder.h +++ b/app/codec/ffmpeg/ffmpegdecoder.h @@ -39,92 +39,100 @@ extern "C" { #include "codec/decoder.h" #include "common/ffmpegutils.h" -namespace olive { +namespace olive +{ /** * @brief A Decoder derivative that wraps FFmpeg functions as on Olive decoder */ -class FFmpegDecoder : public Decoder -{ - Q_OBJECT +class FFmpegDecoder : public Decoder { + Q_OBJECT public: - // Constructor - FFmpegDecoder(); + // Constructor + FFmpegDecoder(); - // Destructor - DECODER_DEFAULT_DESTRUCTOR(FFmpegDecoder) + // Destructor + DECODER_DEFAULT_DESTRUCTOR(FFmpegDecoder) - virtual QString id() const override; + virtual QString id() const override; - virtual bool SupportsVideo() override{return true;} - virtual bool SupportsAudio() override{return true;} + virtual bool SupportsVideo() override + { + return true; + } + virtual bool SupportsAudio() override + { + return true; + } - virtual FootageDescription Probe(const QString &filename, CancelAtom *cancelled) const override; + virtual FootageDescription Probe(const QString &filename, + CancelAtom *cancelled) const override; protected: - virtual bool OpenInternal() override; - virtual TexturePtr RetrieveVideoInternal(const RetrieveVideoParams& p) override; - virtual bool ConformAudioInternal(const QVector& filenames, const AudioParams ¶ms, CancelAtom *cancelled) override; - virtual void CloseInternal() override; + virtual bool OpenInternal() override; + virtual TexturePtr + RetrieveVideoInternal(const RetrieveVideoParams &p) override; + virtual bool ConformAudioInternal(const QVector &filenames, + const AudioParams ¶ms, + CancelAtom *cancelled) override; + virtual void CloseInternal() override; - virtual rational GetAudioStartOffset() const override; + virtual rational GetAudioStartOffset() const override; private: - class Instance - { - public: - Instance(); + class Instance { + public: + Instance(); - ~Instance() - { - Close(); - } + ~Instance() + { + Close(); + } - bool Open(const char* filename, int stream_index); + bool Open(const char *filename, int stream_index); - bool IsOpen() const - { - return fmt_ctx_; - } + bool IsOpen() const + { + return fmt_ctx_; + } - void Close(); + void Close(); - /** + /** * @brief Uses the FFmpeg API to retrieve a packet (stored in pkt_) and decode it (stored in frame_) * * @return * * An FFmpeg error code, or >= 0 on success */ - int GetFrame(AVPacket* pkt, AVFrame* frame); + int GetFrame(AVPacket *pkt, AVFrame *frame); - const char *GetSubtitleHeader() const; + const char *GetSubtitleHeader() const; - int GetSubtitle(AVPacket* pkt, AVSubtitle* sub); + int GetSubtitle(AVPacket *pkt, AVSubtitle *sub); - int GetPacket(AVPacket *pkt); + int GetPacket(AVPacket *pkt); - void Seek(int64_t timestamp); + void Seek(int64_t timestamp); - AVFormatContext* fmt_ctx() const - { - return fmt_ctx_; - } + AVFormatContext *fmt_ctx() const + { + return fmt_ctx_; + } - AVStream* avstream() const - { - return avstream_; - } + AVStream *avstream() const + { + return avstream_; + } - private: - AVFormatContext* fmt_ctx_; - AVCodecContext* codec_ctx_; - AVStream* avstream_; - AVDictionary* opts_; + private: + AVFormatContext *fmt_ctx_; + AVCodecContext *codec_ctx_; + AVStream *avstream_; + AVDictionary *opts_; + }; - }; - - /** + /** * @brief Handle an FFmpeg error code * * Uses the FFmpeg API to retrieve a descriptive string for this error code and sends it to Error(). As such, this @@ -132,54 +140,56 @@ private: * * @param error_code */ - static QString FFmpegError(int error_code); + static QString FFmpegError(int error_code); - void FreeScaler(); + void FreeScaler(); - static PixelFormat GetNativePixelFormat(AVPixelFormat pix_fmt); - static int GetNativeChannelCount(AVPixelFormat pix_fmt); + static PixelFormat GetNativePixelFormat(AVPixelFormat pix_fmt); + static int GetNativeChannelCount(AVPixelFormat pix_fmt); - static AVChannelLayout ValidateChannelLayout(AVStream *stream); + static AVChannelLayout ValidateChannelLayout(AVStream *stream); - static const char* GetInterlacingModeInFFmpeg(VideoParams::Interlacing interlacing); + static const char * + GetInterlacingModeInFFmpeg(VideoParams::Interlacing interlacing); - static bool IsPixelFormatGLSLCompatible(AVPixelFormat f); + static bool IsPixelFormatGLSLCompatible(AVPixelFormat f); - AVFramePtr GetFrameFromCache(const int64_t &t) const; + AVFramePtr GetFrameFromCache(const int64_t &t) const; - void ClearFrameCache(); + void ClearFrameCache(); - AVFramePtr PreProcessFrame(AVFramePtr f, const RetrieveVideoParams &p); + AVFramePtr PreProcessFrame(AVFramePtr f, const RetrieveVideoParams &p); - TexturePtr ProcessFrameIntoTexture(AVFramePtr f, const RetrieveVideoParams &p, const AVFramePtr original); + TexturePtr ProcessFrameIntoTexture(AVFramePtr f, + const RetrieveVideoParams &p, + const AVFramePtr original); - AVFramePtr RetrieveFrame(const rational &time, CancelAtom *cancelled); + AVFramePtr RetrieveFrame(const rational &time, CancelAtom *cancelled); - void RemoveFirstFrame(); + void RemoveFirstFrame(); - static int MaximumQueueSize(); + static int MaximumQueueSize(); - SwsContext *sws_ctx_; - int sws_src_width_; - int sws_src_height_; - AVPixelFormat sws_src_format_; - int sws_dst_width_; - int sws_dst_height_; - AVPixelFormat sws_dst_format_; - AVColorRange sws_colrange_; - AVColorSpace sws_colspace_; + SwsContext *sws_ctx_; + int sws_src_width_; + int sws_src_height_; + AVPixelFormat sws_src_format_; + int sws_dst_width_; + int sws_dst_height_; + AVPixelFormat sws_dst_format_; + AVColorRange sws_colrange_; + AVColorSpace sws_colspace_; - AVPacket *working_packet_; + AVPacket *working_packet_; - int64_t second_ts_; + int64_t second_ts_; - std::list cached_frames_; + std::list cached_frames_; - bool cache_at_zero_; - bool cache_at_eof_; - - Instance instance_; + bool cache_at_zero_; + bool cache_at_eof_; + Instance instance_; }; } diff --git a/app/codec/ffmpeg/ffmpegencoder.cpp b/app/codec/ffmpeg/ffmpegencoder.cpp index f34e7b30b..5f7ea1d87 100644 --- a/app/codec/ffmpeg/ffmpegencoder.cpp +++ b/app/codec/ffmpeg/ffmpegencoder.cpp @@ -30,401 +30,455 @@ extern "C" { #include "common/ffmpegutils.h" -namespace olive { +namespace olive +{ -FFmpegEncoder::FFmpegEncoder(const EncodingParams ¶ms) : - Encoder(params), - fmt_ctx_(nullptr), - video_stream_(nullptr), - video_codec_ctx_(nullptr), - video_scale_ctx_(nullptr), - video_buffersrc_ctx_(nullptr), - video_buffersink_ctx_(nullptr), - audio_stream_(nullptr), - audio_codec_ctx_(nullptr), - audio_resample_ctx_(nullptr), - audio_frame_(nullptr), - open_(false) +FFmpegEncoder::FFmpegEncoder(const EncodingParams ¶ms) + : Encoder(params) + , fmt_ctx_(nullptr) + , video_stream_(nullptr) + , video_codec_ctx_(nullptr) + , video_scale_ctx_(nullptr) + , video_buffersrc_ctx_(nullptr) + , video_buffersink_ctx_(nullptr) + , audio_stream_(nullptr) + , audio_codec_ctx_(nullptr) + , audio_resample_ctx_(nullptr) + , audio_frame_(nullptr) + , open_(false) { } QStringList FFmpegEncoder::GetPixelFormatsForCodec(ExportCodec::Codec c) const { - QStringList pix_fmts; + QStringList pix_fmts; - const AVCodec* codec_info = GetEncoder(c, SampleFormat::INVALID); + const AVCodec *codec_info = GetEncoder(c, SampleFormat::INVALID); - if (codec_info) { - for (int i=0; codec_info->pix_fmts[i]!=-1; i++) { - if (FFmpegUtils::ConvertJPEGSpaceToRegularSpace(codec_info->pix_fmts[i]) != codec_info->pix_fmts[i]) { - // This is a deprecated "JPEG" space, skip it - continue; - } + if (codec_info) { + for (int i = 0; codec_info->pix_fmts[i] != -1; i++) { + if (FFmpegUtils::ConvertJPEGSpaceToRegularSpace( + codec_info->pix_fmts[i]) != codec_info->pix_fmts[i]) { + // This is a deprecated "JPEG" space, skip it + continue; + } - const char* pix_fmt_name = av_get_pix_fmt_name(codec_info->pix_fmts[i]); - pix_fmts.append(pix_fmt_name); - } - } + const char *pix_fmt_name = + av_get_pix_fmt_name(codec_info->pix_fmts[i]); + pix_fmts.append(pix_fmt_name); + } + } - return pix_fmts; + return pix_fmts; } -std::vector FFmpegEncoder::GetSampleFormatsForCodec(ExportCodec::Codec c) const +std::vector +FFmpegEncoder::GetSampleFormatsForCodec(ExportCodec::Codec c) const { - std::vector f; + std::vector f; - if (c == ExportCodec::kCodecPCM) { - // FFmpeg lists these as separate codecs so we need custom functionality here - // We list signed 16 first because ExportDialog will always use the first element by default - // (because first element is the "default" in tFFmpeg) - f = { - SampleFormat::S16, - SampleFormat::U8, - SampleFormat::S32, - SampleFormat::S64, - SampleFormat::F32, - SampleFormat::F64 - }; - } else { - const AVCodec* codec_info = GetEncoder(c, SampleFormat::INVALID); + if (c == ExportCodec::kCodecPCM) { + // FFmpeg lists these as separate codecs so we need custom functionality here + // We list signed 16 first because ExportDialog will always use the first element by default + // (because first element is the "default" in tFFmpeg) + f = { SampleFormat::S16, SampleFormat::U8, SampleFormat::S32, + SampleFormat::S64, SampleFormat::F32, SampleFormat::F64 }; + } else { + const AVCodec *codec_info = GetEncoder(c, SampleFormat::INVALID); - if (codec_info && codec_info->sample_fmts) { - for (int i=0; codec_info->sample_fmts[i]!=-1; i++) { - SampleFormat this_format = FFmpegUtils::GetNativeSampleFormat(static_cast(codec_info->sample_fmts[i])); - if (this_format != SampleFormat::INVALID) { - f.push_back(this_format); - } - } - } - } + if (codec_info && codec_info->sample_fmts) { + for (int i = 0; codec_info->sample_fmts[i] != -1; i++) { + SampleFormat this_format = FFmpegUtils::GetNativeSampleFormat( + static_cast(codec_info->sample_fmts[i])); + if (this_format != SampleFormat::INVALID) { + f.push_back(this_format); + } + } + } + } - return f; + return f; } bool FFmpegEncoder::Open() { - if (open_) { - return true; - } + if (open_) { + return true; + } - int error_code; + int error_code; - // Convert QString to C string that FFmpeg expects - QByteArray filename_bytes = params().filename().toUtf8(); - const char* filename_c_str = filename_bytes.constData(); + // Convert QString to C string that FFmpeg expects + QByteArray filename_bytes = params().filename().toUtf8(); + const char *filename_c_str = filename_bytes.constData(); - // Create output format context - error_code = avformat_alloc_output_context2(&fmt_ctx_, nullptr, nullptr, filename_c_str); + // Create output format context + error_code = avformat_alloc_output_context2(&fmt_ctx_, nullptr, nullptr, + filename_c_str); - // Check error code - if (error_code < 0) { - FFmpegError(tr("Failed to allocate output context"), error_code); - return false; - } + // Check error code + if (error_code < 0) { + FFmpegError(tr("Failed to allocate output context"), error_code); + return false; + } - // Initialize a video stream if it's enabled - if (params().video_enabled()) { - if (!InitializeStream(AVMEDIA_TYPE_VIDEO, &video_stream_, &video_codec_ctx_, params().video_codec())) { - return false; - } + // Initialize a video stream if it's enabled + if (params().video_enabled()) { + if (!InitializeStream(AVMEDIA_TYPE_VIDEO, &video_stream_, + &video_codec_ctx_, params().video_codec())) { + return false; + } - // This is the format we will expect frames received in Write() to be in - PixelFormat native_pixel_fmt = params().video_params().format(); + // This is the format we will expect frames received in Write() to be in + PixelFormat native_pixel_fmt = params().video_params().format(); - // This is the format we will need to convert the frame to for swscale to understand it - video_conversion_fmt_ = FFmpegUtils::GetCompatiblePixelFormat(native_pixel_fmt); + // This is the format we will need to convert the frame to for swscale to understand it + video_conversion_fmt_ = + FFmpegUtils::GetCompatiblePixelFormat(native_pixel_fmt); - // This is the equivalent pixel format above as an AVPixelFormat that swscale can understand - AVPixelFormat src_alpha_pix_fmt = FFmpegUtils::GetFFmpegPixelFormat(video_conversion_fmt_, - VideoParams::kRGBAChannelCount); + // This is the equivalent pixel format above as an AVPixelFormat that swscale can understand + AVPixelFormat src_alpha_pix_fmt = FFmpegUtils::GetFFmpegPixelFormat( + video_conversion_fmt_, VideoParams::kRGBAChannelCount); - AVPixelFormat src_noalpha_pix_fmt = FFmpegUtils::GetFFmpegPixelFormat(video_conversion_fmt_, - VideoParams::kRGBChannelCount); + AVPixelFormat src_noalpha_pix_fmt = FFmpegUtils::GetFFmpegPixelFormat( + video_conversion_fmt_, VideoParams::kRGBChannelCount); - if (src_alpha_pix_fmt == AV_PIX_FMT_NONE || src_noalpha_pix_fmt == AV_PIX_FMT_NONE) { - SetError(tr("Failed to find suitable pixel format for this buffer")); - return false; - } + if (src_alpha_pix_fmt == AV_PIX_FMT_NONE || + src_noalpha_pix_fmt == AV_PIX_FMT_NONE) { + SetError( + tr("Failed to find suitable pixel format for this buffer")); + return false; + } - // This is the pixel format the encoder wants to encode to - AVPixelFormat encoder_pix_fmt = video_codec_ctx_->pix_fmt; + // This is the pixel format the encoder wants to encode to + AVPixelFormat encoder_pix_fmt = video_codec_ctx_->pix_fmt; - video_scale_ctx_ = avfilter_graph_alloc(); - if (!video_scale_ctx_) { - return false; - } + video_scale_ctx_ = avfilter_graph_alloc(); + if (!video_scale_ctx_) { + return false; + } - static const int FILTER_ARG_SZ = 1024; - char filter_args[FILTER_ARG_SZ]; + static const int FILTER_ARG_SZ = 1024; + char filter_args[FILTER_ARG_SZ]; - snprintf(filter_args, FILTER_ARG_SZ, "video_size=%dx%d:pix_fmt=%d:time_base=%d/%d:pixel_aspect=%d/%d", - params().video_params().effective_width(), - params().video_params().effective_height(), - src_alpha_pix_fmt, - params().video_params().time_base().numerator(), - params().video_params().time_base().denominator(), - params().video_params().pixel_aspect_ratio().numerator(), - params().video_params().pixel_aspect_ratio().denominator()); + snprintf( + filter_args, FILTER_ARG_SZ, + "video_size=%dx%d:pix_fmt=%d:time_base=%d/%d:pixel_aspect=%d/%d", + params().video_params().effective_width(), + params().video_params().effective_height(), src_alpha_pix_fmt, + params().video_params().time_base().numerator(), + params().video_params().time_base().denominator(), + params().video_params().pixel_aspect_ratio().numerator(), + params().video_params().pixel_aspect_ratio().denominator()); - avfilter_graph_create_filter(&video_buffersrc_ctx_, avfilter_get_by_name("buffer"), "in", filter_args, nullptr, video_scale_ctx_); - avfilter_graph_create_filter(&video_buffersink_ctx_, avfilter_get_by_name("buffersink"), "out", nullptr, nullptr, video_scale_ctx_); + avfilter_graph_create_filter(&video_buffersrc_ctx_, + avfilter_get_by_name("buffer"), "in", + filter_args, nullptr, video_scale_ctx_); + avfilter_graph_create_filter(&video_buffersink_ctx_, + avfilter_get_by_name("buffersink"), "out", + nullptr, nullptr, video_scale_ctx_); - AVFilterContext *last_filter = video_buffersrc_ctx_; + AVFilterContext *last_filter = video_buffersrc_ctx_; - { - // Set color range - AVFilterContext* range_filter; + { + // Set color range + AVFilterContext *range_filter; - snprintf(filter_args, FILTER_ARG_SZ, "in_range=full:out_range=%s", - params().video_params().color_range() == VideoParams::kColorRangeFull ? "full" : "limited"); + snprintf(filter_args, FILTER_ARG_SZ, "in_range=full:out_range=%s", + params().video_params().color_range() == + VideoParams::kColorRangeFull ? + "full" : + "limited"); - avfilter_graph_create_filter(&range_filter, avfilter_get_by_name("scale"), "range", filter_args, nullptr, video_scale_ctx_); + avfilter_graph_create_filter(&range_filter, + avfilter_get_by_name("scale"), "range", + filter_args, nullptr, + video_scale_ctx_); - avfilter_link(last_filter, 0, range_filter, 0); - last_filter = range_filter; - } + avfilter_link(last_filter, 0, range_filter, 0); + last_filter = range_filter; + } - if (src_alpha_pix_fmt != encoder_pix_fmt) { - // Transform pixel format - AVFilterContext* format_filter; + if (src_alpha_pix_fmt != encoder_pix_fmt) { + // Transform pixel format + AVFilterContext *format_filter; - snprintf(filter_args, FILTER_ARG_SZ, "pix_fmts=%u", encoder_pix_fmt); + snprintf(filter_args, FILTER_ARG_SZ, "pix_fmts=%u", + encoder_pix_fmt); - avfilter_graph_create_filter(&format_filter, avfilter_get_by_name("format"), "format", filter_args, nullptr, video_scale_ctx_); + avfilter_graph_create_filter(&format_filter, + avfilter_get_by_name("format"), + "format", filter_args, nullptr, + video_scale_ctx_); - avfilter_link(last_filter, 0, format_filter, 0); - last_filter = format_filter; - } + avfilter_link(last_filter, 0, format_filter, 0); + last_filter = format_filter; + } - avfilter_link(last_filter, 0, video_buffersink_ctx_, 0); + avfilter_link(last_filter, 0, video_buffersink_ctx_, 0); - if (avfilter_graph_config(video_scale_ctx_, nullptr) < 0) { - SetError(tr("Failed to configure filter graph")); - return false; - } - } + if (avfilter_graph_config(video_scale_ctx_, nullptr) < 0) { + SetError(tr("Failed to configure filter graph")); + return false; + } + } - // Initialize an audio stream if it's enabled - if (params().audio_enabled()) { - if (!InitializeStream(AVMEDIA_TYPE_AUDIO, &audio_stream_, &audio_codec_ctx_, params().audio_codec())) { - return false; - } - } + // Initialize an audio stream if it's enabled + if (params().audio_enabled()) { + if (!InitializeStream(AVMEDIA_TYPE_AUDIO, &audio_stream_, + &audio_codec_ctx_, params().audio_codec())) { + return false; + } + } - // Initialize a subtitle stream if it's enabled - if (params().subtitles_enabled()) { - if (!InitializeStream(AVMEDIA_TYPE_SUBTITLE, &subtitle_stream_, &subtitle_codec_ctx_, params().subtitles_codec())) { - return false; - } - } + // Initialize a subtitle stream if it's enabled + if (params().subtitles_enabled()) { + if (!InitializeStream(AVMEDIA_TYPE_SUBTITLE, &subtitle_stream_, + &subtitle_codec_ctx_, + params().subtitles_codec())) { + return false; + } + } - av_dump_format(fmt_ctx_, 0, filename_c_str, 1); + av_dump_format(fmt_ctx_, 0, filename_c_str, 1); - // Open output file for writing - error_code = avio_open(&fmt_ctx_->pb, filename_c_str, AVIO_FLAG_WRITE); - if (error_code < 0) { - FFmpegError(tr("Failed to open IO context"), error_code); - return false; - } + // Open output file for writing + error_code = avio_open(&fmt_ctx_->pb, filename_c_str, AVIO_FLAG_WRITE); + if (error_code < 0) { + FFmpegError(tr("Failed to open IO context"), error_code); + return false; + } - // Write header - error_code = avformat_write_header(fmt_ctx_, nullptr); - if (error_code < 0) { - FFmpegError(tr("Failed to write format header"), error_code); - return false; - } + // Write header + error_code = avformat_write_header(fmt_ctx_, nullptr); + if (error_code < 0) { + FFmpegError(tr("Failed to write format header"), error_code); + return false; + } - open_ = true; - return true; + open_ = true; + return true; } bool FFmpegEncoder::WriteFrame(FramePtr frame, rational time) { - // We may need to convert this frame to a frame that swscale will understand - if (frame->format() != video_conversion_fmt_) { - frame = frame->convert(video_conversion_fmt_); - } + // We may need to convert this frame to a frame that swscale will understand + if (frame->format() != video_conversion_fmt_) { + frame = frame->convert(video_conversion_fmt_); + } - // Use swscale context to convert formats/linesizes - AVFramePtr input_frame = CreateAVFramePtr(av_frame_alloc()); - input_frame->width = frame->width(); - input_frame->height = frame->height(); - input_frame->format = FFmpegUtils::GetFFmpegPixelFormat(frame->format(), frame->channel_count()); - input_frame->data[0] = reinterpret_cast(frame->data()); - input_frame->linesize[0] = frame->linesize_bytes(); + // Use swscale context to convert formats/linesizes + AVFramePtr input_frame = CreateAVFramePtr(av_frame_alloc()); + input_frame->width = frame->width(); + input_frame->height = frame->height(); + input_frame->format = FFmpegUtils::GetFFmpegPixelFormat( + frame->format(), frame->channel_count()); + input_frame->data[0] = reinterpret_cast(frame->data()); + input_frame->linesize[0] = frame->linesize_bytes(); - input_frame->color_primaries = video_codec_ctx_->color_primaries; - input_frame->color_trc = video_codec_ctx_->color_trc; - input_frame->colorspace = video_codec_ctx_->colorspace; - input_frame->color_range = video_codec_ctx_->color_range; + input_frame->color_primaries = video_codec_ctx_->color_primaries; + input_frame->color_trc = video_codec_ctx_->color_trc; + input_frame->colorspace = video_codec_ctx_->colorspace; + input_frame->color_range = video_codec_ctx_->color_range; - int r; - r = av_buffersrc_add_frame_flags(video_buffersrc_ctx_, input_frame.get(), AV_BUFFERSRC_FLAG_KEEP_REF); - if (r < 0) { - FFmpegError(tr("Failed to add frame to filter graph"), r); - return false; - } + int r; + r = av_buffersrc_add_frame_flags(video_buffersrc_ctx_, input_frame.get(), + AV_BUFFERSRC_FLAG_KEEP_REF); + if (r < 0) { + FFmpegError(tr("Failed to add frame to filter graph"), r); + return false; + } - AVFramePtr encoded_frame = CreateAVFramePtr(av_frame_alloc()); - r = av_buffersink_get_frame(video_buffersink_ctx_, encoded_frame.get()); - if (r < 0) { - FFmpegError(tr("Failed to retrieve frame from buffer sink"), r); - return false; - } + AVFramePtr encoded_frame = CreateAVFramePtr(av_frame_alloc()); + r = av_buffersink_get_frame(video_buffersink_ctx_, encoded_frame.get()); + if (r < 0) { + FFmpegError(tr("Failed to retrieve frame from buffer sink"), r); + return false; + } - encoded_frame->pts = qRound64(time.toDouble() / av_q2d(video_codec_ctx_->time_base)); + encoded_frame->pts = + qRound64(time.toDouble() / av_q2d(video_codec_ctx_->time_base)); - return WriteAVFrame(encoded_frame.get(), video_codec_ctx_, video_stream_); + return WriteAVFrame(encoded_frame.get(), video_codec_ctx_, video_stream_); } bool FFmpegEncoder::WriteAudio(const SampleBuffer &audio) { - if (!audio.is_allocated()) { - return true; - } + if (!audio.is_allocated()) { + return true; + } - bool result = true; + bool result = true; - size_t start = 0; - size_t end = audio.sample_count(); - const size_t max_frame = 48000; + size_t start = 0; + size_t end = audio.sample_count(); + const size_t max_frame = 48000; - while (result && start < end) { - // Create input buffer - uint8_t** input_data = nullptr; - size_t input_sample_count = std::min(end - start, max_frame); - int input_linesize; + while (result && start < end) { + // Create input buffer + uint8_t **input_data = nullptr; + size_t input_sample_count = std::min(end - start, max_frame); + int input_linesize; - int r = av_samples_alloc_array_and_samples(&input_data, &input_linesize, audio.audio_params().channel_count(), - input_sample_count, FFmpegUtils::GetFFmpegSampleFormat(audio.audio_params().format()), 0); + int r = av_samples_alloc_array_and_samples( + &input_data, &input_linesize, audio.audio_params().channel_count(), + input_sample_count, + FFmpegUtils::GetFFmpegSampleFormat(audio.audio_params().format()), + 0); - if (r < 0) { - FFmpegError(tr("Failed to allocate sample array"), r); - return false; - } else { - int bpsc = audio.audio_params().bytes_per_sample_per_channel(); - for (int i=0; i(input_data), input_sample_count); + result = WriteAudioData(audio.audio_params().is_valid() ? + audio.audio_params() : + params().audio_params(), + const_cast(input_data), + input_sample_count); - if (input_data) { - av_freep(&input_data[0]); - av_freep(&input_data); - } - } + if (input_data) { + av_freep(&input_data[0]); + av_freep(&input_data); + } + } - return result; + return result; } -bool FFmpegEncoder::WriteAudioData(const AudioParams &audio_params, const uint8_t **input_data, int input_sample_count) +bool FFmpegEncoder::WriteAudioData(const AudioParams &audio_params, + const uint8_t **input_data, + int input_sample_count) { - if (!InitializeResampleContext(audio_params)) { - qCritical() << "Failed to initialize resample context"; - return false; - } + if (!InitializeResampleContext(audio_params)) { + qCritical() << "Failed to initialize resample context"; + return false; + } - bool result = true; + bool result = true; - // Create output buffer - int output_sample_count = input_sample_count ? swr_get_out_samples(audio_resample_ctx_, input_sample_count) : 102400; - uint8_t** output_data = nullptr; - int output_linesize; - av_samples_alloc_array_and_samples(&output_data, &output_linesize, audio_stream_->codecpar->ch_layout.nb_channels, - output_sample_count, static_cast(audio_stream_->codecpar->format), 0); + // Create output buffer + int output_sample_count = + input_sample_count ? + swr_get_out_samples(audio_resample_ctx_, input_sample_count) : + 102400; + uint8_t **output_data = nullptr; + int output_linesize; + av_samples_alloc_array_and_samples( + &output_data, &output_linesize, + audio_stream_->codecpar->ch_layout.nb_channels, output_sample_count, + static_cast(audio_stream_->codecpar->format), 0); - // Perform conversion - int converted = swr_convert(audio_resample_ctx_, output_data, output_sample_count, const_cast(input_data), input_sample_count); - if (converted > 0) { - // Split sample buffer into frames - for (int i=0; i(input_data), + input_sample_count); + if (converted > 0) { + // Split sample buffer into frames + for (int i = 0; i < converted;) { + int frame_remaining_samples = + audio_max_samples_ - audio_frame_offset_; + int converted_remaining_samples = converted - i; - int copy_length = qMin(frame_remaining_samples, converted_remaining_samples); + int copy_length = + qMin(frame_remaining_samples, converted_remaining_samples); - av_samples_copy(audio_frame_->data, output_data, audio_frame_offset_, i, - copy_length, - audio_frame_->ch_layout.nb_channels, static_cast(audio_frame_->format)); + av_samples_copy(audio_frame_->data, output_data, + audio_frame_offset_, i, copy_length, + audio_frame_->ch_layout.nb_channels, + static_cast(audio_frame_->format)); - audio_frame_offset_ += copy_length; - i += copy_length; + audio_frame_offset_ += copy_length; + i += copy_length; - if (audio_frame_offset_ == audio_max_samples_ || (i == converted && !input_data)) { - // Got all the samples we needed, write the frame - audio_frame_->pts = av_rescale_q(audio_write_count_, {1, audio_codec_ctx_->sample_rate}, audio_codec_ctx_->time_base); + if (audio_frame_offset_ == audio_max_samples_ || + (i == converted && !input_data)) { + // Got all the samples we needed, write the frame + audio_frame_->pts = av_rescale_q( + audio_write_count_, { 1, audio_codec_ctx_->sample_rate }, + audio_codec_ctx_->time_base); - WriteAVFrame(audio_frame_, audio_codec_ctx_, audio_stream_); - audio_write_count_ += audio_frame_offset_; - audio_frame_offset_ = 0; - } - } - } else if (converted < 0) { - FFmpegError(tr("Failed to resample audio"), converted); - result = false; - } + WriteAVFrame(audio_frame_, audio_codec_ctx_, audio_stream_); + audio_write_count_ += audio_frame_offset_; + audio_frame_offset_ = 0; + } + } + } else if (converted < 0) { + FFmpegError(tr("Failed to resample audio"), converted); + result = false; + } - if (!input_data && audio_frame_offset_ > 0) { - audio_frame_->nb_samples = audio_frame_offset_; - audio_frame_->pts = av_rescale_q(audio_write_count_, {1, audio_codec_ctx_->sample_rate}, audio_codec_ctx_->time_base); - WriteAVFrame(audio_frame_, audio_codec_ctx_, audio_stream_); - } + if (!input_data && audio_frame_offset_ > 0) { + audio_frame_->nb_samples = audio_frame_offset_; + audio_frame_->pts = av_rescale_q(audio_write_count_, + { 1, audio_codec_ctx_->sample_rate }, + audio_codec_ctx_->time_base); + WriteAVFrame(audio_frame_, audio_codec_ctx_, audio_stream_); + } - // Free buffers created - if (output_data) { - av_freep(&output_data[0]); - av_freep(&output_data); - } + // Free buffers created + if (output_data) { + av_freep(&output_data[0]); + av_freep(&output_data); + } - return result; + return result; } QString GetAssTime(const rational &time) { - int64_t total_centiseconds = qRound64(time.toDouble() * 100); + int64_t total_centiseconds = qRound64(time.toDouble() * 100); - int64_t cs = total_centiseconds % 100; - int64_t ss = (total_centiseconds / 100) % 60; - int64_t mm = (total_centiseconds / 6000) % 60; - int64_t hh = total_centiseconds / 360000; + int64_t cs = total_centiseconds % 100; + int64_t ss = (total_centiseconds / 100) % 60; + int64_t mm = (total_centiseconds / 6000) % 60; + int64_t hh = total_centiseconds / 360000; - return QStringLiteral("%1:%2:%3.%4").arg( - QString::number(hh), - QStringLiteral("%1").arg(mm, 2, 10, QLatin1Char('0')), - QStringLiteral("%1").arg(ss, 2, 10, QLatin1Char('0')), - QStringLiteral("%1").arg(cs, 2, 10, QLatin1Char('0')) - ); + return QStringLiteral("%1:%2:%3.%4") + .arg(QString::number(hh), + QStringLiteral("%1").arg(mm, 2, 10, QLatin1Char('0')), + QStringLiteral("%1").arg(ss, 2, 10, QLatin1Char('0')), + QStringLiteral("%1").arg(cs, 2, 10, QLatin1Char('0'))); } bool FFmpegEncoder::WriteSubtitle(const SubtitleBlock *sub_block) { - QByteArray utf8_sub = sub_block->GetText().toUtf8(); + QByteArray utf8_sub = sub_block->GetText().toUtf8(); - AVPacket *pkt = av_packet_alloc(); + AVPacket *pkt = av_packet_alloc(); - pkt->stream_index = subtitle_stream_->index; - pkt->data = (uint8_t *) utf8_sub.data(); - pkt->size = utf8_sub.size(); - pkt->pts = Timecode::time_to_timestamp(sub_block->in(), subtitle_codec_ctx_->time_base, Timecode::kFloor); - pkt->duration = av_rescale_q(qRound64(sub_block->length().toDouble() * 1000), {1, 1000}, subtitle_codec_ctx_->time_base); - pkt->dts = pkt->pts; - av_packet_rescale_ts(pkt, subtitle_codec_ctx_->time_base, subtitle_stream_->time_base); + pkt->stream_index = subtitle_stream_->index; + pkt->data = (uint8_t *)utf8_sub.data(); + pkt->size = utf8_sub.size(); + pkt->pts = Timecode::time_to_timestamp( + sub_block->in(), subtitle_codec_ctx_->time_base, Timecode::kFloor); + pkt->duration = + av_rescale_q(qRound64(sub_block->length().toDouble() * 1000), + { 1, 1000 }, subtitle_codec_ctx_->time_base); + pkt->dts = pkt->pts; + av_packet_rescale_ts(pkt, subtitle_codec_ctx_->time_base, + subtitle_stream_->time_base); - int err = av_interleaved_write_frame(fmt_ctx_, pkt); - bool ret = true; + int err = av_interleaved_write_frame(fmt_ctx_, pkt); + bool ret = true; - if (err < 0) { - FFmpegError(tr("Failed to write interleaved packet"), err); - ret = false; - } + if (err < 0) { + FFmpegError(tr("Failed to write interleaved packet"), err); + ret = false; + } - av_packet_free(&pkt); + av_packet_free(&pkt); - return ret; + return ret; } /* @@ -489,471 +543,497 @@ void FFmpegEncoder::WriteAudio(AudioParams pcm_info, QIODevice* file) void FFmpegEncoder::Close() { - if (open_) { - // Flush encoders - FlushEncoders(); + if (open_) { + // Flush encoders + FlushEncoders(); - // We've written a header, so we'll write a trailer - av_write_trailer(fmt_ctx_); - avio_closep(&fmt_ctx_->pb); + // We've written a header, so we'll write a trailer + av_write_trailer(fmt_ctx_); + avio_closep(&fmt_ctx_->pb); - open_ = false; - } + open_ = false; + } - if (audio_resample_ctx_) { - swr_init(audio_resample_ctx_); - audio_resample_ctx_ = nullptr; - } + if (audio_resample_ctx_) { + swr_init(audio_resample_ctx_); + audio_resample_ctx_ = nullptr; + } - if (audio_frame_) { - av_frame_free(&audio_frame_); - audio_frame_ = nullptr; - } + if (audio_frame_) { + av_frame_free(&audio_frame_); + audio_frame_ = nullptr; + } - if (video_scale_ctx_) { - avfilter_graph_free(&video_scale_ctx_); - video_scale_ctx_ = nullptr; - video_buffersrc_ctx_ = nullptr; - video_buffersink_ctx_ = nullptr; - } + if (video_scale_ctx_) { + avfilter_graph_free(&video_scale_ctx_); + video_scale_ctx_ = nullptr; + video_buffersrc_ctx_ = nullptr; + video_buffersink_ctx_ = nullptr; + } - if (video_codec_ctx_) { - avcodec_free_context(&video_codec_ctx_); - video_codec_ctx_ = nullptr; - } + if (video_codec_ctx_) { + avcodec_free_context(&video_codec_ctx_); + video_codec_ctx_ = nullptr; + } - if (audio_codec_ctx_) { - avcodec_free_context(&audio_codec_ctx_); - audio_codec_ctx_ = nullptr; - } + if (audio_codec_ctx_) { + avcodec_free_context(&audio_codec_ctx_); + audio_codec_ctx_ = nullptr; + } - if (fmt_ctx_) { - // NOTE: This also frees video_stream_ and audio_stream_ - avformat_free_context(fmt_ctx_); - fmt_ctx_ = nullptr; - video_stream_ = nullptr; - audio_stream_ = nullptr; - } + if (fmt_ctx_) { + // NOTE: This also frees video_stream_ and audio_stream_ + avformat_free_context(fmt_ctx_); + fmt_ctx_ = nullptr; + video_stream_ = nullptr; + audio_stream_ = nullptr; + } } -void FFmpegEncoder::FFmpegError(const QString& context, int error_code) +void FFmpegEncoder::FFmpegError(const QString &context, int error_code) { - char err[1024]; - av_strerror(error_code, err, 1024); + char err[1024]; + av_strerror(error_code, err, 1024); - QString formatted_err = tr("%1: %2 %3").arg(context, err, QString::number(error_code)); - qDebug() << formatted_err; - SetError(formatted_err); + QString formatted_err = + tr("%1: %2 %3").arg(context, err, QString::number(error_code)); + qDebug() << formatted_err; + SetError(formatted_err); } -bool FFmpegEncoder::WriteAVFrame(AVFrame *frame, AVCodecContext* codec_ctx, AVStream* stream) +bool FFmpegEncoder::WriteAVFrame(AVFrame *frame, AVCodecContext *codec_ctx, + AVStream *stream) { - // Send raw frame to the encoder - int error_code = avcodec_send_frame(codec_ctx, frame); - if (error_code < 0) { - FFmpegError(tr("Failed to send frame to encoder"), error_code); - return false; - } + // Send raw frame to the encoder + int error_code = avcodec_send_frame(codec_ctx, frame); + if (error_code < 0) { + FFmpegError(tr("Failed to send frame to encoder"), error_code); + return false; + } - bool succeeded = false; + bool succeeded = false; - AVPacket* pkt = av_packet_alloc(); + AVPacket *pkt = av_packet_alloc(); - // Retrieve packets from encoder - while (error_code >= 0) { - error_code = avcodec_receive_packet(codec_ctx, pkt); + // Retrieve packets from encoder + while (error_code >= 0) { + error_code = avcodec_receive_packet(codec_ctx, pkt); - // EAGAIN just means the encoder wants another frame before encoding - if (error_code == AVERROR(EAGAIN)) { - break; - } else if (error_code < 0) { - FFmpegError(tr("Failed to receive packet from decoder"), error_code); - goto fail; - } + // EAGAIN just means the encoder wants another frame before encoding + if (error_code == AVERROR(EAGAIN)) { + break; + } else if (error_code < 0) { + FFmpegError(tr("Failed to receive packet from decoder"), + error_code); + goto fail; + } - // Set packet stream index - pkt->stream_index = stream->index; + // Set packet stream index + pkt->stream_index = stream->index; - av_packet_rescale_ts(pkt, codec_ctx->time_base, stream->time_base); + av_packet_rescale_ts(pkt, codec_ctx->time_base, stream->time_base); - // Write packet to file - error_code = av_interleaved_write_frame(fmt_ctx_, pkt); - if (error_code < 0) { - FFmpegError(tr("Failed to write interleaved packet"), error_code); - goto fail; - } + // Write packet to file + error_code = av_interleaved_write_frame(fmt_ctx_, pkt); + if (error_code < 0) { + FFmpegError(tr("Failed to write interleaved packet"), error_code); + goto fail; + } - // Unref packet in case we're getting another - av_packet_unref(pkt); - } + // Unref packet in case we're getting another + av_packet_unref(pkt); + } - succeeded = true; + succeeded = true; fail: - av_packet_free(&pkt); + av_packet_free(&pkt); - return succeeded; + return succeeded; } -bool FFmpegEncoder::InitializeStream(AVMediaType type, AVStream** stream_ptr, AVCodecContext** codec_ctx_ptr, const ExportCodec::Codec& codec) +bool FFmpegEncoder::InitializeStream(AVMediaType type, AVStream **stream_ptr, + AVCodecContext **codec_ctx_ptr, + const ExportCodec::Codec &codec) { - if (type != AVMEDIA_TYPE_VIDEO && type != AVMEDIA_TYPE_AUDIO && type != AVMEDIA_TYPE_SUBTITLE) { - SetError(tr("Cannot initialize a stream that is not a video, audio, or subtitle type")); - return false; - } + if (type != AVMEDIA_TYPE_VIDEO && type != AVMEDIA_TYPE_AUDIO && + type != AVMEDIA_TYPE_SUBTITLE) { + SetError(tr( + "Cannot initialize a stream that is not a video, audio, or subtitle type")); + return false; + } - // Find encoder - const AVCodec* encoder = GetEncoder(codec, params().audio_params().format()); - if (!encoder) { - SetError(tr("Failed to find codec for 0x%1").arg(codec, 16)); - return false; - } + // Find encoder + const AVCodec *encoder = + GetEncoder(codec, params().audio_params().format()); + if (!encoder) { + SetError(tr("Failed to find codec for 0x%1").arg(codec, 16)); + return false; + } - if (encoder->type != type) { - SetError(tr("Retrieved unexpected codec type %1 for codec %2").arg(QString::number(encoder->type), QString::number(codec))); - return false; - } + if (encoder->type != type) { + SetError( + tr("Retrieved unexpected codec type %1 for codec %2") + .arg(QString::number(encoder->type), QString::number(codec))); + return false; + } - if (!InitializeCodecContext(stream_ptr, codec_ctx_ptr, encoder)) { - return false; - } + if (!InitializeCodecContext(stream_ptr, codec_ctx_ptr, encoder)) { + return false; + } - // Set codec parameters - AVCodecContext* codec_ctx = *codec_ctx_ptr; - AVStream* stream = *stream_ptr; + // Set codec parameters + AVCodecContext *codec_ctx = *codec_ctx_ptr; + AVStream *stream = *stream_ptr; - if (type == AVMEDIA_TYPE_VIDEO) { - codec_ctx->width = params().video_params().width(); - codec_ctx->height = params().video_params().height(); - codec_ctx->sample_aspect_ratio = params().video_params().pixel_aspect_ratio().toAVRational(); - codec_ctx->time_base = params().video_params().frame_rate_as_time_base().toAVRational(); - codec_ctx->framerate = params().video_params().frame_rate().toAVRational(); - codec_ctx->pix_fmt = av_get_pix_fmt(params().video_pix_fmt().toUtf8()); - codec_ctx->color_range = params().video_params().color_range() == VideoParams::kColorRangeFull ? AVCOL_RANGE_JPEG : AVCOL_RANGE_MPEG; + if (type == AVMEDIA_TYPE_VIDEO) { + codec_ctx->width = params().video_params().width(); + codec_ctx->height = params().video_params().height(); + codec_ctx->sample_aspect_ratio = + params().video_params().pixel_aspect_ratio().toAVRational(); + codec_ctx->time_base = + params().video_params().frame_rate_as_time_base().toAVRational(); + codec_ctx->framerate = + params().video_params().frame_rate().toAVRational(); + codec_ctx->pix_fmt = av_get_pix_fmt(params().video_pix_fmt().toUtf8()); + codec_ctx->color_range = params().video_params().color_range() == + VideoParams::kColorRangeFull ? + AVCOL_RANGE_JPEG : + AVCOL_RANGE_MPEG; - if (params().video_params().interlacing() != VideoParams::kInterlaceNone) { - // FIXME: I actually don't know what these flags do, the documentation helpfully doesn't - // explain them at all. I hope using both of them is the right thing to do. - codec_ctx->flags |= AV_CODEC_FLAG_INTERLACED_DCT | AV_CODEC_FLAG_INTERLACED_ME; + if (params().video_params().interlacing() != + VideoParams::kInterlaceNone) { + // FIXME: I actually don't know what these flags do, the documentation helpfully doesn't + // explain them at all. I hope using both of them is the right thing to do. + codec_ctx->flags |= AV_CODEC_FLAG_INTERLACED_DCT | + AV_CODEC_FLAG_INTERLACED_ME; + if (params().video_params().interlacing() == + VideoParams::kInterlacedTopFirst) { + codec_ctx->field_order = AV_FIELD_TT; + } else { + codec_ctx->field_order = AV_FIELD_BB; - if (params().video_params().interlacing() == VideoParams::kInterlacedTopFirst) { - codec_ctx->field_order = AV_FIELD_TT; - } else { - codec_ctx->field_order = AV_FIELD_BB; + if (codec == ExportCodec::kCodecH264 || + codec == ExportCodec::kCodecH264rgb) { + // For some reason, FFmpeg doesn't set libx264's bff flag so we have to do it ourselves + av_opt_set(codec_ctx->priv_data, "x264opts", "bff=1", + AV_OPT_SEARCH_CHILDREN); + } + } + } - if (codec == ExportCodec::kCodecH264 || codec == ExportCodec::kCodecH264rgb) { - // For some reason, FFmpeg doesn't set libx264's bff flag so we have to do it ourselves - av_opt_set(codec_ctx->priv_data, "x264opts", "bff=1", AV_OPT_SEARCH_CHILDREN); - } - } - } + // Set custom options + { + for (auto i = params().video_opts().begin(); + i != params().video_opts().end(); i++) { + if (!i.key().startsWith(QStringLiteral("ove_"))) { + av_opt_set(codec_ctx->priv_data, i.key().toUtf8(), + i.value().toUtf8(), AV_OPT_SEARCH_CHILDREN); + } + } - // Set custom options - { - for (auto i=params().video_opts().begin();i!=params().video_opts().end();i++) { - if (!i.key().startsWith(QStringLiteral("ove_"))) { - av_opt_set(codec_ctx->priv_data, i.key().toUtf8(), i.value().toUtf8(), AV_OPT_SEARCH_CHILDREN); - } - } + if (params().video_bit_rate() > 0) { + codec_ctx->bit_rate = params().video_bit_rate(); + } - if (params().video_bit_rate() > 0) { - codec_ctx->bit_rate = params().video_bit_rate(); - } + if (params().video_min_bit_rate() > 0) { + codec_ctx->rc_min_rate = params().video_min_bit_rate(); + } - if (params().video_min_bit_rate() > 0) { - codec_ctx->rc_min_rate = params().video_min_bit_rate(); - } + if (params().video_max_bit_rate() > 0) { + codec_ctx->rc_max_rate = params().video_max_bit_rate(); + } - if (params().video_max_bit_rate() > 0) { - codec_ctx->rc_max_rate = params().video_max_bit_rate(); - } + if (params().video_buffer_size() > 0) { + codec_ctx->rc_buffer_size = + static_cast(params().video_buffer_size()); + } - if (params().video_buffer_size() > 0) { - codec_ctx->rc_buffer_size = static_cast(params().video_buffer_size()); - } + // nclc tags. See https://ffmpeg.org/doxygen/4.0/pixfmt_8h.html#ad384ee5a840bafd73daef08e6d9cafe7 + // ffprobe -v error -show_format -show_streams "C:\Users\Tom\Documents\srgb correct tags.mov" + if (params().color_transform().output().contains( + QStringLiteral("sRGB"), Qt::CaseInsensitive)) { + codec_ctx->color_primaries = AVCOL_PRI_BT709; + codec_ctx->color_trc = AVCOL_TRC_IEC61966_2_1; + codec_ctx->colorspace = AVCOL_SPC_BT709; + } else { // Assume Rec.709 + codec_ctx->color_primaries = AVCOL_PRI_BT709; + codec_ctx->color_trc = AVCOL_TRC_BT709; + codec_ctx->colorspace = AVCOL_SPC_BT709; + } + } - // nclc tags. See https://ffmpeg.org/doxygen/4.0/pixfmt_8h.html#ad384ee5a840bafd73daef08e6d9cafe7 - // ffprobe -v error -show_format -show_streams "C:\Users\Tom\Documents\srgb correct tags.mov" - if (params().color_transform().output().contains(QStringLiteral("sRGB"), Qt::CaseInsensitive)) { - codec_ctx->color_primaries = AVCOL_PRI_BT709; - codec_ctx->color_trc = AVCOL_TRC_IEC61966_2_1; - codec_ctx->colorspace = AVCOL_SPC_BT709; - } else { // Assume Rec.709 - codec_ctx->color_primaries = AVCOL_PRI_BT709; - codec_ctx->color_trc = AVCOL_TRC_BT709; - codec_ctx->colorspace = AVCOL_SPC_BT709; - } - } + } else if (type == AVMEDIA_TYPE_AUDIO) { + // Assume audio stream + codec_ctx->sample_rate = params().audio_params().sample_rate(); + codec_ctx->ch_layout = params().audio_params().channel_layout(); + codec_ctx->sample_fmt = FFmpegUtils::GetFFmpegSampleFormat( + params().audio_params().format()); + codec_ctx->time_base = { 1, codec_ctx->sample_rate }; - } else if (type == AVMEDIA_TYPE_AUDIO) { + if (params().audio_bit_rate() > 0) { + codec_ctx->bit_rate = params().audio_bit_rate(); + } - // Assume audio stream - codec_ctx->sample_rate = params().audio_params().sample_rate(); - codec_ctx->ch_layout = params().audio_params().channel_layout(); - codec_ctx->sample_fmt = FFmpegUtils::GetFFmpegSampleFormat(params().audio_params().format()); - codec_ctx->time_base = {1, codec_ctx->sample_rate}; + } else if (type == AVMEDIA_TYPE_SUBTITLE) { + codec_ctx->time_base = av_get_time_base_q(); - if (params().audio_bit_rate() > 0) { - codec_ctx->bit_rate = params().audio_bit_rate(); - } + QByteArray ass_header = SubtitleParams::GenerateASSHeader().toUtf8(); + codec_ctx->subtitle_header = new uint8_t[ass_header.size()]; + memcpy(codec_ctx->subtitle_header, ass_header.constData(), + ass_header.size()); + codec_ctx->subtitle_header_size = ass_header.size(); + } - } else if (type == AVMEDIA_TYPE_SUBTITLE) { + if (!SetupCodecContext(stream, codec_ctx, encoder)) { + return false; + } - codec_ctx->time_base = av_get_time_base_q(); - - QByteArray ass_header = SubtitleParams::GenerateASSHeader().toUtf8(); - codec_ctx->subtitle_header = new uint8_t[ass_header.size()]; - memcpy(codec_ctx->subtitle_header, ass_header.constData(), ass_header.size()); - codec_ctx->subtitle_header_size = ass_header.size(); - - } - - if (!SetupCodecContext(stream, codec_ctx, encoder)) { - return false; - } - - return true; + return true; } -bool FFmpegEncoder::InitializeCodecContext(AVStream **stream, AVCodecContext **codec_ctx, const AVCodec* codec) +bool FFmpegEncoder::InitializeCodecContext(AVStream **stream, + AVCodecContext **codec_ctx, + const AVCodec *codec) { - *stream = avformat_new_stream(fmt_ctx_, nullptr); - if (!(*stream)) { - SetError(tr("Failed to allocate AVStream")); - return false; - } + *stream = avformat_new_stream(fmt_ctx_, nullptr); + if (!(*stream)) { + SetError(tr("Failed to allocate AVStream")); + return false; + } - // Allocate a codec context - *codec_ctx = avcodec_alloc_context3(codec); - if (!(*codec_ctx)) { - SetError(tr("Failed to allocate AVCodecContext")); - return false; - } + // Allocate a codec context + *codec_ctx = avcodec_alloc_context3(codec); + if (!(*codec_ctx)) { + SetError(tr("Failed to allocate AVCodecContext")); + return false; + } - return true; + return true; } -bool FFmpegEncoder::SetupCodecContext(AVStream* stream, AVCodecContext* codec_ctx, const AVCodec* codec) +bool FFmpegEncoder::SetupCodecContext(AVStream *stream, + AVCodecContext *codec_ctx, + const AVCodec *codec) { - int error_code; + int error_code; - if (fmt_ctx_->oformat->flags & AVFMT_GLOBALHEADER) { - codec_ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; - } + if (fmt_ctx_->oformat->flags & AVFMT_GLOBALHEADER) { + codec_ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; + } - AVDictionary* codec_opts = nullptr; + AVDictionary *codec_opts = nullptr; - // Set thread count - if (params().video_threads() == 0) { - av_dict_set(&codec_opts, "threads", "auto", 0); - } else { - QString thread_val = QString::number(params().video_threads()); - av_dict_set(&codec_opts, "threads", thread_val.toUtf8(), 0); - } + // Set thread count + if (params().video_threads() == 0) { + av_dict_set(&codec_opts, "threads", "auto", 0); + } else { + QString thread_val = QString::number(params().video_threads()); + av_dict_set(&codec_opts, "threads", thread_val.toUtf8(), 0); + } - // Try to open encoder - error_code = avcodec_open2(codec_ctx, codec, &codec_opts); - if (error_code < 0) { - FFmpegError(tr("Failed to open encoder"), error_code); - return false; - } + // Try to open encoder + error_code = avcodec_open2(codec_ctx, codec, &codec_opts); + if (error_code < 0) { + FFmpegError(tr("Failed to open encoder"), error_code); + return false; + } - // Copy context settings to codecpar object - error_code = avcodec_parameters_from_context(stream->codecpar, codec_ctx); - if (error_code < 0) { - FFmpegError(tr("Failed to copy codec parameters to stream"), error_code); - return false; - } + // Copy context settings to codecpar object + error_code = avcodec_parameters_from_context(stream->codecpar, codec_ctx); + if (error_code < 0) { + FFmpegError(tr("Failed to copy codec parameters to stream"), + error_code); + return false; + } - if (codec->type == AVMEDIA_TYPE_VIDEO) { - stream->avg_frame_rate = codec_ctx->framerate; - } + if (codec->type == AVMEDIA_TYPE_VIDEO) { + stream->avg_frame_rate = codec_ctx->framerate; + } - return true; + return true; } void FFmpegEncoder::FlushEncoders() { - if (video_codec_ctx_) { - FlushCodecCtx(video_codec_ctx_, video_stream_); - } + if (video_codec_ctx_) { + FlushCodecCtx(video_codec_ctx_, video_stream_); + } - if (audio_codec_ctx_) { - WriteAudio(SampleBuffer()); + if (audio_codec_ctx_) { + WriteAudio(SampleBuffer()); - FlushCodecCtx(audio_codec_ctx_, audio_stream_); - } + FlushCodecCtx(audio_codec_ctx_, audio_stream_); + } - if (fmt_ctx_) { - if (fmt_ctx_->oformat->flags & AVFMT_ALLOW_FLUSH) { - int r = av_interleaved_write_frame(fmt_ctx_, nullptr); - if (r < 0) { - FFmpegError(tr("Failed to write interleaved packet"), r); - } - } - } + if (fmt_ctx_) { + if (fmt_ctx_->oformat->flags & AVFMT_ALLOW_FLUSH) { + int r = av_interleaved_write_frame(fmt_ctx_, nullptr); + if (r < 0) { + FFmpegError(tr("Failed to write interleaved packet"), r); + } + } + } } -void FFmpegEncoder::FlushCodecCtx(AVCodecContext *codec_ctx, AVStream* stream) +void FFmpegEncoder::FlushCodecCtx(AVCodecContext *codec_ctx, AVStream *stream) { - avcodec_send_frame(codec_ctx, nullptr); - AVPacket* pkt = av_packet_alloc(); + avcodec_send_frame(codec_ctx, nullptr); + AVPacket *pkt = av_packet_alloc(); - int error_code; - do { - error_code = avcodec_receive_packet(codec_ctx, pkt); + int error_code; + do { + error_code = avcodec_receive_packet(codec_ctx, pkt); - if (error_code < 0) { - break; - } + if (error_code < 0) { + break; + } - pkt->stream_index = stream->index; - av_packet_rescale_ts(pkt, codec_ctx->time_base, stream->time_base); - int r = av_interleaved_write_frame(fmt_ctx_, pkt); - if (r < 0) { - FFmpegError(tr("Failed to write interleaved packet"), r); - break; - } - av_packet_unref(pkt); - } while (error_code >= 0); + pkt->stream_index = stream->index; + av_packet_rescale_ts(pkt, codec_ctx->time_base, stream->time_base); + int r = av_interleaved_write_frame(fmt_ctx_, pkt); + if (r < 0) { + FFmpegError(tr("Failed to write interleaved packet"), r); + break; + } + av_packet_unref(pkt); + } while (error_code >= 0); - av_packet_free(&pkt); + av_packet_free(&pkt); } bool FFmpegEncoder::InitializeResampleContext(const AudioParams &audio) { - if (audio_resample_ctx_) { - return true; - } - AVChannelLayout layout=audio.channel_layout(); - // Create resample context - swr_alloc_set_opts2(&audio_resample_ctx_, - &audio_codec_ctx_->ch_layout, - audio_codec_ctx_->sample_fmt, - audio_codec_ctx_->sample_rate, - &layout, - FFmpegUtils::GetFFmpegSampleFormat(audio.format()), - audio.sample_rate(), - 0, - nullptr); - if (!audio_resample_ctx_) { - return false; - } + if (audio_resample_ctx_) { + return true; + } + AVChannelLayout layout = audio.channel_layout(); + // Create resample context + swr_alloc_set_opts2(&audio_resample_ctx_, &audio_codec_ctx_->ch_layout, + audio_codec_ctx_->sample_fmt, + audio_codec_ctx_->sample_rate, &layout, + FFmpegUtils::GetFFmpegSampleFormat(audio.format()), + audio.sample_rate(), 0, nullptr); + if (!audio_resample_ctx_) { + return false; + } - int err = swr_init(audio_resample_ctx_); - if (err < 0) { - FFmpegError(tr("Failed to create resampling context"), err); - return false; - } + int err = swr_init(audio_resample_ctx_); + if (err < 0) { + FFmpegError(tr("Failed to create resampling context"), err); + return false; + } - audio_max_samples_ = audio_codec_ctx_->frame_size; - if (!audio_max_samples_) { - // If not, use another frame size - if (params().video_enabled()) { - // If we're encoding video, use enough samples to cover roughly one frame of video - audio_max_samples_ = params().audio_params().time_to_samples(params().video_params().frame_rate_as_time_base()); - } else { - // If no video, just use an arbitrary number - audio_max_samples_ = 256; - } - } + audio_max_samples_ = audio_codec_ctx_->frame_size; + if (!audio_max_samples_) { + // If not, use another frame size + if (params().video_enabled()) { + // If we're encoding video, use enough samples to cover roughly one frame of video + audio_max_samples_ = params().audio_params().time_to_samples( + params().video_params().frame_rate_as_time_base()); + } else { + // If no video, just use an arbitrary number + audio_max_samples_ = 256; + } + } - audio_frame_ = av_frame_alloc(); - if (!audio_frame_) { - return false; - } + audio_frame_ = av_frame_alloc(); + if (!audio_frame_) { + return false; + } - audio_frame_->ch_layout = audio_codec_ctx_->ch_layout; - audio_frame_->format = audio_codec_ctx_->sample_fmt; - audio_frame_->nb_samples = audio_max_samples_; + audio_frame_->ch_layout = audio_codec_ctx_->ch_layout; + audio_frame_->format = audio_codec_ctx_->sample_fmt; + audio_frame_->nb_samples = audio_max_samples_; - err = av_frame_get_buffer(audio_frame_, 0); - if (err < 0) { - FFmpegError(tr("Failed to create audio frame"), err); - return false; - } + err = av_frame_get_buffer(audio_frame_, 0); + if (err < 0) { + FFmpegError(tr("Failed to create audio frame"), err); + return false; + } - audio_frame_offset_ = 0; - audio_write_count_ = 0; + audio_frame_offset_ = 0; + audio_write_count_ = 0; - return true; + return true; } -const AVCodec *FFmpegEncoder::GetEncoder(ExportCodec::Codec c, SampleFormat aformat) +const AVCodec *FFmpegEncoder::GetEncoder(ExportCodec::Codec c, + SampleFormat aformat) { - switch (c) { - case ExportCodec::kCodecH264: - return avcodec_find_encoder_by_name("libx264"); - case ExportCodec::kCodecH264rgb: - return avcodec_find_encoder_by_name("libx264rgb"); - case ExportCodec::kCodecDNxHD: - return avcodec_find_encoder(AV_CODEC_ID_DNXHD); - case ExportCodec::kCodecProRes: - return avcodec_find_encoder(AV_CODEC_ID_PRORES); - case ExportCodec::kCodecCineform: - return avcodec_find_encoder(AV_CODEC_ID_CFHD); - case ExportCodec::kCodecH265: - return avcodec_find_encoder(AV_CODEC_ID_HEVC); - case ExportCodec::kCodecVP9: - return avcodec_find_encoder(AV_CODEC_ID_VP9); - case ExportCodec::kCodecAV1: { - const AVCodec *encoder = avcodec_find_encoder_by_name("libsvtav1"); - if(!encoder) - encoder = avcodec_find_encoder(AV_CODEC_ID_AV1); - return encoder; - } - case ExportCodec::kCodecOpenEXR: - return avcodec_find_encoder(AV_CODEC_ID_EXR); - case ExportCodec::kCodecPNG: - return avcodec_find_encoder(AV_CODEC_ID_PNG); - case ExportCodec::kCodecTIFF: - return avcodec_find_encoder(AV_CODEC_ID_TIFF); - case ExportCodec::kCodecMP2: - return avcodec_find_encoder(AV_CODEC_ID_MP2); - case ExportCodec::kCodecMP3: - return avcodec_find_encoder(AV_CODEC_ID_MP3); - case ExportCodec::kCodecAAC: - return avcodec_find_encoder(AV_CODEC_ID_AAC); - case ExportCodec::kCodecPCM: - switch (aformat) { - case SampleFormat::INVALID: - case SampleFormat::COUNT: - case SampleFormat::U8P: - case SampleFormat::S16P: - case SampleFormat::S32P: - case SampleFormat::S64P: - case SampleFormat::F32P: - case SampleFormat::F64P: - break; - case SampleFormat::U8: - return avcodec_find_encoder(AV_CODEC_ID_PCM_U8); - case SampleFormat::S16: - return avcodec_find_encoder(AV_CODEC_ID_PCM_S16LE); - case SampleFormat::S32: - return avcodec_find_encoder(AV_CODEC_ID_PCM_S32LE); - case SampleFormat::S64: - return avcodec_find_encoder(AV_CODEC_ID_PCM_S64LE); - case SampleFormat::F32: - return avcodec_find_encoder(AV_CODEC_ID_PCM_F32LE); - case SampleFormat::F64: - return avcodec_find_encoder(AV_CODEC_ID_PCM_F64LE); - } - break; - case ExportCodec::kCodecFLAC: - return avcodec_find_encoder(AV_CODEC_ID_FLAC); - case ExportCodec::kCodecOpus: - return avcodec_find_encoder(AV_CODEC_ID_OPUS); - case ExportCodec::kCodecVorbis: - return avcodec_find_encoder(AV_CODEC_ID_VORBIS); - case ExportCodec::kCodecSRT: - return avcodec_find_encoder(AV_CODEC_ID_SUBRIP); - case ExportCodec::kCodecCount: - // These are audio or invalid codecs and therefore have no pixel formats - break; - } + switch (c) { + case ExportCodec::kCodecH264: + return avcodec_find_encoder_by_name("libx264"); + case ExportCodec::kCodecH264rgb: + return avcodec_find_encoder_by_name("libx264rgb"); + case ExportCodec::kCodecDNxHD: + return avcodec_find_encoder(AV_CODEC_ID_DNXHD); + case ExportCodec::kCodecProRes: + return avcodec_find_encoder(AV_CODEC_ID_PRORES); + case ExportCodec::kCodecCineform: + return avcodec_find_encoder(AV_CODEC_ID_CFHD); + case ExportCodec::kCodecH265: + return avcodec_find_encoder(AV_CODEC_ID_HEVC); + case ExportCodec::kCodecVP9: + return avcodec_find_encoder(AV_CODEC_ID_VP9); + case ExportCodec::kCodecAV1: { + const AVCodec *encoder = avcodec_find_encoder_by_name("libsvtav1"); + if (!encoder) + encoder = avcodec_find_encoder(AV_CODEC_ID_AV1); + return encoder; + } + case ExportCodec::kCodecOpenEXR: + return avcodec_find_encoder(AV_CODEC_ID_EXR); + case ExportCodec::kCodecPNG: + return avcodec_find_encoder(AV_CODEC_ID_PNG); + case ExportCodec::kCodecTIFF: + return avcodec_find_encoder(AV_CODEC_ID_TIFF); + case ExportCodec::kCodecMP2: + return avcodec_find_encoder(AV_CODEC_ID_MP2); + case ExportCodec::kCodecMP3: + return avcodec_find_encoder(AV_CODEC_ID_MP3); + case ExportCodec::kCodecAAC: + return avcodec_find_encoder(AV_CODEC_ID_AAC); + case ExportCodec::kCodecPCM: + switch (aformat) { + case SampleFormat::INVALID: + case SampleFormat::COUNT: + case SampleFormat::U8P: + case SampleFormat::S16P: + case SampleFormat::S32P: + case SampleFormat::S64P: + case SampleFormat::F32P: + case SampleFormat::F64P: + break; + case SampleFormat::U8: + return avcodec_find_encoder(AV_CODEC_ID_PCM_U8); + case SampleFormat::S16: + return avcodec_find_encoder(AV_CODEC_ID_PCM_S16LE); + case SampleFormat::S32: + return avcodec_find_encoder(AV_CODEC_ID_PCM_S32LE); + case SampleFormat::S64: + return avcodec_find_encoder(AV_CODEC_ID_PCM_S64LE); + case SampleFormat::F32: + return avcodec_find_encoder(AV_CODEC_ID_PCM_F32LE); + case SampleFormat::F64: + return avcodec_find_encoder(AV_CODEC_ID_PCM_F64LE); + } + break; + case ExportCodec::kCodecFLAC: + return avcodec_find_encoder(AV_CODEC_ID_FLAC); + case ExportCodec::kCodecOpus: + return avcodec_find_encoder(AV_CODEC_ID_OPUS); + case ExportCodec::kCodecVorbis: + return avcodec_find_encoder(AV_CODEC_ID_VORBIS); + case ExportCodec::kCodecSRT: + return avcodec_find_encoder(AV_CODEC_ID_SUBRIP); + case ExportCodec::kCodecCount: + // These are audio or invalid codecs and therefore have no pixel formats + break; + } - return nullptr; + return nullptr; } } diff --git a/app/codec/ffmpeg/ffmpegencoder.h b/app/codec/ffmpeg/ffmpegencoder.h index 3c1ec49ed..9474f527c 100644 --- a/app/codec/ffmpeg/ffmpegencoder.h +++ b/app/codec/ffmpeg/ffmpegencoder.h @@ -31,37 +31,41 @@ extern "C" { #include "codec/encoder.h" -namespace olive { - -class FFmpegEncoder : public Encoder +namespace olive { - Q_OBJECT + +class FFmpegEncoder : public Encoder { + Q_OBJECT public: - FFmpegEncoder(const EncodingParams ¶ms); + FFmpegEncoder(const EncodingParams ¶ms); - virtual QStringList GetPixelFormatsForCodec(ExportCodec::Codec c) const override; + virtual QStringList + GetPixelFormatsForCodec(ExportCodec::Codec c) const override; - virtual std::vector GetSampleFormatsForCodec(ExportCodec::Codec c) const override; + virtual std::vector + GetSampleFormatsForCodec(ExportCodec::Codec c) const override; - virtual bool Open() override; + virtual bool Open() override; - virtual bool WriteFrame(olive::FramePtr frame, olive::core::rational time) override; + virtual bool WriteFrame(olive::FramePtr frame, + olive::core::rational time) override; - virtual bool WriteAudio(const olive::SampleBuffer &audio) override; + virtual bool WriteAudio(const olive::SampleBuffer &audio) override; - bool WriteAudioData(const AudioParams &audio_params, const uint8_t **data, int input_sample_count); + bool WriteAudioData(const AudioParams &audio_params, const uint8_t **data, + int input_sample_count); - virtual bool WriteSubtitle(const SubtitleBlock *sub_block) override; + virtual bool WriteSubtitle(const SubtitleBlock *sub_block) override; - virtual void Close() override; + virtual void Close() override; - virtual PixelFormat GetDesiredPixelFormat() const override - { - return video_conversion_fmt_; - } + virtual PixelFormat GetDesiredPixelFormat() const override + { + return video_conversion_fmt_; + } private: - /** + /** * @brief Handle an FFmpeg error code * * Uses the FFmpeg API to retrieve a descriptive string for this error code and sends it to Error(). As such, this @@ -69,43 +73,48 @@ private: * * @param error_code */ - void FFmpegError(const QString &context, int error_code); + void FFmpegError(const QString &context, int error_code); - bool WriteAVFrame(AVFrame* frame, AVCodecContext *codec_ctx, AVStream *stream); + bool WriteAVFrame(AVFrame *frame, AVCodecContext *codec_ctx, + AVStream *stream); - bool InitializeStream(enum AVMediaType type, AVStream** stream, AVCodecContext** codec_ctx, const ExportCodec::Codec &codec); - bool InitializeCodecContext(AVStream** stream, AVCodecContext** codec_ctx, const AVCodec* codec); - bool SetupCodecContext(AVStream *stream, AVCodecContext *codec_ctx, const AVCodec *codec); + bool InitializeStream(enum AVMediaType type, AVStream **stream, + AVCodecContext **codec_ctx, + const ExportCodec::Codec &codec); + bool InitializeCodecContext(AVStream **stream, AVCodecContext **codec_ctx, + const AVCodec *codec); + bool SetupCodecContext(AVStream *stream, AVCodecContext *codec_ctx, + const AVCodec *codec); - void FlushEncoders(); - void FlushCodecCtx(AVCodecContext* codec_ctx, AVStream *stream); + void FlushEncoders(); + void FlushCodecCtx(AVCodecContext *codec_ctx, AVStream *stream); - bool InitializeResampleContext(const AudioParams &audio); + bool InitializeResampleContext(const AudioParams &audio); - static const AVCodec *GetEncoder(ExportCodec::Codec c, SampleFormat aformat); + static const AVCodec *GetEncoder(ExportCodec::Codec c, + SampleFormat aformat); - AVFormatContext* fmt_ctx_; + AVFormatContext *fmt_ctx_; - AVStream* video_stream_; - AVCodecContext* video_codec_ctx_; - AVFilterGraph *video_scale_ctx_; - AVFilterContext *video_buffersrc_ctx_; - AVFilterContext *video_buffersink_ctx_; - PixelFormat video_conversion_fmt_; + AVStream *video_stream_; + AVCodecContext *video_codec_ctx_; + AVFilterGraph *video_scale_ctx_; + AVFilterContext *video_buffersrc_ctx_; + AVFilterContext *video_buffersink_ctx_; + PixelFormat video_conversion_fmt_; - AVStream* audio_stream_; - AVCodecContext* audio_codec_ctx_; - SwrContext* audio_resample_ctx_; - AVFrame* audio_frame_; - int audio_max_samples_; - int audio_frame_offset_; - int audio_write_count_; + AVStream *audio_stream_; + AVCodecContext *audio_codec_ctx_; + SwrContext *audio_resample_ctx_; + AVFrame *audio_frame_; + int audio_max_samples_; + int audio_frame_offset_; + int audio_write_count_; - AVStream* subtitle_stream_; - AVCodecContext* subtitle_codec_ctx_; - - bool open_; + AVStream *subtitle_stream_; + AVCodecContext *subtitle_codec_ctx_; + bool open_; }; } diff --git a/app/codec/frame.cpp b/app/codec/frame.cpp index a1342fa1e..f2c087247 100644 --- a/app/codec/frame.cpp +++ b/app/codec/frame.cpp @@ -28,153 +28,161 @@ #include "common/oiioutils.h" #include "render/framemanager.h" -namespace olive { +namespace olive +{ -Frame::Frame() : - data_(nullptr), - data_size_(0), - timestamp_(0) +Frame::Frame() + : data_(nullptr) + , data_size_(0) + , timestamp_(0) { } Frame::~Frame() { - destroy(); + destroy(); } FramePtr Frame::Create() { - return std::make_shared(); + return std::make_shared(); } const VideoParams &Frame::video_params() const { - return params_; + return params_; } void Frame::set_video_params(const VideoParams ¶ms) { - params_ = params; + params_ = params; - linesize_ = generate_linesize_bytes(width(), params_.format(), params_.channel_count()); - linesize_pixels_ = linesize_ / params_.GetBytesPerPixel(); + linesize_ = generate_linesize_bytes(width(), params_.format(), + params_.channel_count()); + linesize_pixels_ = linesize_ / params_.GetBytesPerPixel(); } FramePtr Frame::Interlace(FramePtr top, FramePtr bottom) { - if (top->video_params() != bottom->video_params()) { - qCritical() << "Tried to interlace two frames that had incompatible parameters"; - return nullptr; - } + if (top->video_params() != bottom->video_params()) { + qCritical() + << "Tried to interlace two frames that had incompatible parameters"; + return nullptr; + } - FramePtr interlaced = Frame::Create(); - interlaced->set_video_params(top->video_params()); - interlaced->allocate(); + FramePtr interlaced = Frame::Create(); + interlaced->set_video_params(top->video_params()); + interlaced->allocate(); - int linesize = interlaced->linesize_bytes(); + int linesize = interlaced->linesize_bytes(); - for (int i=0; iheight(); i++) { - FramePtr which = (i%2 == 0) ? top : bottom; + for (int i = 0; i < interlaced->height(); i++) { + FramePtr which = (i % 2 == 0) ? top : bottom; - memcpy(interlaced->data() + i*linesize, - which->const_data() + i*linesize, - linesize); - } + memcpy(interlaced->data() + i * linesize, + which->const_data() + i * linesize, linesize); + } - return interlaced; + return interlaced; } -int Frame::generate_linesize_bytes(int width, PixelFormat format, int channel_count) +int Frame::generate_linesize_bytes(int width, PixelFormat format, + int channel_count) { - // Align to 32 bytes (not sure if this is necessary?) - return VideoParams::GetBytesPerPixel(format, channel_count) * ((width + 31) & ~31); + // Align to 32 bytes (not sure if this is necessary?) + return VideoParams::GetBytesPerPixel(format, channel_count) * + ((width + 31) & ~31); } Color Frame::get_pixel(int x, int y) const { - if (!contains_pixel(x, y)) { - return Color(); - } + if (!contains_pixel(x, y)) { + return Color(); + } - int byte_offset = y * linesize_bytes() + x * video_params().GetBytesPerPixel(); + int byte_offset = + y * linesize_bytes() + x * video_params().GetBytesPerPixel(); - return Color(reinterpret_cast(data_ + byte_offset), video_params().format(), video_params().channel_count()); + return Color(reinterpret_cast(data_ + byte_offset), + video_params().format(), video_params().channel_count()); } bool Frame::contains_pixel(int x, int y) const { - return (is_allocated() && x >= 0 && x < width() && y >= 0 && y < height()); + return (is_allocated() && x >= 0 && x < width() && y >= 0 && y < height()); } void Frame::set_pixel(int x, int y, const Color &c) { - if (!contains_pixel(x, y)) { - return; - } + if (!contains_pixel(x, y)) { + return; + } - int byte_offset = y * linesize_bytes() + x * video_params().GetBytesPerPixel(); + int byte_offset = + y * linesize_bytes() + x * video_params().GetBytesPerPixel(); - c.toData(reinterpret_cast(data_ + byte_offset), video_params().format(), video_params().channel_count()); + c.toData(reinterpret_cast(data_ + byte_offset), + video_params().format(), video_params().channel_count()); } bool Frame::allocate() { - // Assume this frame is intended to be a video frame - if (!params_.is_valid()) { - qWarning() << "Tried to allocate a frame with invalid parameters"; - return false; - } + // Assume this frame is intended to be a video frame + if (!params_.is_valid()) { + qWarning() << "Tried to allocate a frame with invalid parameters"; + return false; + } - if (is_allocated()) { - // Already allocated - return true; - } + if (is_allocated()) { + // Already allocated + return true; + } - data_size_ = linesize_ * height(); - data_ = FrameManager::Allocate(data_size_); + data_size_ = linesize_ * height(); + data_ = FrameManager::Allocate(data_size_); - return true; + return true; } void Frame::destroy() { - if (is_allocated()) { - FrameManager::Deallocate(data_size_, data_); + if (is_allocated()) { + FrameManager::Deallocate(data_size_, data_); - data_size_ = 0; - data_ = nullptr; - } + data_size_ = 0; + data_ = nullptr; + } } FramePtr Frame::convert(PixelFormat format) const { - // Create new params with destination format - VideoParams params = params_; - params.set_format(format); + // Create new params with destination format + VideoParams params = params_; + params.set_format(format); - // Create new frame - FramePtr converted = Frame::Create(); - converted->set_video_params(params); - converted->set_timestamp(timestamp_); - converted->allocate(); + // Create new frame + FramePtr converted = Frame::Create(); + converted->set_video_params(params); + converted->set_timestamp(timestamp_); + converted->allocate(); - // Do the conversion through OIIO for convenience - OIIO::ImageBuf src(OIIO::ImageSpec(width(), height(), - channel_count(), - OIIOUtils::GetOIIOBaseTypeFromFormat(this->format()))); + // Do the conversion through OIIO for convenience + OIIO::ImageBuf src( + OIIO::ImageSpec(width(), height(), channel_count(), + OIIOUtils::GetOIIOBaseTypeFromFormat(this->format()))); - OIIOUtils::FrameToBuffer(this, &src); + OIIOUtils::FrameToBuffer(this, &src); - OIIO::ImageBuf dst(OIIO::ImageSpec(converted->width(), converted->height(), - channel_count(), - OIIOUtils::GetOIIOBaseTypeFromFormat(format))); + OIIO::ImageBuf dst(OIIO::ImageSpec( + converted->width(), converted->height(), channel_count(), + OIIOUtils::GetOIIOBaseTypeFromFormat(format))); - if (dst.copy_pixels(src)) { - OIIOUtils::BufferToFrame(&dst, converted.get()); - return converted; - } else { - return nullptr; - } + if (dst.copy_pixels(src)) { + OIIOUtils::BufferToFrame(&dst, converted.get()); + return converted; + } else { + return nullptr; + } } } diff --git a/app/codec/frame.h b/app/codec/frame.h index 30a6ebe86..a87ac4080 100644 --- a/app/codec/frame.h +++ b/app/codec/frame.h @@ -28,7 +28,8 @@ #include "common/define.h" #include "render/videoparams.h" -namespace olive { +namespace olive +{ class Frame; using FramePtr = std::shared_ptr; @@ -36,135 +37,134 @@ using FramePtr = std::shared_ptr; /** * @brief Video frame data or audio sample data from a Decoder */ -class Frame -{ +class Frame { public: - Frame(); + Frame(); - ~Frame(); + ~Frame(); - DISABLE_COPY_MOVE(Frame) + DISABLE_COPY_MOVE(Frame) - static FramePtr Create(); + static FramePtr Create(); - const VideoParams& video_params() const; - void set_video_params(const VideoParams& params); + const VideoParams &video_params() const; + void set_video_params(const VideoParams ¶ms); - static FramePtr Interlace(FramePtr top, FramePtr bottom); + static FramePtr Interlace(FramePtr top, FramePtr bottom); - static int generate_linesize_bytes(int width, PixelFormat format, int channel_count); + static int generate_linesize_bytes(int width, PixelFormat format, + int channel_count); - int linesize_pixels() const - { - return linesize_pixels_; - } + int linesize_pixels() const + { + return linesize_pixels_; + } - int linesize_bytes() const - { - return linesize_; - } + int linesize_bytes() const + { + return linesize_; + } - int width() const - { - return params_.effective_width(); - } + int width() const + { + return params_.effective_width(); + } - int height() const - { - return params_.effective_height(); - } + int height() const + { + return params_.effective_height(); + } - PixelFormat format() const - { - return params_.format(); - } + PixelFormat format() const + { + return params_.format(); + } - int channel_count() const - { - return params_.channel_count(); - } + int channel_count() const + { + return params_.channel_count(); + } - Color get_pixel(int x, int y) const; - bool contains_pixel(int x, int y) const; - void set_pixel(int x, int y, const Color& c); + Color get_pixel(int x, int y) const; + bool contains_pixel(int x, int y) const; + void set_pixel(int x, int y, const Color &c); - /** + /** * @brief Get frame's timestamp. * * This timestamp is always a rational that will equate to the time in seconds. */ - const rational& timestamp() const - { - return timestamp_; - } + const rational ×tamp() const + { + return timestamp_; + } - void set_timestamp(const rational& timestamp) - { - timestamp_ = timestamp; - } + void set_timestamp(const rational ×tamp) + { + timestamp_ = timestamp; + } - /** + /** * @brief Get the data buffer of this frame */ - char* data() - { - return data_; - } + char *data() + { + return data_; + } - /** + /** * @brief Get the const data buffer of this frame */ - const char* const_data() const - { - return data_; - } + const char *const_data() const + { + return data_; + } - /** + /** * @brief Allocate memory buffer to store data based on parameters * * For video frames, the width(), height(), and format() must be set for this function to work. * * If a memory buffer has been previously allocated without destroying, this function will destroy it. */ - bool allocate(); + bool allocate(); - /** + /** * @brief Return whether the frame is allocated or not */ - bool is_allocated() const - { - return data_; - } + bool is_allocated() const + { + return data_; + } - /** + /** * @brief Destroy a memory buffer allocated with allocate() */ - void destroy(); + void destroy(); - /** + /** * @brief Returns the size of the array returned in data() in bytes * * Returns 0 if nothing is allocated. */ - int allocated_size() const - { - return data_size_; - } + int allocated_size() const + { + return data_size_; + } - FramePtr convert(PixelFormat format) const; + FramePtr convert(PixelFormat format) const; private: - VideoParams params_; + VideoParams params_; - char* data_; - int data_size_; + char *data_; + int data_size_; - rational timestamp_; + rational timestamp_; - int linesize_; - - int linesize_pixels_; + int linesize_; + int linesize_pixels_; }; } diff --git a/app/codec/oiio/oiiodecoder.cpp b/app/codec/oiio/oiiodecoder.cpp index 5ba005558..ebb8c1f04 100644 --- a/app/codec/oiio/oiiodecoder.cpp +++ b/app/codec/oiio/oiiodecoder.cpp @@ -31,217 +31,234 @@ #include "core.h" #include "render/renderer.h" -namespace olive { +namespace olive +{ QStringList OIIODecoder::supported_formats_; -OIIODecoder::OIIODecoder() : - image_(nullptr) +OIIODecoder::OIIODecoder() + : image_(nullptr) { } QString OIIODecoder::id() const { - return QStringLiteral("oiio"); + return QStringLiteral("oiio"); } -FootageDescription OIIODecoder::Probe(const QString &filename, CancelAtom *cancelled) const +FootageDescription OIIODecoder::Probe(const QString &filename, + CancelAtom *cancelled) const { - Q_UNUSED(cancelled) + Q_UNUSED(cancelled) - FootageDescription desc(id()); + FootageDescription desc(id()); - // Filter out any file extensions that aren't expected to work - sometimes OIIO will crash trying - // to open a file that it can't if it's given one - if (!FileTypeIsSupported(filename)) { - return desc; - } + // Filter out any file extensions that aren't expected to work - sometimes OIIO will crash trying + // to open a file that it can't if it's given one + if (!FileTypeIsSupported(filename)) { + return desc; + } - std::string std_filename = filename.toStdString(); + std::string std_filename = filename.toStdString(); - auto in = OIIO::ImageInput::open(std_filename); + auto in = OIIO::ImageInput::open(std_filename); - if (!in) { - return desc; - } + if (!in) { + return desc; + } - // Filter out OIIO detecting an "FFmpeg movie", we have a native FFmpeg decoder that can handle - // it better - if (!strcmp(in->format_name(), "FFmpeg movie")) { - return desc; - } + // Filter out OIIO detecting an "FFmpeg movie", we have a native FFmpeg decoder that can handle + // it better + if (!strcmp(in->format_name(), "FFmpeg movie")) { + return desc; + } - bool stream_enabled = true; + bool stream_enabled = true; - int i; - for (i=0; in->seek_subimage(i, 0); i++) { - OIIO::ImageSpec spec = in->spec(); + int i; + for (i = 0; in->seek_subimage(i, 0); i++) { + OIIO::ImageSpec spec = in->spec(); - VideoParams video_params = GetVideoParamsFromImageSpec(spec); + VideoParams video_params = GetVideoParamsFromImageSpec(spec); - video_params.set_stream_index(i); + video_params.set_stream_index(i); - if (i > 1) { - // This is a multilayer image and this image might have an offset - OIIO::ImageSpec root_spec = in->spec(0); + if (i > 1) { + // This is a multilayer image and this image might have an offset + OIIO::ImageSpec root_spec = in->spec(0); - float norm_x = spec.x + float(spec.width)*0.5f - float(root_spec.width)*0.5f; - float norm_y = spec.y + float(spec.height)*0.5f - float(root_spec.height)*0.5f; + float norm_x = spec.x + float(spec.width) * 0.5f - + float(root_spec.width) * 0.5f; + float norm_y = spec.y + float(spec.height) * 0.5f - + float(root_spec.height) * 0.5f; - video_params.set_x(norm_x); - video_params.set_y(norm_y); - } + video_params.set_x(norm_x); + video_params.set_y(norm_y); + } - // By default, only enable the first subimage (presumably the combined image). Later we will - // ask the user if they want to enable the layers instead. - video_params.set_enabled(stream_enabled); - stream_enabled = false; + // By default, only enable the first subimage (presumably the combined image). Later we will + // ask the user if they want to enable the layers instead. + video_params.set_enabled(stream_enabled); + stream_enabled = false; - // OIIO automatically premultiplies alpha - // FIXME: We usually disassociate the alpha for the color management later, for 8-bit images this - // likely reduces the fidelity? - video_params.set_premultiplied_alpha(true); + // OIIO automatically premultiplies alpha + // FIXME: We usually disassociate the alpha for the color management later, for 8-bit images this + // likely reduces the fidelity? + video_params.set_premultiplied_alpha(true); - desc.AddVideoStream(video_params); - } + desc.AddVideoStream(video_params); + } - desc.SetStreamCount(i); + desc.SetStreamCount(i); - // If we're here, we have a successful image open - in->close(); + // If we're here, we have a successful image open + in->close(); - return desc; + return desc; } bool OIIODecoder::OpenInternal() { - // If we can open the filename provided, assume everything is working - return OpenImageHandler(stream().filename(), stream().stream()); + // If we can open the filename provided, assume everything is working + return OpenImageHandler(stream().filename(), stream().stream()); } TexturePtr OIIODecoder::RetrieveVideoInternal(const RetrieveVideoParams &p) { - VideoParams vp = GetVideoParamsFromImageSpec(image_->spec()); - vp.set_divider(p.divider); + VideoParams vp = GetVideoParamsFromImageSpec(image_->spec()); + vp.set_divider(p.divider); - if (!buffer_.is_allocated() - || last_params_.divider != p.divider) { - last_params_ = p; + if (!buffer_.is_allocated() || last_params_.divider != p.divider) { + last_params_ = p; - buffer_.destroy(); - buffer_.set_video_params(vp); - buffer_.allocate(); + buffer_.destroy(); + buffer_.set_video_params(vp); + buffer_.allocate(); - if (p.divider == 1) { - // Just upload straight to the buffer - image_->read_image(0, 0, 0, -1, oiio_pix_fmt_, buffer_.data()); - } else { - OIIO::ImageBuf buf(image_->spec()); - image_->read_image(0,0,0,-1,image_->spec().format, buf.localpixels(), buf.pixel_stride(), buf.scanline_stride(), buf.z_stride()); + if (p.divider == 1) { + // Just upload straight to the buffer + image_->read_image(0, 0, 0, -1, oiio_pix_fmt_, buffer_.data()); + } else { + OIIO::ImageBuf buf(image_->spec()); + image_->read_image(0, 0, 0, -1, image_->spec().format, + buf.localpixels(), buf.pixel_stride(), + buf.scanline_stride(), buf.z_stride()); - // Roughly downsample image for divider (for some reason OIIO::ImageBufAlgo::resample failed here) - int px_sz = vp.GetBytesPerPixel(); - for (int dst_y=0; dst_y(buf.localpixels()) + buf.scanline_stride() * src_y + px_sz * src_x, - px_sz); - } - } - } - } + for (int dst_x = 0; dst_x < buffer_.width(); dst_x++) { + int src_x = dst_x * buf.spec().width / buffer_.width(); + memcpy(buffer_.data() + buffer_.linesize_bytes() * dst_y + + px_sz * dst_x, + static_cast(buf.localpixels()) + + buf.scanline_stride() * src_y + px_sz * src_x, + px_sz); + } + } + } + } - return p.renderer->CreateTexture(vp, buffer_.data(), buffer_.linesize_pixels()); + return p.renderer->CreateTexture(vp, buffer_.data(), + buffer_.linesize_pixels()); } void OIIODecoder::CloseInternal() { - CloseImageHandle(); + CloseImageHandle(); } -bool OIIODecoder::FileTypeIsSupported(const QString& fn) +bool OIIODecoder::FileTypeIsSupported(const QString &fn) { - // We prioritize OIIO over FFmpeg to pick up still images more effectively, but some OIIO decoders (notably OpenJPEG) - // will segfault entirely if given unexpected data (an MPEG-4 for instance). To workaround this issue, we use OIIO's - // "extension_list" attribute and match it with the extension of the file. + // We prioritize OIIO over FFmpeg to pick up still images more effectively, but some OIIO decoders (notably OpenJPEG) + // will segfault entirely if given unexpected data (an MPEG-4 for instance). To workaround this issue, we use OIIO's + // "extension_list" attribute and match it with the extension of the file. - // Check if we've created the supported formats list, create it if not - if (supported_formats_.isEmpty()) { - QStringList extension_list = QString::fromStdString(OIIO::get_string_attribute("extension_list")).split(';'); + // Check if we've created the supported formats list, create it if not + if (supported_formats_.isEmpty()) { + QStringList extension_list = + QString::fromStdString(OIIO::get_string_attribute("extension_list")) + .split(';'); - // The format of "extension_list" is "format:ext", we want to separate it into a simple list of extensions - foreach (const QString& ext, extension_list) { - QStringList format_and_ext = ext.split(':'); + // The format of "extension_list" is "format:ext", we want to separate it into a simple list of extensions + foreach (const QString &ext, extension_list) { + QStringList format_and_ext = ext.split(':'); - supported_formats_.append(format_and_ext.at(1).split(',')); - } - } + supported_formats_.append(format_and_ext.at(1).split(',')); + } + } - if (!supported_formats_.contains(QFileInfo(fn).suffix(), Qt::CaseInsensitive)) { - return false; - } + if (!supported_formats_.contains(QFileInfo(fn).suffix(), + Qt::CaseInsensitive)) { + return false; + } - return true; + return true; } bool OIIODecoder::OpenImageHandler(const QString &fn, int subimage) { - image_ = OIIO::ImageInput::open(fn.toStdString()); + image_ = OIIO::ImageInput::open(fn.toStdString()); - if (!image_) { - return false; - } + if (!image_) { + return false; + } - if (!image_->seek_subimage(subimage, 0)) { - return false; - } + if (!image_->seek_subimage(subimage, 0)) { + return false; + } - // Check if we can work with this pixel format - const OIIO::ImageSpec& spec = image_->spec(); + // Check if we can work with this pixel format + const OIIO::ImageSpec &spec = image_->spec(); - // We use RGBA frames because that tends to be the native format of GPUs - pix_fmt_ = OIIOUtils::GetFormatFromOIIOBasetype(static_cast(spec.format.basetype)); + // We use RGBA frames because that tends to be the native format of GPUs + pix_fmt_ = OIIOUtils::GetFormatFromOIIOBasetype( + static_cast(spec.format.basetype)); - if (pix_fmt_ == PixelFormat::INVALID) { - qWarning() << "Failed to convert OIIO::ImageDesc to native pixel format"; - return false; - } + if (pix_fmt_ == PixelFormat::INVALID) { + qWarning() + << "Failed to convert OIIO::ImageDesc to native pixel format"; + return false; + } - oiio_pix_fmt_ = OIIOUtils::GetOIIOBaseTypeFromFormat(pix_fmt_); + oiio_pix_fmt_ = OIIOUtils::GetOIIOBaseTypeFromFormat(pix_fmt_); - if (oiio_pix_fmt_ == OIIO::TypeDesc::UNKNOWN) { - qCritical() << "Failed to determine appropriate OIIO basetype from native format"; - return false; - } + if (oiio_pix_fmt_ == OIIO::TypeDesc::UNKNOWN) { + qCritical() + << "Failed to determine appropriate OIIO basetype from native format"; + return false; + } - return true; + return true; } void OIIODecoder::CloseImageHandle() { - if (image_) { - image_->close(); - image_ = nullptr; - } + if (image_) { + image_->close(); + image_ = nullptr; + } - buffer_.destroy(); + buffer_.destroy(); } -VideoParams OIIODecoder::GetVideoParamsFromImageSpec(const OIIO::ImageSpec &spec) +VideoParams +OIIODecoder::GetVideoParamsFromImageSpec(const OIIO::ImageSpec &spec) { - VideoParams video_params; + VideoParams video_params; - video_params.set_width(spec.width); - video_params.set_height(spec.height); - video_params.set_format(OIIOUtils::GetFormatFromOIIOBasetype(static_cast(spec.format.basetype))); - video_params.set_channel_count(spec.nchannels); - video_params.set_pixel_aspect_ratio(OIIOUtils::GetPixelAspectRatioFromOIIO(spec)); - video_params.set_video_type(VideoParams::kVideoTypeStill); + video_params.set_width(spec.width); + video_params.set_height(spec.height); + video_params.set_format(OIIOUtils::GetFormatFromOIIOBasetype( + static_cast(spec.format.basetype))); + video_params.set_channel_count(spec.nchannels); + video_params.set_pixel_aspect_ratio( + OIIOUtils::GetPixelAspectRatioFromOIIO(spec)); + video_params.set_video_type(VideoParams::kVideoTypeStill); - return video_params; + return video_params; } } diff --git a/app/codec/oiio/oiiodecoder.h b/app/codec/oiio/oiiodecoder.h index ca20a8374..9bb1197e8 100644 --- a/app/codec/oiio/oiiodecoder.h +++ b/app/codec/oiio/oiiodecoder.h @@ -26,46 +26,50 @@ #include "codec/decoder.h" -namespace olive { - -class OIIODecoder : public Decoder +namespace olive { - Q_OBJECT + +class OIIODecoder : public Decoder { + Q_OBJECT public: - OIIODecoder(); + OIIODecoder(); - DECODER_DEFAULT_DESTRUCTOR(OIIODecoder) + DECODER_DEFAULT_DESTRUCTOR(OIIODecoder) - virtual QString id() const override; + virtual QString id() const override; - virtual bool SupportsVideo() override{return true;} + virtual bool SupportsVideo() override + { + return true; + } - virtual FootageDescription Probe(const QString& filename, CancelAtom *cancelled) const override; + virtual FootageDescription Probe(const QString &filename, + CancelAtom *cancelled) const override; protected: - virtual bool OpenInternal() override; - virtual TexturePtr RetrieveVideoInternal(const RetrieveVideoParams& p) override; - virtual void CloseInternal() override; + virtual bool OpenInternal() override; + virtual TexturePtr + RetrieveVideoInternal(const RetrieveVideoParams &p) override; + virtual void CloseInternal() override; private: - std::unique_ptr image_; + std::unique_ptr image_; - static bool FileTypeIsSupported(const QString& fn); + static bool FileTypeIsSupported(const QString &fn); - bool OpenImageHandler(const QString& fn, int subimage); + bool OpenImageHandler(const QString &fn, int subimage); - void CloseImageHandle(); + void CloseImageHandle(); - static VideoParams GetVideoParamsFromImageSpec(const OIIO::ImageSpec &spec); + static VideoParams GetVideoParamsFromImageSpec(const OIIO::ImageSpec &spec); - PixelFormat pix_fmt_; - OIIO::TypeDesc::BASETYPE oiio_pix_fmt_; + PixelFormat pix_fmt_; + OIIO::TypeDesc::BASETYPE oiio_pix_fmt_; - Frame buffer_; - RetrieveVideoParams last_params_; - - static QStringList supported_formats_; + Frame buffer_; + RetrieveVideoParams last_params_; + static QStringList supported_formats_; }; } diff --git a/app/codec/oiio/oiioencoder.cpp b/app/codec/oiio/oiioencoder.cpp index 0b676615c..585d69210 100644 --- a/app/codec/oiio/oiioencoder.cpp +++ b/app/codec/oiio/oiioencoder.cpp @@ -22,60 +22,62 @@ #include "common/oiioutils.h" -namespace olive { - -OIIOEncoder::OIIOEncoder(const EncodingParams ¶ms) : - Encoder(params) +namespace olive { +OIIOEncoder::OIIOEncoder(const EncodingParams ¶ms) + : Encoder(params) +{ } bool OIIOEncoder::Open() { - return true; + return true; } bool OIIOEncoder::WriteFrame(FramePtr frame, rational time) { - std::string filename = GetFilenameForFrame(time).toStdString(); + std::string filename = GetFilenameForFrame(time).toStdString(); - auto output = OIIO::ImageOutput::create(filename); - if (!output) { - return false; - } + auto output = OIIO::ImageOutput::create(filename); + if (!output) { + return false; + } - OIIO::TypeDesc type = OIIOUtils::GetOIIOBaseTypeFromFormat(frame->format()); - OIIO::ImageSpec spec(frame->width(), frame->height(), frame->channel_count(), type); + OIIO::TypeDesc type = OIIOUtils::GetOIIOBaseTypeFromFormat(frame->format()); + OIIO::ImageSpec spec(frame->width(), frame->height(), + frame->channel_count(), type); - if (!output->open(filename, spec)) { - return false; - } + if (!output->open(filename, spec)) { + return false; + } - if (!output->write_image(type, frame->data(), OIIO::AutoStride, frame->linesize_bytes())) { - return false; - } + if (!output->write_image(type, frame->data(), OIIO::AutoStride, + frame->linesize_bytes())) { + return false; + } - if (!output->close()) { - return false; - } + if (!output->close()) { + return false; + } - return true; + return true; } bool OIIOEncoder::WriteAudio(const SampleBuffer &audio) { - // Do nothing - return false; + // Do nothing + return false; } bool OIIOEncoder::WriteSubtitle(const SubtitleBlock *sub_block) { - return false; + return false; } void OIIOEncoder::Close() { - // Do nothing + // Do nothing } } diff --git a/app/codec/oiio/oiioencoder.h b/app/codec/oiio/oiioencoder.h index 778a91474..cb3971774 100644 --- a/app/codec/oiio/oiioencoder.h +++ b/app/codec/oiio/oiioencoder.h @@ -23,23 +23,23 @@ #include "codec/encoder.h" -namespace olive { - -class OIIOEncoder : public Encoder +namespace olive { - Q_OBJECT + +class OIIOEncoder : public Encoder { + Q_OBJECT public: - OIIOEncoder(const EncodingParams ¶ms); + OIIOEncoder(const EncodingParams ¶ms); public slots: - virtual bool Open() override; + virtual bool Open() override; - virtual bool WriteFrame(olive::FramePtr frame, olive::core::rational time) override; - virtual bool WriteAudio(const SampleBuffer &audio) override; - virtual bool WriteSubtitle(const SubtitleBlock *sub_block) override; - - virtual void Close() override; + virtual bool WriteFrame(olive::FramePtr frame, + olive::core::rational time) override; + virtual bool WriteAudio(const SampleBuffer &audio) override; + virtual bool WriteSubtitle(const SubtitleBlock *sub_block) override; + virtual void Close() override; }; } diff --git a/app/codec/planarfiledevice.cpp b/app/codec/planarfiledevice.cpp index f8c961998..4db824dac 100644 --- a/app/codec/planarfiledevice.cpp +++ b/app/codec/planarfiledevice.cpp @@ -20,100 +20,103 @@ #include "planarfiledevice.h" -namespace olive { - -PlanarFileDevice::PlanarFileDevice(QObject *parent) : - QObject(parent) +namespace olive { +PlanarFileDevice::PlanarFileDevice(QObject *parent) + : QObject(parent) +{ } PlanarFileDevice::~PlanarFileDevice() { - close(); + close(); } -bool PlanarFileDevice::open(const QVector &filenames, QIODevice::OpenMode mode) +bool PlanarFileDevice::open(const QVector &filenames, + QIODevice::OpenMode mode) { - if (isOpen()) { - // Already open - return false; - } + if (isOpen()) { + // Already open + return false; + } - files_.resize(filenames.size()); - files_.fill(nullptr); + files_.resize(filenames.size()); + files_.fill(nullptr); - for (int i=0; iopen(mode)) { - close(); - return false; - } - } + for (int i = 0; i < files_.size(); i++) { + files_[i] = new QFile(filenames.at(i)); + if (!files_[i]->open(mode)) { + close(); + return false; + } + } - return true; + return true; } -qint64 PlanarFileDevice::read(char **data, qint64 bytes_per_channel, qint64 offset) +qint64 PlanarFileDevice::read(char **data, qint64 bytes_per_channel, + qint64 offset) { - qint64 ret = -1; + qint64 ret = -1; - if (isOpen()) { - for (int i=0; iread(data[i] + offset, bytes_per_channel); - } - } + if (isOpen()) { + for (int i = 0; i < files_.size(); i++) { + // Kind of clunky but should be largely fine + ret = files_[i]->read(data[i] + offset, bytes_per_channel); + } + } - return ret; + return ret; } -qint64 PlanarFileDevice::write(const char **data, qint64 bytes_per_channel, qint64 offset) +qint64 PlanarFileDevice::write(const char **data, qint64 bytes_per_channel, + qint64 offset) { - qint64 ret = -1; + qint64 ret = -1; - if (isOpen()) { - for (int i=0; iwrite(data[i] + offset, bytes_per_channel); - } - } + if (isOpen()) { + for (int i = 0; i < files_.size(); i++) { + // Kind of clunky but should be largely fine + ret = files_[i]->write(data[i] + offset, bytes_per_channel); + } + } - return ret; + return ret; } qint64 PlanarFileDevice::size() const { - if (isOpen()) { - return files_.first()->size(); - } else { - return 0; - } + if (isOpen()) { + return files_.first()->size(); + } else { + return 0; + } } bool PlanarFileDevice::seek(qint64 pos) { - bool ret = true; + bool ret = true; - for (int i=0; iseek(pos) & ret; - } + for (int i = 0; i < files_.size(); i++) { + ret = files_[i]->seek(pos) & ret; + } - return ret; + return ret; } void PlanarFileDevice::close() { - for (int i=0; iisOpen()) { - f->close(); - } - delete f; - } - } - files_.clear(); + for (int i = 0; i < files_.size(); i++) { + QFile *f = files_.at(i); + if (f) { + if (f->isOpen()) { + f->close(); + } + delete f; + } + } + files_.clear(); } } diff --git a/app/codec/planarfiledevice.h b/app/codec/planarfiledevice.h index feaf2c647..4f39a46cd 100644 --- a/app/codec/planarfiledevice.h +++ b/app/codec/planarfiledevice.h @@ -25,38 +25,38 @@ #include #include -namespace olive { +namespace olive +{ using namespace core; -class PlanarFileDevice : public QObject -{ - Q_OBJECT +class PlanarFileDevice : public QObject { + Q_OBJECT public: - PlanarFileDevice(QObject *parent = nullptr); + PlanarFileDevice(QObject *parent = nullptr); - virtual ~PlanarFileDevice() override; + virtual ~PlanarFileDevice() override; - bool isOpen() const - { - return !files_.isEmpty(); - } + bool isOpen() const + { + return !files_.isEmpty(); + } - bool open(const QVector &filenames, QIODevice::OpenMode mode); + bool open(const QVector &filenames, QIODevice::OpenMode mode); - qint64 read(char **data, qint64 bytes_per_channel, qint64 offset = 0); + qint64 read(char **data, qint64 bytes_per_channel, qint64 offset = 0); - qint64 write(const char **data, qint64 bytes_per_channel, qint64 offset = 0); + qint64 write(const char **data, qint64 bytes_per_channel, + qint64 offset = 0); - qint64 size() const; + qint64 size() const; - bool seek(qint64 pos); + bool seek(qint64 pos); - void close(); + void close(); private: - QVector files_; - + QVector files_; }; } diff --git a/app/common/autoscroll.h b/app/common/autoscroll.h index 8f35d3b55..46c34e871 100644 --- a/app/common/autoscroll.h +++ b/app/common/autoscroll.h @@ -23,15 +23,12 @@ #include "common/define.h" -namespace olive { +namespace olive +{ class AutoScroll { public: - enum Method { - kNone, - kPage, - kSmooth - }; + enum Method { kNone, kPage, kSmooth }; }; } diff --git a/app/common/cancelableobject.h b/app/common/cancelableobject.h index eef63d375..3cd686ea2 100644 --- a/app/common/cancelableobject.h +++ b/app/common/cancelableobject.h @@ -24,36 +24,38 @@ #include "common/define.h" #include "render/cancelatom.h" -namespace olive { +namespace olive +{ class CancelableObject { public: - CancelableObject() - { - } + CancelableObject() + { + } - void Cancel() - { - cancel_.Cancel(); - CancelEvent(); - } + void Cancel() + { + cancel_.Cancel(); + CancelEvent(); + } - CancelAtom *GetCancelAtom() - { - return &cancel_; - } + CancelAtom *GetCancelAtom() + { + return &cancel_; + } - bool IsCancelled() - { - return cancel_.IsCancelled(); - } + bool IsCancelled() + { + return cancel_.IsCancelled(); + } protected: - virtual void CancelEvent(){} + virtual void CancelEvent() + { + } private: - CancelAtom cancel_; - + CancelAtom cancel_; }; } diff --git a/app/common/commandlineparser.cpp b/app/common/commandlineparser.cpp index 4d1187c04..46ce5a85f 100644 --- a/app/common/commandlineparser.cpp +++ b/app/common/commandlineparser.cpp @@ -25,146 +25,154 @@ CommandLineParser::~CommandLineParser() { - foreach (const KnownOption& o, options_) { - delete o.option; - } + foreach (const KnownOption &o, options_) { + delete o.option; + } - foreach (const KnownPositionalArgument& a, positional_args_) { - delete a.option; - } + foreach (const KnownPositionalArgument &a, positional_args_) { + delete a.option; + } } -const CommandLineParser::Option *CommandLineParser::AddOption(const QStringList &strings, const QString &description, bool takes_arg, const QString &arg_placeholder, bool hidden) +const CommandLineParser::Option * +CommandLineParser::AddOption(const QStringList &strings, + const QString &description, bool takes_arg, + const QString &arg_placeholder, bool hidden) { - Option* o = new Option(); + Option *o = new Option(); - options_.append({strings, description, o, takes_arg, arg_placeholder, hidden}); + options_.append( + { strings, description, o, takes_arg, arg_placeholder, hidden }); - return o; + return o; } -const CommandLineParser::PositionalArgument *CommandLineParser::AddPositionalArgument(const QString &name, const QString &description, bool required) +const CommandLineParser::PositionalArgument * +CommandLineParser::AddPositionalArgument(const QString &name, + const QString &description, + bool required) { - PositionalArgument* a = new PositionalArgument(); + PositionalArgument *a = new PositionalArgument(); - positional_args_.append({name, description, a, required}); + positional_args_.append({ name, description, a, required }); - return a; + return a; } void CommandLineParser::Process(const QVector &argv) { - int positional_index = 0; + int positional_index = 0; - for (int i=1; iSet(); + foreach (const QString &s, o.args) { + if (!s.compare(arg_basename, Qt::CaseInsensitive)) { + // Flag discovered! + o.option->Set(); - if (o.takes_arg && i+1 < argv.size()) { - o.option->SetSetting(argv[i+1]); - i++; - } + if (o.takes_arg && i + 1 < argv.size()) { + o.option->SetSetting(argv[i + 1]); + i++; + } - matched_known = true; - goto found_flag; - } - } - } + matched_known = true; + goto found_flag; + } + } + } found_flag: - if (!matched_known) { - qWarning() << "Unknown parameter:" << argv[i]; - } + if (!matched_known) { + qWarning() << "Unknown parameter:" << argv[i]; + } - } else { - // Must be a positional flag - if (positional_index < positional_args_.size()) { - positional_args_[positional_index].option->SetSetting(argv[i]); - positional_index++; - } else { - qWarning() << "Unknown parameter:" << argv[i]; - } - } - } + } else { + // Must be a positional flag + if (positional_index < positional_args_.size()) { + positional_args_[positional_index].option->SetSetting(argv[i]); + positional_index++; + } else { + qWarning() << "Unknown parameter:" << argv[i]; + } + } + } } -void CommandLineParser::PrintHelp(const char* filename) +void CommandLineParser::PrintHelp(const char *filename) { - printf("%s %s\n", - QCoreApplication::applicationName().toUtf8().constData(), - QCoreApplication::applicationVersion().toUtf8().constData()); + printf("%s %s\n", QCoreApplication::applicationName().toUtf8().constData(), + QCoreApplication::applicationVersion().toUtf8().constData()); - printf("Copyright (C) 2018-2022 Olive Team\n"); + printf("Copyright (C) 2018-2022 Olive Team\n"); - QString positional_args; - for (int i=0; i 0) { - positional_args.append(' '); - } + QString positional_args; + for (int i = 0; i < positional_args_.size(); i++) { + if (i > 0) { + positional_args.append(' '); + } - positional_args.append('['); - positional_args.append(positional_args_.at(i).name); - positional_args.append(']'); - } + positional_args.append('['); + positional_args.append(positional_args_.at(i).name); + positional_args.append(']'); + } - const char* basename; + const char *basename; #ifdef Q_OS_WINDOWS - basename = strrchr(filename, '\\'); - if (!basename) { - basename = strrchr(filename, '/'); - } + basename = strrchr(filename, '\\'); + if (!basename) { + basename = strrchr(filename, '/'); + } #else - basename = strrchr(filename, '/'); + basename = strrchr(filename, '/'); #endif - if (basename) { - // Slash found, increment pointer to avoid showing the slash itself - basename++; - } else { - // If no slashes are found, assume string is already a basename - basename = filename; - } + if (basename) { + // Slash found, increment pointer to avoid showing the slash itself + basename++; + } else { + // If no slashes are found, assume string is already a basename + basename = filename; + } - printf("Usage: %s [options] %s\n\n", basename, positional_args.toUtf8().constData()); - foreach (const KnownOption& o, options_) { - if (o.hidden) { - continue; - } + printf("Usage: %s [options] %s\n\n", basename, + positional_args.toUtf8().constData()); + foreach (const KnownOption &o, options_) { + if (o.hidden) { + continue; + } - QString all_args; + QString all_args; - for (int i=0; i 0) { - all_args.append(QStringLiteral(", ")); - } + for (int i = 0; i < o.args.size(); i++) { + if (i > 0) { + all_args.append(QStringLiteral(", ")); + } - const QString& this_arg = o.args.at(i); + const QString &this_arg = o.args.at(i); - all_args.append('-'); - all_args.append(this_arg); - } + all_args.append('-'); + all_args.append(this_arg); + } - if (o.arg_placeholder.isEmpty()) { - printf(" %s\n", all_args.toUtf8().constData()); - } else { - printf(" %s <%s>\n", all_args.toUtf8().constData(), o.arg_placeholder.toUtf8().constData()); - } + if (o.arg_placeholder.isEmpty()) { + printf(" %s\n", all_args.toUtf8().constData()); + } else { + printf(" %s <%s>\n", all_args.toUtf8().constData(), + o.arg_placeholder.toUtf8().constData()); + } - printf(" %s\n\n", o.description.toUtf8().constData()); - } + printf(" %s\n\n", o.description.toUtf8().constData()); + } - printf("\n"); + printf("\n"); } diff --git a/app/common/commandlineparser.h b/app/common/commandlineparser.h index a1f49d2c4..b7a060c38 100644 --- a/app/common/commandlineparser.h +++ b/app/common/commandlineparser.h @@ -36,86 +36,86 @@ * the user as a command line argument. Therefore we needed a custom implementation that could * parse arguments without the need for a Q(Core)Application to be present already. */ -class CommandLineParser -{ +class CommandLineParser { public: - ~CommandLineParser(); + ~CommandLineParser(); - DISABLE_COPY_MOVE(CommandLineParser) + DISABLE_COPY_MOVE(CommandLineParser) - class PositionalArgument - { - public: - PositionalArgument() = default; + class PositionalArgument { + public: + PositionalArgument() = default; - const QString& GetSetting() const - { - return setting_; - } + const QString &GetSetting() const + { + return setting_; + } - void SetSetting(const QString& s) - { - setting_ = s; - } + void SetSetting(const QString &s) + { + setting_ = s; + } - private: - QString setting_; + private: + QString setting_; + }; - }; + class Option : public PositionalArgument { + public: + Option() + { + is_set_ = false; + } - class Option : public PositionalArgument { - public: - Option() - { - is_set_ = false; - } + bool IsSet() const + { + return is_set_; + } - bool IsSet() const - { - return is_set_; - } + void Set() + { + is_set_ = true; + } - void Set() - { - is_set_ = true; - } + private: + bool is_set_; + }; - private: - bool is_set_; + CommandLineParser() = default; - }; + const Option *AddOption(const QStringList &strings, + const QString &description, bool takes_arg = false, + const QString &arg_placeholder = QString(), + bool hidden = false); - CommandLineParser() = default; + const PositionalArgument *AddPositionalArgument(const QString &name, + const QString &description, + bool required = false); - const Option* AddOption(const QStringList& strings, const QString& description, bool takes_arg = false, const QString& arg_placeholder = QString(), bool hidden = false); + void Process(const QVector &argv); - const PositionalArgument* AddPositionalArgument(const QString& name, const QString& description, bool required = false); - - void Process(const QVector &argv); - - void PrintHelp(const char* filename); + void PrintHelp(const char *filename); private: - struct KnownOption { - QStringList args; - QString description; - Option* option; - bool takes_arg; - QString arg_placeholder; - bool hidden; - }; + struct KnownOption { + QStringList args; + QString description; + Option *option; + bool takes_arg; + QString arg_placeholder; + bool hidden; + }; - struct KnownPositionalArgument { - QString name; - QString description; - PositionalArgument* option; - bool required; - }; + struct KnownPositionalArgument { + QString name; + QString description; + PositionalArgument *option; + bool required; + }; - QVector options_; - - QVector positional_args_; + QVector options_; + QVector positional_args_; }; #endif // COMMANDLINEPARSER_H diff --git a/app/common/crashpadinterface.cpp b/app/common/crashpadinterface.cpp index 6cee4f9c4..8ae837efc 100644 --- a/app/common/crashpadinterface.cpp +++ b/app/common/crashpadinterface.cpp @@ -40,52 +40,63 @@ crashpad::CrashpadClient *client; bool InitializeCrashpad() { - QString report_path = QDir(olive::FileFunctions::GetTempFilePath()).filePath(QStringLiteral("reports")); + QString report_path = QDir(olive::FileFunctions::GetTempFilePath()) + .filePath(QStringLiteral("reports")); - QString handler_fn = olive::FileFunctions::GetFormattedExecutableForPlatform(QStringLiteral("crashpad_handler")); + QString handler_fn = + olive::FileFunctions::GetFormattedExecutableForPlatform( + QStringLiteral("crashpad_handler")); - // Generate absolute path - QString handler_abs_path = QDir(QCoreApplication::applicationDirPath()).filePath(handler_fn); + // Generate absolute path + QString handler_abs_path = + QDir(QCoreApplication::applicationDirPath()).filePath(handler_fn); - bool status = false; + bool status = false; - if (QFileInfo::exists(handler_abs_path)) { - base::FilePath handler(QSTRING_TO_BASE_STRING(handler_abs_path)); + if (QFileInfo::exists(handler_abs_path)) { + base::FilePath handler(QSTRING_TO_BASE_STRING(handler_abs_path)); - base::FilePath reports_dir(QSTRING_TO_BASE_STRING(report_path)); + base::FilePath reports_dir(QSTRING_TO_BASE_STRING(report_path)); - base::FilePath metrics_dir(QSTRING_TO_BASE_STRING(QDir(olive::FileFunctions::GetTempFilePath()).filePath(QStringLiteral("metrics")))); + base::FilePath metrics_dir( + QSTRING_TO_BASE_STRING(QDir(olive::FileFunctions::GetTempFilePath()) + .filePath(QStringLiteral("metrics")))); - // Metadata that will be posted to the server with the crash report map - std::map annotations; + // Metadata that will be posted to the server with the crash report map + std::map annotations; - // Disable crashpad rate limiting so that all crashes have dmp files - std::vector arguments; - arguments.push_back("--no-rate-limit"); - arguments.push_back("--no-upload-gzip"); + // Disable crashpad rate limiting so that all crashes have dmp files + std::vector arguments; + arguments.push_back("--no-rate-limit"); + arguments.push_back("--no-upload-gzip"); - // Initialize Crashpad database - std::unique_ptr database = crashpad::CrashReportDatabase::Initialize(reports_dir); - if (database == NULL) return false; + // Initialize Crashpad database + std::unique_ptr database = + crashpad::CrashReportDatabase::Initialize(reports_dir); + if (database == NULL) + return false; - // Disable automated crash uploads - crashpad::Settings *settings = database->GetSettings(); - if (settings == NULL) return false; - settings->SetUploadsEnabled(false); + // Disable automated crash uploads + crashpad::Settings *settings = database->GetSettings(); + if (settings == NULL) + return false; + settings->SetUploadsEnabled(false); - // Start crash handler - client = new crashpad::CrashpadClient(); - status = client->StartHandler(handler, reports_dir, metrics_dir, - "https://olivevideoeditor.org/crashpad/report.php", - annotations, arguments, true, true); - } + // Start crash handler + client = new crashpad::CrashpadClient(); + status = client->StartHandler( + handler, reports_dir, metrics_dir, + "https://olivevideoeditor.org/crashpad/report.php", annotations, + arguments, true, true); + } - // Override Crashpad exception filter with our own - if (!status) { - qWarning() << "Failed to start Crashpad, automatic crash reporting will be disabled"; - } + // Override Crashpad exception filter with our own + if (!status) { + qWarning() + << "Failed to start Crashpad, automatic crash reporting will be disabled"; + } - return status; + return status; } #endif // USE_CRASHPAD diff --git a/app/common/crashpadutils.h b/app/common/crashpadutils.h index 8b0e3e6d7..b30eca5a1 100644 --- a/app/common/crashpadutils.h +++ b/app/common/crashpadutils.h @@ -35,6 +35,6 @@ // arrays encoded in UTF-16. #define QSTRING_TO_BASE_STRING(x) x.toStdWString() #define BASE_STRING_TO_QSTRING(x) QString::fromStdWString(x) -#endif // BUILDFLAG(IS_WIN) +#endif // BUILDFLAG(IS_WIN) #endif // CRASHPADUTILS_H diff --git a/app/common/debug.cpp b/app/common/debug.cpp index c289c2f7c..734572976 100644 --- a/app/common/debug.cpp +++ b/app/common/debug.cpp @@ -20,38 +20,40 @@ #include "debug.h" -namespace olive { - -void DebugHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg) +namespace olive { - QByteArray localMsg = msg.toLocal8Bit(); - const char* msg_type = "UNKNOWN"; - switch (type) { - case QtDebugMsg: - msg_type = "DEBUG"; - break; - case QtInfoMsg: - msg_type = "INFO"; - break; - case QtWarningMsg: - msg_type = "WARNING"; - break; - case QtCriticalMsg: - msg_type = "ERROR"; - break; - case QtFatalMsg: - msg_type = "FATAL"; - break; - } +void DebugHandler(QtMsgType type, const QMessageLogContext &context, + const QString &msg) +{ + QByteArray localMsg = msg.toLocal8Bit(); - //fprintf(stderr, "[%s] %s (%s:%u)\n", msg_type, localMsg.constData(), context.function, context.line); - fprintf(stderr, "[%s] %s\n", msg_type, localMsg.constData()); + const char *msg_type = "UNKNOWN"; + switch (type) { + case QtDebugMsg: + msg_type = "DEBUG"; + break; + case QtInfoMsg: + msg_type = "INFO"; + break; + case QtWarningMsg: + msg_type = "WARNING"; + break; + case QtCriticalMsg: + msg_type = "ERROR"; + break; + case QtFatalMsg: + msg_type = "FATAL"; + break; + } + + //fprintf(stderr, "[%s] %s (%s:%u)\n", msg_type, localMsg.constData(), context.function, context.line); + fprintf(stderr, "[%s] %s\n", msg_type, localMsg.constData()); #ifdef Q_OS_WINDOWS - // Windows still seems to buffer stderr and we want to see debug messages immediately, so here we make sure each line - // is flushed - fflush(stderr); + // Windows still seems to buffer stderr and we want to see debug messages immediately, so here we make sure each line + // is flushed + fflush(stderr); #endif } diff --git a/app/common/debug.h b/app/common/debug.h index b2a5e9289..fd131dc1c 100644 --- a/app/common/debug.h +++ b/app/common/debug.h @@ -25,9 +25,11 @@ #include "common/define.h" -namespace olive { +namespace olive +{ -void DebugHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg); +void DebugHandler(QtMsgType type, const QMessageLogContext &context, + const QString &msg); } diff --git a/app/common/decibel.h b/app/common/decibel.h index 569b0a969..bdb56bd26 100644 --- a/app/common/decibel.h +++ b/app/common/decibel.h @@ -26,77 +26,76 @@ //#define ALLOW_RETURNING_INFINITY -namespace olive { - -class Decibel +namespace olive { + +class Decibel { public: - // In basically all circumstances, this should calculate to 0.0 linear - static constexpr double MINIMUM = -200.0; + // In basically all circumstances, this should calculate to 0.0 linear + static constexpr double MINIMUM = -200.0; - static double fromLinear(double linear) - { - double v = double(20.0) * std::log10(linear); + static double fromLinear(double linear) + { + double v = double(20.0) * std::log10(linear); #ifndef ALLOW_RETURNING_INFINITY - if (std::isinf(v)) { - return MINIMUM; - } + if (std::isinf(v)) { + return MINIMUM; + } #endif - return v; - } + return v; + } - static double toLinear(double decibel) - { - double to_linear = std::pow(double(10.0), decibel / double(20.0)); + static double toLinear(double decibel) + { + double to_linear = std::pow(double(10.0), decibel / double(20.0)); - // Minimum threshold that we figure is close enough to 0 that we may as well just return 0 - if (to_linear < 0.000001) { - return 0; - } else { - return to_linear; - } - } + // Minimum threshold that we figure is close enough to 0 that we may as well just return 0 + if (to_linear < 0.000001) { + return 0; + } else { + return to_linear; + } + } - static double fromLogarithmic(double logarithmic) - { - if (logarithmic < 0.001) + static double fromLogarithmic(double logarithmic) + { + if (logarithmic < 0.001) #ifdef ALLOW_RETURNING_INFINITY - return std::numeric_limits::infinity(); + return std::numeric_limits::infinity(); #else - return MINIMUM; + return MINIMUM; #endif - else if (logarithmic > 0.99) - return 0; - else - return 20.0 * std::log10(-std::log(1 - logarithmic) / LOG100); - } + else if (logarithmic > 0.99) + return 0; + else + return 20.0 * std::log10(-std::log(1 - logarithmic) / LOG100); + } - static double toLogarithmic(double decibel) - { - if (qFuzzyIsNull(decibel)) { - return 1; - } else { - return 1 - std::exp(-std::pow(10.0, decibel / 20.0) * LOG100); - } - } + static double toLogarithmic(double decibel) + { + if (qFuzzyIsNull(decibel)) { + return 1; + } else { + return 1 - std::exp(-std::pow(10.0, decibel / 20.0) * LOG100); + } + } - static double LinearToLogarithmic(double linear) - { - return 1 - std::exp(-linear * LOG100); - } + static double LinearToLogarithmic(double linear) + { + return 1 - std::exp(-linear * LOG100); + } - static double LogarithmicToLinear(double logarithmic) - { - if (logarithmic > 0.99) { - return 1; - } else { - return -std::log(1 - logarithmic) / LOG100; - } - } + static double LogarithmicToLinear(double logarithmic) + { + if (logarithmic > 0.99) { + return 1; + } else { + return -std::log(1 - logarithmic) / LOG100; + } + } private: - static constexpr double LOG100 = 4.60517018599; - + static constexpr double LOG100 = 4.60517018599; }; } diff --git a/app/common/define.h b/app/common/define.h index 889020eaf..3782eeb6c 100644 --- a/app/common/define.h +++ b/app/common/define.h @@ -21,7 +21,8 @@ #ifndef OLIVECOMMONDEFINE_H #define OLIVECOMMONDEFINE_H -namespace olive { +namespace olive +{ /// The minimum size an icon in ProjectExplorer can be const int kProjectIconSizeMinimum = 16; @@ -39,25 +40,28 @@ const int kBytesInGigabyte = 1073741824; #define MACRO_NAME_AS_STR(s) #s #define MACRO_VAL_AS_STR(s) MACRO_NAME_AS_STR(s) -#define OLIVE_NS_CONST_ARG(x, y) QArgument("const " MACRO_VAL_AS_STR(olive) "::" #x, y) -#define OLIVE_NS_ARG(x, y) QArgument(MACRO_VAL_AS_STR(olive) "::" #x, y) -#define OLIVE_NS_RETURN_ARG(x, y) QReturnArgument(MACRO_VAL_AS_STR(olive) "::" #x, y) +#define OLIVE_NS_CONST_ARG(x, y) \ + QArgument("const " MACRO_VAL_AS_STR(olive) "::" #x, y) +#define OLIVE_NS_ARG(x, y) \ + QArgument(MACRO_VAL_AS_STR(olive) "::" #x, y) +#define OLIVE_NS_RETURN_ARG(x, y) \ + QReturnArgument(MACRO_VAL_AS_STR(olive) "::" #x, y) /** * Copy/move deleters. Similar to Q_DISABLE_COPY_MOVE, et al. but those functions are not present in Qt < 5.13 so we * use our own functions for portability. */ -#define DISABLE_COPY(Class) \ - Class(const Class &) = delete;\ - Class &operator=(const Class &) = delete; +#define DISABLE_COPY(Class) \ + Class(const Class &) = delete; \ + Class &operator=(const Class &) = delete; -#define DISABLE_MOVE(Class) \ - Class(Class &&) = delete; \ - Class &operator=(Class &&) = delete; +#define DISABLE_MOVE(Class) \ + Class(Class &&) = delete; \ + Class &operator=(Class &&) = delete; #define DISABLE_COPY_MOVE(Class) \ - DISABLE_COPY(Class) \ - DISABLE_MOVE(Class) + DISABLE_COPY(Class) \ + DISABLE_MOVE(Class) #endif // OLIVECOMMONDEFINE_H diff --git a/app/common/digit.h b/app/common/digit.h index 7e03f96ff..4b4ef9d4a 100644 --- a/app/common/digit.h +++ b/app/common/digit.h @@ -23,21 +23,22 @@ #include -namespace olive { +namespace olive +{ inline int64_t GetDigitCount(int64_t input) { - input = std::abs(input); + input = std::abs(input); - int64_t lim = 10; - int64_t digit = 1; + int64_t lim = 10; + int64_t digit = 1; - while (input >= lim) { - lim *= 10; - digit++; - } + while (input >= lim) { + lim *= 10; + digit++; + } - return digit; + return digit; } } diff --git a/app/common/ffmpegutils.cpp b/app/common/ffmpegutils.cpp index 81ae18b4f..5e516998f 100644 --- a/app/common/ffmpegutils.cpp +++ b/app/common/ffmpegutils.cpp @@ -20,180 +20,187 @@ #include "common/ffmpegutils.h" -namespace olive { - -AVPixelFormat FFmpegUtils::GetCompatiblePixelFormat(const AVPixelFormat &pix_fmt, PixelFormat maximum) +namespace olive { - AVPixelFormat possible_pix_fmts[3]; - possible_pix_fmts[0] = AV_PIX_FMT_RGBA; +AVPixelFormat +FFmpegUtils::GetCompatiblePixelFormat(const AVPixelFormat &pix_fmt, + PixelFormat maximum) +{ + AVPixelFormat possible_pix_fmts[3]; - if (maximum == PixelFormat::U8) { - possible_pix_fmts[1] = AV_PIX_FMT_NONE; - } else { - possible_pix_fmts[1] = AV_PIX_FMT_RGBA64; - possible_pix_fmts[2] = AV_PIX_FMT_NONE; - } + possible_pix_fmts[0] = AV_PIX_FMT_RGBA; - return avcodec_find_best_pix_fmt_of_list(possible_pix_fmts, - pix_fmt, - 1, - nullptr); + if (maximum == PixelFormat::U8) { + possible_pix_fmts[1] = AV_PIX_FMT_NONE; + } else { + possible_pix_fmts[1] = AV_PIX_FMT_RGBA64; + possible_pix_fmts[2] = AV_PIX_FMT_NONE; + } + + return avcodec_find_best_pix_fmt_of_list(possible_pix_fmts, pix_fmt, 1, + nullptr); } SampleFormat FFmpegUtils::GetNativeSampleFormat(const AVSampleFormat &smp_fmt) { - switch (smp_fmt) { - case AV_SAMPLE_FMT_U8: - return SampleFormat::U8; - case AV_SAMPLE_FMT_S16: - return SampleFormat::S16; - case AV_SAMPLE_FMT_S32: - return SampleFormat::S32; - case AV_SAMPLE_FMT_S64: - return SampleFormat::S64; - case AV_SAMPLE_FMT_FLT: - return SampleFormat::F32; - case AV_SAMPLE_FMT_DBL: - return SampleFormat::F64; - case AV_SAMPLE_FMT_U8P : - return SampleFormat::U8P; - case AV_SAMPLE_FMT_S16P: - return SampleFormat::S16P; - case AV_SAMPLE_FMT_S32P: - return SampleFormat::S32P; - case AV_SAMPLE_FMT_S64P: - return SampleFormat::S64P; - case AV_SAMPLE_FMT_FLTP: - return SampleFormat::F32P; - case AV_SAMPLE_FMT_DBLP: - return SampleFormat::F64P; - case AV_SAMPLE_FMT_NONE: - case AV_SAMPLE_FMT_NB: - break; - } + switch (smp_fmt) { + case AV_SAMPLE_FMT_U8: + return SampleFormat::U8; + case AV_SAMPLE_FMT_S16: + return SampleFormat::S16; + case AV_SAMPLE_FMT_S32: + return SampleFormat::S32; + case AV_SAMPLE_FMT_S64: + return SampleFormat::S64; + case AV_SAMPLE_FMT_FLT: + return SampleFormat::F32; + case AV_SAMPLE_FMT_DBL: + return SampleFormat::F64; + case AV_SAMPLE_FMT_U8P: + return SampleFormat::U8P; + case AV_SAMPLE_FMT_S16P: + return SampleFormat::S16P; + case AV_SAMPLE_FMT_S32P: + return SampleFormat::S32P; + case AV_SAMPLE_FMT_S64P: + return SampleFormat::S64P; + case AV_SAMPLE_FMT_FLTP: + return SampleFormat::F32P; + case AV_SAMPLE_FMT_DBLP: + return SampleFormat::F64P; + case AV_SAMPLE_FMT_NONE: + case AV_SAMPLE_FMT_NB: + break; + } - return SampleFormat::INVALID; + return SampleFormat::INVALID; } AVSampleFormat FFmpegUtils::GetFFmpegSampleFormat(const SampleFormat &smp_fmt) { - switch (smp_fmt) { - case SampleFormat::U8: - return AV_SAMPLE_FMT_U8; - case SampleFormat::S16: - return AV_SAMPLE_FMT_S16; - case SampleFormat::S32: - return AV_SAMPLE_FMT_S32; - case SampleFormat::S64: - return AV_SAMPLE_FMT_S64; - case SampleFormat::F32: - return AV_SAMPLE_FMT_FLT; - case SampleFormat::F64: - return AV_SAMPLE_FMT_DBL; - case SampleFormat::U8P: - return AV_SAMPLE_FMT_U8P; - case SampleFormat::S16P: - return AV_SAMPLE_FMT_S16P; - case SampleFormat::S32P: - return AV_SAMPLE_FMT_S32P; - case SampleFormat::S64P: - return AV_SAMPLE_FMT_S64P; - case SampleFormat::F32P: - return AV_SAMPLE_FMT_FLTP; - case SampleFormat::F64P: - return AV_SAMPLE_FMT_DBLP; - case SampleFormat::INVALID: - case SampleFormat::COUNT: - break; - } + switch (smp_fmt) { + case SampleFormat::U8: + return AV_SAMPLE_FMT_U8; + case SampleFormat::S16: + return AV_SAMPLE_FMT_S16; + case SampleFormat::S32: + return AV_SAMPLE_FMT_S32; + case SampleFormat::S64: + return AV_SAMPLE_FMT_S64; + case SampleFormat::F32: + return AV_SAMPLE_FMT_FLT; + case SampleFormat::F64: + return AV_SAMPLE_FMT_DBL; + case SampleFormat::U8P: + return AV_SAMPLE_FMT_U8P; + case SampleFormat::S16P: + return AV_SAMPLE_FMT_S16P; + case SampleFormat::S32P: + return AV_SAMPLE_FMT_S32P; + case SampleFormat::S64P: + return AV_SAMPLE_FMT_S64P; + case SampleFormat::F32P: + return AV_SAMPLE_FMT_FLTP; + case SampleFormat::F64P: + return AV_SAMPLE_FMT_DBLP; + case SampleFormat::INVALID: + case SampleFormat::COUNT: + break; + } - return AV_SAMPLE_FMT_NONE; + return AV_SAMPLE_FMT_NONE; } int FFmpegUtils::GetSwsColorspaceFromAVColorSpace(AVColorSpace cs) { - switch (cs) { - case AVCOL_SPC_BT709: - return SWS_CS_ITU709; - case AVCOL_SPC_FCC: - return SWS_CS_FCC; - case AVCOL_SPC_BT470BG: - return SWS_CS_ITU624; - case AVCOL_SPC_SMPTE170M: - return SWS_CS_SMPTE170M; - case AVCOL_SPC_SMPTE240M: - return SWS_CS_SMPTE240M; - case AVCOL_SPC_BT2020_NCL: - return SWS_CS_BT2020; - default: - break; - } + switch (cs) { + case AVCOL_SPC_BT709: + return SWS_CS_ITU709; + case AVCOL_SPC_FCC: + return SWS_CS_FCC; + case AVCOL_SPC_BT470BG: + return SWS_CS_ITU624; + case AVCOL_SPC_SMPTE170M: + return SWS_CS_SMPTE170M; + case AVCOL_SPC_SMPTE240M: + return SWS_CS_SMPTE240M; + case AVCOL_SPC_BT2020_NCL: + return SWS_CS_BT2020; + default: + break; + } - return SWS_CS_DEFAULT; + return SWS_CS_DEFAULT; } AVPixelFormat FFmpegUtils::ConvertJPEGSpaceToRegularSpace(AVPixelFormat f) { - switch (f) { - case AV_PIX_FMT_YUVJ420P: return AV_PIX_FMT_YUV420P; - case AV_PIX_FMT_YUVJ422P: return AV_PIX_FMT_YUV422P; - case AV_PIX_FMT_YUVJ444P: return AV_PIX_FMT_YUV444P; - case AV_PIX_FMT_YUVJ440P: return AV_PIX_FMT_YUV440P; - case AV_PIX_FMT_YUVJ411P: return AV_PIX_FMT_YUV411P; - default: - break; - } + switch (f) { + case AV_PIX_FMT_YUVJ420P: + return AV_PIX_FMT_YUV420P; + case AV_PIX_FMT_YUVJ422P: + return AV_PIX_FMT_YUV422P; + case AV_PIX_FMT_YUVJ444P: + return AV_PIX_FMT_YUV444P; + case AV_PIX_FMT_YUVJ440P: + return AV_PIX_FMT_YUV440P; + case AV_PIX_FMT_YUVJ411P: + return AV_PIX_FMT_YUV411P; + default: + break; + } - return f; + return f; } -AVPixelFormat FFmpegUtils::GetFFmpegPixelFormat(const PixelFormat &pix_fmt, int channel_layout) +AVPixelFormat FFmpegUtils::GetFFmpegPixelFormat(const PixelFormat &pix_fmt, + int channel_layout) { - if (channel_layout == VideoParams::kRGBChannelCount) { - switch (pix_fmt) { - case PixelFormat::U8: - return AV_PIX_FMT_RGB24; - case PixelFormat::U16: - return AV_PIX_FMT_RGB48; - case PixelFormat::F16: - case PixelFormat::F32: - case PixelFormat::INVALID: - case PixelFormat::COUNT: - break; - } - } else if (channel_layout == VideoParams::kRGBAChannelCount) { - switch (pix_fmt) { - case PixelFormat::U8: - return AV_PIX_FMT_RGBA; - case PixelFormat::U16: - return AV_PIX_FMT_RGBA64; - case PixelFormat::F16: - case PixelFormat::F32: - case PixelFormat::INVALID: - case PixelFormat::COUNT: - break; - } - } + if (channel_layout == VideoParams::kRGBChannelCount) { + switch (pix_fmt) { + case PixelFormat::U8: + return AV_PIX_FMT_RGB24; + case PixelFormat::U16: + return AV_PIX_FMT_RGB48; + case PixelFormat::F16: + case PixelFormat::F32: + case PixelFormat::INVALID: + case PixelFormat::COUNT: + break; + } + } else if (channel_layout == VideoParams::kRGBAChannelCount) { + switch (pix_fmt) { + case PixelFormat::U8: + return AV_PIX_FMT_RGBA; + case PixelFormat::U16: + return AV_PIX_FMT_RGBA64; + case PixelFormat::F16: + case PixelFormat::F32: + case PixelFormat::INVALID: + case PixelFormat::COUNT: + break; + } + } - return AV_PIX_FMT_NONE; + return AV_PIX_FMT_NONE; } PixelFormat FFmpegUtils::GetCompatiblePixelFormat(const PixelFormat &pix_fmt) { - switch (pix_fmt) { - case PixelFormat::U8: - return PixelFormat::U8; - case PixelFormat::U16: - case PixelFormat::F16: - case PixelFormat::F32: - return PixelFormat::U16; - case PixelFormat::INVALID: - case PixelFormat::COUNT: - break; - } + switch (pix_fmt) { + case PixelFormat::U8: + return PixelFormat::U8; + case PixelFormat::U16: + case PixelFormat::F16: + case PixelFormat::F32: + return PixelFormat::U16; + case PixelFormat::INVALID: + case PixelFormat::COUNT: + break; + } - return PixelFormat::INVALID; + return PixelFormat::INVALID; } } diff --git a/app/common/ffmpegutils.h b/app/common/ffmpegutils.h index 89252fd53..1d5e7da29 100644 --- a/app/common/ffmpegutils.h +++ b/app/common/ffmpegutils.h @@ -31,63 +31,67 @@ extern "C" { #include "render/videoparams.h" -namespace olive { +namespace olive +{ using namespace core; class FFmpegUtils { public: - /** + /** * @brief Returns an AVPixelFormat that can be used to convert a frame to a data type Olive supports with minimal data loss */ - static AVPixelFormat GetCompatiblePixelFormat(const AVPixelFormat& pix_fmt, PixelFormat maximum = PixelFormat::INVALID); + static AVPixelFormat + GetCompatiblePixelFormat(const AVPixelFormat &pix_fmt, + PixelFormat maximum = PixelFormat::INVALID); - /** + /** * @brief Returns a native pixel format that can be used to convert from a native frame to an AVFrame with minimal data loss */ - static PixelFormat GetCompatiblePixelFormat(const PixelFormat& pix_fmt); + static PixelFormat GetCompatiblePixelFormat(const PixelFormat &pix_fmt); - /** + /** * @brief Returns an FFmpeg pixel format for a given native pixel format */ - static AVPixelFormat GetFFmpegPixelFormat(const PixelFormat& pix_fmt, int channel_layout); + static AVPixelFormat GetFFmpegPixelFormat(const PixelFormat &pix_fmt, + int channel_layout); - /** + /** * @brief Returns a native sample format type for a given AVSampleFormat */ - static SampleFormat GetNativeSampleFormat(const AVSampleFormat& smp_fmt); + static SampleFormat GetNativeSampleFormat(const AVSampleFormat &smp_fmt); - /** + /** * @brief Returns an FFmpeg sample format type for a given native type */ - static AVSampleFormat GetFFmpegSampleFormat(const SampleFormat &smp_fmt); + static AVSampleFormat GetFFmpegSampleFormat(const SampleFormat &smp_fmt); - /** + /** * @brief Returns an SWS_CS_* macro from an AVColorSpace enum member * * Why aren't these the same thing anyway? And for that matter, why doesn't FFmpeg provide a * convenience function to do this conversion for us? Who knows, but here we are. */ - static int GetSwsColorspaceFromAVColorSpace(AVColorSpace cs); + static int GetSwsColorspaceFromAVColorSpace(AVColorSpace cs); - /** + /** * @brief Convert "JPEG"/full-range colorspace to its regular counterpart * * "JPEG "spaces are deprecated in favor of the regular space and setting `color_range`. For the * time being, FFmpeg still uses these JPEG spaces, so for simplicity (since we *are* color_range * aware), we use this function. */ - static AVPixelFormat ConvertJPEGSpaceToRegularSpace(AVPixelFormat f); + static AVPixelFormat ConvertJPEGSpaceToRegularSpace(AVPixelFormat f); }; using AVFramePtr = std::shared_ptr; inline AVFramePtr CreateAVFramePtr(AVFrame *f) { - return std::shared_ptr(f, [](AVFrame *g){ av_frame_free(&g); }); + return std::shared_ptr(f, [](AVFrame *g) { av_frame_free(&g); }); } inline AVFramePtr CreateAVFramePtr() { - return CreateAVFramePtr(av_frame_alloc()); + return CreateAVFramePtr(av_frame_alloc()); } } diff --git a/app/common/filefunctions.cpp b/app/common/filefunctions.cpp index 6630470cd..ac7ccfc24 100644 --- a/app/common/filefunctions.cpp +++ b/app/common/filefunctions.cpp @@ -29,206 +29,223 @@ #include "config/config.h" -namespace olive { +namespace olive +{ QString FileFunctions::GetUniqueFileIdentifier(const QString &filename) { - QFileInfo info(filename); + QFileInfo info(filename); - if (!info.exists()) { - return QString(); - } + if (!info.exists()) { + return QString(); + } - QCryptographicHash hash(QCryptographicHash::Sha1); + QCryptographicHash hash(QCryptographicHash::Sha1); - hash.addData(info.absoluteFilePath().toUtf8()); + hash.addData(info.absoluteFilePath().toUtf8()); - hash.addData(QString::number(info.lastModified().toMSecsSinceEpoch()).toUtf8()); + hash.addData( + QString::number(info.lastModified().toMSecsSinceEpoch()).toUtf8()); - QByteArray result = hash.result(); + QByteArray result = hash.result(); - return QString(result.toHex()); + return QString(result.toHex()); } QString FileFunctions::GetConfigurationLocation() { - if (IsPortable()) { - return GetApplicationPath(); - } else { - QString s = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation); - QDir(s).mkpath("."); - return s; - } + if (IsPortable()) { + return GetApplicationPath(); + } else { + QString s = + QStandardPaths::writableLocation(QStandardPaths::AppDataLocation); + QDir(s).mkpath("."); + return s; + } } bool FileFunctions::IsPortable() { - return QFileInfo::exists(QDir(GetApplicationPath()).filePath("portable")); + return QFileInfo::exists(QDir(GetApplicationPath()).filePath("portable")); } QString FileFunctions::GetApplicationPath() { - return QCoreApplication::applicationDirPath(); + return QCoreApplication::applicationDirPath(); } QString FileFunctions::GetTempFilePath() { - QString temp_path = QDir(QDir(QStandardPaths::writableLocation(QStandardPaths::TempLocation)) - .filePath(QCoreApplication::organizationName())) - .filePath(QCoreApplication::applicationName()); + QString temp_path = + QDir( + QDir(QStandardPaths::writableLocation(QStandardPaths::TempLocation)) + .filePath(QCoreApplication::organizationName())) + .filePath(QCoreApplication::applicationName()); - // Ensure it exists - QDir(temp_path).mkpath("."); + // Ensure it exists + QDir(temp_path).mkpath("."); - return temp_path; + return temp_path; } -bool FileFunctions::CanCopyDirectoryWithoutOverwriting(const QString& source, const QString& dest) +bool FileFunctions::CanCopyDirectoryWithoutOverwriting(const QString &source, + const QString &dest) { - QFileInfoList info_list = QDir(source).entryInfoList(); + QFileInfoList info_list = QDir(source).entryInfoList(); - foreach (const QFileInfo& info, info_list) { - // QDir::NoDotAndDotDot continues to not work, so we have to check manually - if (info.fileName() == QStringLiteral(".") || info.fileName() == QStringLiteral("..")) { - continue; - } + foreach (const QFileInfo &info, info_list) { + // QDir::NoDotAndDotDot continues to not work, so we have to check manually + if (info.fileName() == QStringLiteral(".") || + info.fileName() == QStringLiteral("..")) { + continue; + } - QString dest_equivalent = QDir(dest).filePath(info.fileName()); + QString dest_equivalent = QDir(dest).filePath(info.fileName()); - if (info.isDir()) { - if (!CanCopyDirectoryWithoutOverwriting(info.absoluteFilePath(), dest_equivalent)) { - return false; - } - } else if (QFileInfo::exists(dest_equivalent)) { - return false; - } - } + if (info.isDir()) { + if (!CanCopyDirectoryWithoutOverwriting(info.absoluteFilePath(), + dest_equivalent)) { + return false; + } + } else if (QFileInfo::exists(dest_equivalent)) { + return false; + } + } - return true; + return true; } -void FileFunctions::CopyDirectory(const QString &source, const QString &dest, bool overwrite) +void FileFunctions::CopyDirectory(const QString &source, const QString &dest, + bool overwrite) { - QDir d(source); + QDir d(source); - if (!d.exists()) { - qCritical() << "Failed to copy directory, source" << source << "didn't exist"; - return; - } + if (!d.exists()) { + qCritical() + << "Failed to copy directory, source" << source << "didn't exist"; + return; + } - QDir dest_dir(dest); + QDir dest_dir(dest); - if (!dest_dir.mkpath(QStringLiteral("."))) { - qCritical() << "Failed to create destination directory" << dest; - return; - } + if (!dest_dir.mkpath(QStringLiteral("."))) { + qCritical() << "Failed to create destination directory" << dest; + return; + } - QFileInfoList l = d.entryInfoList(); + QFileInfoList l = d.entryInfoList(); - foreach (const QFileInfo& info, l) { - // QDir::NoDotAndDotDot continues to not work, so we have to check manually - if (info.fileName() == QStringLiteral(".") || info.fileName() == QStringLiteral("..")) { - continue; - } + foreach (const QFileInfo &info, l) { + // QDir::NoDotAndDotDot continues to not work, so we have to check manually + if (info.fileName() == QStringLiteral(".") || + info.fileName() == QStringLiteral("..")) { + continue; + } - QString dest_file_path = dest_dir.filePath(info.fileName()); + QString dest_file_path = dest_dir.filePath(info.fileName()); - if (info.isDir()) { - // Copy dir - CopyDirectory(info.absoluteFilePath(), dest_file_path, overwrite); - } else { - // Copy file - if (overwrite && QFile::exists(dest_file_path)) { - QFile file(dest_file_path); - file.setPermissions(file.permissions() | QFileDevice::WriteOwner | QFileDevice::WriteUser | - QFileDevice::WriteGroup | QFileDevice::WriteOther); - file.remove(); - } + if (info.isDir()) { + // Copy dir + CopyDirectory(info.absoluteFilePath(), dest_file_path, overwrite); + } else { + // Copy file + if (overwrite && QFile::exists(dest_file_path)) { + QFile file(dest_file_path); + file.setPermissions( + file.permissions() | QFileDevice::WriteOwner | + QFileDevice::WriteUser | QFileDevice::WriteGroup | + QFileDevice::WriteOther); + file.remove(); + } - QFile::copy(info.absoluteFilePath(), dest_file_path); - } - } + QFile::copy(info.absoluteFilePath(), dest_file_path); + } + } } -bool FileFunctions::DirectoryIsValid(const QDir &d, bool try_to_create_if_not_exists) +bool FileFunctions::DirectoryIsValid(const QDir &d, + bool try_to_create_if_not_exists) { - // Return whether the directory exists, or whether it could be created if it doesn't - return d.exists() || d.mkpath(QStringLiteral(".")); + // Return whether the directory exists, or whether it could be created if it doesn't + return d.exists() || d.mkpath(QStringLiteral(".")); } -QString FileFunctions::EnsureFilenameExtension(QString fn, const QString &extension) +QString FileFunctions::EnsureFilenameExtension(QString fn, + const QString &extension) { - // No-op if either input is empty - if (!fn.isEmpty() && !extension.isEmpty()) { - QString extension_with_dot; + // No-op if either input is empty + if (!fn.isEmpty() && !extension.isEmpty()) { + QString extension_with_dot; - extension_with_dot.append('.'); - extension_with_dot.append(extension); + extension_with_dot.append('.'); + extension_with_dot.append(extension); - if (!fn.endsWith(extension_with_dot, Qt::CaseInsensitive)) { - fn.append(extension_with_dot); - } - } + if (!fn.endsWith(extension_with_dot, Qt::CaseInsensitive)) { + fn.append(extension_with_dot); + } + } - return fn; + return fn; } QString FileFunctions::ReadFileAsString(const QString &filename) { - QFile f(filename); - QString file_data; - if (f.open(QFile::ReadOnly | QFile::Text)) { - QTextStream text_stream(&f); - file_data = text_stream.readAll(); - f.close(); - } - return file_data; + QFile f(filename); + QString file_data; + if (f.open(QFile::ReadOnly | QFile::Text)) { + QTextStream text_stream(&f); + file_data = text_stream.readAll(); + f.close(); + } + return file_data; } QString FileFunctions::GetSafeTemporaryFilename(const QString &original) { - int counter = 0; + int counter = 0; - QFileInfo original_info(original); - QString basename = original_info.baseName(); - QString complete_suffix = original_info.completeSuffix(); + QFileInfo original_info(original); + QString basename = original_info.baseName(); + QString complete_suffix = original_info.completeSuffix(); - // If we have a complete suffix, make sure there's a period in it - if (!complete_suffix.isEmpty()) { - complete_suffix.prepend('.'); - } + // If we have a complete suffix, make sure there's a period in it + if (!complete_suffix.isEmpty()) { + complete_suffix.prepend('.'); + } - QString temp_abs_path; - do { - temp_abs_path = original_info.dir().filePath( - QStringLiteral("%1.tmp%2%3").arg(basename, - QString::number(counter), - complete_suffix)); - counter++; - } while (QFileInfo::exists(temp_abs_path)); + QString temp_abs_path; + do { + temp_abs_path = original_info.dir().filePath( + QStringLiteral("%1.tmp%2%3") + .arg(basename, QString::number(counter), complete_suffix)); + counter++; + } while (QFileInfo::exists(temp_abs_path)); - return temp_abs_path; + return temp_abs_path; } -bool FileFunctions::RenameFileAllowOverwrite(const QString &from, const QString &to) +bool FileFunctions::RenameFileAllowOverwrite(const QString &from, + const QString &to) { - if (QFileInfo::exists(to) && !QFile::remove(to)) { - qCritical() << "Couldn't remove existing file" << to << "for overwrite"; - return false; - } + if (QFileInfo::exists(to) && !QFile::remove(to)) { + qCritical() << "Couldn't remove existing file" << to << "for overwrite"; + return false; + } - // By this point, we can assume `to` either never existed or has now been deleted - if (!QFile::rename(from, to)) { - qCritical() << "Failed to rename file" << from << "to" << to; - return false; - } + // By this point, we can assume `to` either never existed or has now been deleted + if (!QFile::rename(from, to)) { + qCritical() << "Failed to rename file" << from << "to" << to; + return false; + } - return true; + return true; } QString FileFunctions::GetAutoRecoveryRoot() { - return QDir(QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation)).filePath(QStringLiteral("autorecovery")); + return QDir(QStandardPaths::writableLocation( + QStandardPaths::AppLocalDataLocation)) + .filePath(QStringLiteral("autorecovery")); } } diff --git a/app/common/filefunctions.h b/app/common/filefunctions.h index f613fc001..c38629a10 100644 --- a/app/common/filefunctions.h +++ b/app/common/filefunctions.h @@ -26,36 +26,40 @@ #include "common/define.h" -namespace olive { +namespace olive +{ /** * @brief A collection of static file and directory functions */ class FileFunctions { public: - /** + /** * @brief Returns true if the application is running in portable mode * * In portable mode, any persistent configuration files should be made in a path relative to the application rather * than in the user's home folder. */ - static bool IsPortable(); + static bool IsPortable(); - static QString GetUniqueFileIdentifier(const QString& filename); + static QString GetUniqueFileIdentifier(const QString &filename); - static QString GetConfigurationLocation(); + static QString GetConfigurationLocation(); - static QString GetApplicationPath(); + static QString GetApplicationPath(); - static QString GetTempFilePath(); + static QString GetTempFilePath(); - static bool CanCopyDirectoryWithoutOverwriting(const QString& source, const QString& dest); + static bool CanCopyDirectoryWithoutOverwriting(const QString &source, + const QString &dest); - static void CopyDirectory(const QString& source, const QString& dest, bool overwrite = false); + static void CopyDirectory(const QString &source, const QString &dest, + bool overwrite = false); - static bool DirectoryIsValid(const QDir& dir, bool try_to_create_if_not_exists = true); + static bool DirectoryIsValid(const QDir &dir, + bool try_to_create_if_not_exists = true); - /** + /** * @brief Ensures a given filename has a certain extension * * Checks if the filename has the extension provided and appends it if not. The extension is @@ -64,11 +68,12 @@ public: * @return The filename provided either untouched or with the extension appended to it. */ - static QString EnsureFilenameExtension(QString fn, const QString& extension); + static QString EnsureFilenameExtension(QString fn, + const QString &extension); - static QString ReadFileAsString(const QString& filename); + static QString ReadFileAsString(const QString &filename); - /** + /** * @brief Returns a temporary filename that can be used while writing rather than the original * * If overwriting a file, it's safest to write to a new file first and then only replace it at @@ -78,28 +83,26 @@ public: * This function returns a slight variant of the filename provided that's guaranteed to not exist * and therefore won't overwrite anything important. */ - static QString GetSafeTemporaryFilename(const QString& original); + static QString GetSafeTemporaryFilename(const QString &original); - /** + /** * @brief Renames a file from `from` to `to`, deleting `to` if such a file already exists first */ - static bool RenameFileAllowOverwrite(const QString& from, const QString& to); + static bool RenameFileAllowOverwrite(const QString &from, + const QString &to); - inline static QString GetFormattedExecutableForPlatform(QString unformatted) - { + inline static QString GetFormattedExecutableForPlatform(QString unformatted) + { #ifdef Q_OS_WINDOWS - unformatted.append(QStringLiteral(".exe")); + unformatted.append(QStringLiteral(".exe")); #endif - return unformatted; - } - - static QString GetAutoRecoveryRoot(); + return unformatted; + } + static QString GetAutoRecoveryRoot(); }; - - } #endif // FILEFUNCTIONS_H diff --git a/app/common/html.cpp b/app/common/html.cpp index 74cc805f9..8ebe4ea2e 100644 --- a/app/common/html.cpp +++ b/app/common/html.cpp @@ -5,446 +5,472 @@ #include "xmlutils.h" -namespace olive { +namespace olive +{ -const QVector Html::kBlockTags = { - QStringLiteral("p"), - QStringLiteral("div") -}; +const QVector Html::kBlockTags = { QStringLiteral("p"), + QStringLiteral("div") }; inline bool StrEquals(const QStringView &a, const QStringView &b) { - return !a.compare(b, Qt::CaseInsensitive); + return !a.compare(b, Qt::CaseInsensitive); } QString Html::DocToHtml(const QTextDocument *doc) { - QString html; - QXmlStreamWriter writer(&html); + QString html; + QXmlStreamWriter writer(&html); - //writer.setAutoFormatting(true); + //writer.setAutoFormatting(true); - for (auto it=doc->begin(); it!=doc->end(); it=it.next()) { - WriteBlock(&writer, it); - } + for (auto it = doc->begin(); it != doc->end(); it = it.next()) { + WriteBlock(&writer, it); + } - return html; + return html; } struct HtmlNode { - QString tag; - QTextCharFormat format; + QString tag; + QTextCharFormat format; }; QTextCharFormat MergeHtmlFormats(const QVector &stack) { - QTextCharFormat f; + QTextCharFormat f; - for (int i=0; iclear(); - bool inside_block = true; + // Empty doc + doc->clear(); + bool inside_block = true; - // Create cursor, which appears to be Qt's official way of inserting blocks and fragments - QTextCursor c(doc); + // Create cursor, which appears to be Qt's official way of inserting blocks and fragments + QTextCursor c(doc); - QString wrapped = QStringLiteral("").append(html).append(""); - QXmlStreamReader reader(wrapped); + QString wrapped = QStringLiteral("").append(html).append(""); + QXmlStreamReader reader(wrapped); - QVector fmt_stack; + QVector fmt_stack; - QTextCharFormat default_fmt; - default_fmt.setFontWeight(QFont::Normal); - fmt_stack.append({QStringLiteral("html"), default_fmt}); + QTextCharFormat default_fmt; + default_fmt.setFontWeight(QFont::Normal); + fmt_stack.append({ QStringLiteral("html"), default_fmt }); - QTextCharFormat current_fmt; + QTextCharFormat current_fmt; - while (!reader.atEnd()) { - reader.readNext(); + while (!reader.atEnd()) { + reader.readNext(); - if (reader.tokenType() == QXmlStreamReader::StartElement) { + if (reader.tokenType() == QXmlStreamReader::StartElement) { + QString tag = reader.name().toString().toLower(); - QString tag = reader.name().toString().toLower(); + fmt_stack.append({ tag, ReadCharFormat(reader.attributes()) }); + current_fmt = MergeHtmlFormats(fmt_stack); - fmt_stack.append({tag, ReadCharFormat(reader.attributes())}); - current_fmt = MergeHtmlFormats(fmt_stack); + if (kBlockTags.contains(tag)) { + QTextBlockFormat block_fmt = + ReadBlockFormat(reader.attributes()); + if (inside_block) { + c.setBlockFormat(block_fmt); + c.setBlockCharFormat(current_fmt); + } else { + c.insertBlock(block_fmt, current_fmt); + inside_block = true; + } + } - if (kBlockTags.contains(tag)) { - QTextBlockFormat block_fmt = ReadBlockFormat(reader.attributes()); - if (inside_block) { - c.setBlockFormat(block_fmt); - c.setBlockCharFormat(current_fmt); - } else { - c.insertBlock(block_fmt, current_fmt); - inside_block = true; - } - } + } else if (reader.tokenType() == QXmlStreamReader::Characters) { + QString characters = reader.text().toString(); + c.insertText(characters, current_fmt); - } else if (reader.tokenType() == QXmlStreamReader::Characters) { + } else if (reader.tokenType() == QXmlStreamReader::EndElement) { + QString tag = reader.name().toString().toLower(); - QString characters = reader.text().toString(); - c.insertText(characters, current_fmt); + for (int i = fmt_stack.size() - 1; i >= 0; i--) { + if (fmt_stack.at(i).tag == tag) { + fmt_stack.removeAt(i); + current_fmt = MergeHtmlFormats(fmt_stack); - } else if (reader.tokenType() == QXmlStreamReader::EndElement) { + if (kBlockTags.contains(tag)) { + inside_block = false; + } + break; + } + } + } + } - QString tag = reader.name().toString().toLower(); - - for (int i=fmt_stack.size()-1; i>=0; i--) { - if (fmt_stack.at(i).tag == tag) { - fmt_stack.removeAt(i); - current_fmt = MergeHtmlFormats(fmt_stack); - - if (kBlockTags.contains(tag)) { - inside_block = false; - } - break; - } - } - - } - } - - if (reader.error()) { - qCritical() << "Failed to parse HTML:" << reader.errorString(); - } + if (reader.error()) { + qCritical() << "Failed to parse HTML:" << reader.errorString(); + } } void Html::WriteBlock(QXmlStreamWriter *writer, const QTextBlock &block) { - writer->writeStartElement(QStringLiteral("p")); + writer->writeStartElement(QStringLiteral("p")); - const QTextBlockFormat &fmt = block.blockFormat(); + const QTextBlockFormat &fmt = block.blockFormat(); - // Write block alignment - if (!(fmt.alignment() & Qt::AlignLeft)) { - if (fmt.alignment() & Qt::AlignRight) { - writer->writeAttribute(QStringLiteral("align"), QStringLiteral("right")); - } else if (fmt.alignment() & Qt::AlignHCenter) { - writer->writeAttribute(QStringLiteral("align"), QStringLiteral("center")); - } else if (fmt.alignment() & Qt::AlignJustify) { - writer->writeAttribute(QStringLiteral("align"), QStringLiteral("justify")); - } - } + // Write block alignment + if (!(fmt.alignment() & Qt::AlignLeft)) { + if (fmt.alignment() & Qt::AlignRight) { + writer->writeAttribute(QStringLiteral("align"), + QStringLiteral("right")); + } else if (fmt.alignment() & Qt::AlignHCenter) { + writer->writeAttribute(QStringLiteral("align"), + QStringLiteral("center")); + } else if (fmt.alignment() & Qt::AlignJustify) { + writer->writeAttribute(QStringLiteral("align"), + QStringLiteral("justify")); + } + } - // RTL support - if (block.textDirection() == Qt::RightToLeft) { - writer->writeAttribute(QStringLiteral("dir"), QStringLiteral("rtl")); - } + // RTL support + if (block.textDirection() == Qt::RightToLeft) { + writer->writeAttribute(QStringLiteral("dir"), QStringLiteral("rtl")); + } - // Write CSS attributes - QString style; + // Write CSS attributes + QString style; - if (fmt.lineHeightType() != QTextBlockFormat::SingleHeight) { - WriteCSSProperty(&style, QStringLiteral("line-height"), QStringLiteral("%1%").arg(fmt.lineHeight())); - } + if (fmt.lineHeightType() != QTextBlockFormat::SingleHeight) { + WriteCSSProperty(&style, QStringLiteral("line-height"), + QStringLiteral("%1%").arg(fmt.lineHeight())); + } - WriteCharFormat(&style, block.charFormat()); + WriteCharFormat(&style, block.charFormat()); - if (!style.isEmpty()) { - writer->writeAttribute(QStringLiteral("style"), style); - } + if (!style.isEmpty()) { + writer->writeAttribute(QStringLiteral("style"), style); + } - auto it = block.begin(); + auto it = block.begin(); - if (it != block.end()) { - for (; it!=block.end(); it++) { - WriteFragment(writer, it.fragment()); - } - } + if (it != block.end()) { + for (; it != block.end(); it++) { + WriteFragment(writer, it.fragment()); + } + } - writer->writeEndElement(); // p + writer->writeEndElement(); // p } -void Html::WriteFragment(QXmlStreamWriter *writer, const QTextFragment &fragment) +void Html::WriteFragment(QXmlStreamWriter *writer, + const QTextFragment &fragment) { - const QTextCharFormat &fmt = fragment.charFormat(); + const QTextCharFormat &fmt = fragment.charFormat(); - writer->writeStartElement(QStringLiteral("span")); + writer->writeStartElement(QStringLiteral("span")); - // Write CSS attributes - QString style; + // Write CSS attributes + QString style; - WriteCharFormat(&style, fmt); + WriteCharFormat(&style, fmt); - if (!style.isEmpty()) { - writer->writeAttribute(QStringLiteral("style"), style); - } + if (!style.isEmpty()) { + writer->writeAttribute(QStringLiteral("style"), style); + } - QStringList lines = fragment.text().split(QChar::LineSeparator); - bool first_line = true; - foreach (const QString &l, lines) { - if (first_line) { - first_line = false; - } else { - writer->writeEmptyElement(QStringLiteral("br")); - } - writer->writeCharacters(l); - } + QStringList lines = fragment.text().split(QChar::LineSeparator); + bool first_line = true; + foreach (const QString &l, lines) { + if (first_line) { + first_line = false; + } else { + writer->writeEmptyElement(QStringLiteral("br")); + } + writer->writeCharacters(l); + } - writer->writeEndElement(); // span + writer->writeEndElement(); // span } -void Html::WriteCSSProperty(QString *style, const QString &key, const QStringList &values) +void Html::WriteCSSProperty(QString *style, const QString &key, + const QStringList &values) { - QString value; - foreach (QString v, values) { - if (v.contains(' ')) { - v = QStringLiteral("'%1'").arg(v); - } + QString value; + foreach (QString v, values) { + if (v.contains(' ')) { + v = QStringLiteral("'%1'").arg(v); + } - AppendStringAutoSpace(&value, v); - } + AppendStringAutoSpace(&value, v); + } - AppendStringAutoSpace(style, QStringLiteral("%1: %2;").arg(key, value)); + AppendStringAutoSpace(style, QStringLiteral("%1: %2;").arg(key, value)); } void Html::WriteCharFormat(QString *style, const QTextCharFormat &fmt) { - QStringList families = fmt.fontFamilies().toStringList(); - if (!families.isEmpty()) { - WriteCSSProperty(style, QStringLiteral("font-family"), families.first()); - } + QStringList families = fmt.fontFamilies().toStringList(); + if (!families.isEmpty()) { + WriteCSSProperty(style, QStringLiteral("font-family"), + families.first()); + } - if (fmt.hasProperty(QTextFormat::FontPointSize)) { - WriteCSSProperty(style, QStringLiteral("font-size"), QStringLiteral("%1pt").arg(QString::number(fmt.fontPointSize()))); - } + if (fmt.hasProperty(QTextFormat::FontPointSize)) { + WriteCSSProperty( + style, QStringLiteral("font-size"), + QStringLiteral("%1pt").arg(QString::number(fmt.fontPointSize()))); + } - if (fmt.hasProperty(QTextFormat::FontWeight)) { - WriteCSSProperty(style, QStringLiteral("font-weight"), QString::number(fmt.fontWeight() * 8)); - } + if (fmt.hasProperty(QTextFormat::FontWeight)) { + WriteCSSProperty(style, QStringLiteral("font-weight"), + QString::number(fmt.fontWeight() * 8)); + } - if (fmt.hasProperty(QTextFormat::FontItalic)) { - WriteCSSProperty(style, QStringLiteral("font-style"), fmt.fontItalic() ? QStringLiteral("italic") : QStringLiteral("normal")); - } + if (fmt.hasProperty(QTextFormat::FontItalic)) { + WriteCSSProperty(style, QStringLiteral("font-style"), + fmt.fontItalic() ? QStringLiteral("italic") : + QStringLiteral("normal")); + } - if (fmt.hasProperty(QTextFormat::FontStyleName)) { - WriteCSSProperty(style, QStringLiteral("-ove-font-style"), fmt.fontStyleName().toString()); - } + if (fmt.hasProperty(QTextFormat::FontStyleName)) { + WriteCSSProperty(style, QStringLiteral("-ove-font-style"), + fmt.fontStyleName().toString()); + } - QStringList deco; + QStringList deco; - if (fmt.fontUnderline()) { - deco.append(QStringLiteral("underline")); - } + if (fmt.fontUnderline()) { + deco.append(QStringLiteral("underline")); + } - if (fmt.fontStrikeOut()) { - deco.append(QStringLiteral("line-through")); - } + if (fmt.fontStrikeOut()) { + deco.append(QStringLiteral("line-through")); + } - if (fmt.fontOverline()) { - deco.append(QStringLiteral("overline")); - } + if (fmt.fontOverline()) { + deco.append(QStringLiteral("overline")); + } - if (!deco.isEmpty()) { - WriteCSSProperty(style, QStringLiteral("text-decoration"), deco); - } + if (!deco.isEmpty()) { + WriteCSSProperty(style, QStringLiteral("text-decoration"), deco); + } - if (fmt.foreground().style() != Qt::NoBrush) { - const QColor &color = fmt.foreground().color(); - QString cs; + if (fmt.foreground().style() != Qt::NoBrush) { + const QColor &color = fmt.foreground().color(); + QString cs; - if (color.alpha() == 255) { - cs = color.name(); - } else if (color.alpha()) { - cs = QStringLiteral("rgba(%1, %2, %3, %4)").arg(QString::number(color.red()), QString::number(color.green()), QString::number(color.blue()), QString::number(color.alphaF())); - } + if (color.alpha() == 255) { + cs = color.name(); + } else if (color.alpha()) { + cs = QStringLiteral("rgba(%1, %2, %3, %4)") + .arg(QString::number(color.red()), + QString::number(color.green()), + QString::number(color.blue()), + QString::number(color.alphaF())); + } - WriteCSSProperty(style, QStringLiteral("color"), cs); - } + WriteCSSProperty(style, QStringLiteral("color"), cs); + } - if (fmt.fontCapitalization() != QFont::MixedCase) { - if (fmt.fontCapitalization() == QFont::SmallCaps) { - WriteCSSProperty(style, QStringLiteral("font-variant"), QStringLiteral("small-caps")); - // TODO: Add others - } - } + if (fmt.fontCapitalization() != QFont::MixedCase) { + if (fmt.fontCapitalization() == QFont::SmallCaps) { + WriteCSSProperty(style, QStringLiteral("font-variant"), + QStringLiteral("small-caps")); + // TODO: Add others + } + } - if (fmt.fontLetterSpacing() != 0.0) { - WriteCSSProperty(style, QStringLiteral("letter-spacing"), QStringLiteral("%1%").arg(QString::number(fmt.fontLetterSpacing()))); - } + if (fmt.fontLetterSpacing() != 0.0) { + WriteCSSProperty(style, QStringLiteral("letter-spacing"), + QStringLiteral("%1%").arg( + QString::number(fmt.fontLetterSpacing()))); + } - if (fmt.fontStretch() != 0) { - WriteCSSProperty(style, QStringLiteral("font-stretch"), QStringLiteral("%1%").arg(QString::number(fmt.fontStretch()))); - } + if (fmt.fontStretch() != 0) { + WriteCSSProperty( + style, QStringLiteral("font-stretch"), + QStringLiteral("%1%").arg(QString::number(fmt.fontStretch()))); + } } QTextCharFormat Html::ReadCharFormat(const QXmlStreamAttributes &attributes) { - QTextCharFormat fmt; + QTextCharFormat fmt; - foreach (const QXmlStreamAttribute &attr, attributes) { - if (StrEquals(attr.name(), QStringLiteral("style"))) { - auto css = GetCSSFromStyle(attr.value().toString()); + foreach (const QXmlStreamAttribute &attr, attributes) { + if (StrEquals(attr.name(), QStringLiteral("style"))) { + auto css = GetCSSFromStyle(attr.value().toString()); - for (auto it=css.begin(); it!=css.end(); it++) { - const QString &first_val = it.value().first(); + for (auto it = css.begin(); it != css.end(); it++) { + const QString &first_val = it.value().first(); - if (it.key() == QStringLiteral("font-family")) { - fmt.setFontFamilies({first_val}); - } else if (it.key() == QStringLiteral("font-size")) { - if (first_val.endsWith(QStringLiteral("pt"), Qt::CaseInsensitive)) { - fmt.setFontPointSize(first_val.chopped(2).toDouble()); - } - } else if (it.key() == QStringLiteral("font-weight")) { - fmt.setFontWeight(first_val.toInt()/8); - } else if (it.key() == QStringLiteral("font-style")) { - fmt.setFontItalic(StrEquals(first_val, QStringLiteral("italic"))); - } else if (it.key() == QStringLiteral("text-decoration")) { - foreach (const QString &v, it.value()) { - if (StrEquals(v, QStringLiteral("underline"))) { - fmt.setFontUnderline(true); - } else if (StrEquals(v, QStringLiteral("line-through"))) { - fmt.setFontStrikeOut(true); - } else if (StrEquals(v, QStringLiteral("overline"))) { - fmt.setFontOverline(true); - } - } - } else if (it.key() == QStringLiteral("color")) { - if (first_val.startsWith(QStringLiteral("rgba"), Qt::CaseInsensitive)) { - QString vals_only = first_val; - vals_only.remove(QStringLiteral("rgba")); - vals_only.remove(QStringLiteral("(")); - vals_only.remove(QStringLiteral(")")); - QStringList rgba = vals_only.split(','); - if (rgba.size() == 4) { - QColor c; - c.setRedF(rgba.at(0).toDouble()); - c.setGreenF(rgba.at(1).toDouble()); - c.setBlueF(rgba.at(2).toDouble()); - c.setAlphaF(rgba.at(3).toDouble()); - fmt.setForeground(c); - } - } else { - fmt.setForeground(QColor(first_val)); - } - } else if (it.key() == QStringLiteral("font-variant")) { - if (StrEquals(first_val, QStringLiteral("small-caps"))) { - fmt.setFontCapitalization(QFont::SmallCaps); - } - } else if (it.key() == QStringLiteral("letter-spacing")) { - if (first_val.contains(QChar('%'))) { - fmt.setFontLetterSpacing(first_val.chopped(1).toDouble()); - } - } else if (it.key() == QStringLiteral("font-stretch")) { - if (first_val.contains(QChar('%'))) { - fmt.setFontStretch(first_val.chopped(1).toInt()); - } - } else if (it.key() == QStringLiteral("-ove-font-style")) { - fmt.setFontStyleName(first_val); - } - } - } - } - return fmt; + if (it.key() == QStringLiteral("font-family")) { + fmt.setFontFamilies({ first_val }); + } else if (it.key() == QStringLiteral("font-size")) { + if (first_val.endsWith(QStringLiteral("pt"), + Qt::CaseInsensitive)) { + fmt.setFontPointSize(first_val.chopped(2).toDouble()); + } + } else if (it.key() == QStringLiteral("font-weight")) { + fmt.setFontWeight(first_val.toInt() / 8); + } else if (it.key() == QStringLiteral("font-style")) { + fmt.setFontItalic( + StrEquals(first_val, QStringLiteral("italic"))); + } else if (it.key() == QStringLiteral("text-decoration")) { + foreach (const QString &v, it.value()) { + if (StrEquals(v, QStringLiteral("underline"))) { + fmt.setFontUnderline(true); + } else if (StrEquals(v, + QStringLiteral("line-through"))) { + fmt.setFontStrikeOut(true); + } else if (StrEquals(v, QStringLiteral("overline"))) { + fmt.setFontOverline(true); + } + } + } else if (it.key() == QStringLiteral("color")) { + if (first_val.startsWith(QStringLiteral("rgba"), + Qt::CaseInsensitive)) { + QString vals_only = first_val; + vals_only.remove(QStringLiteral("rgba")); + vals_only.remove(QStringLiteral("(")); + vals_only.remove(QStringLiteral(")")); + QStringList rgba = vals_only.split(','); + if (rgba.size() == 4) { + QColor c; + c.setRedF(rgba.at(0).toDouble()); + c.setGreenF(rgba.at(1).toDouble()); + c.setBlueF(rgba.at(2).toDouble()); + c.setAlphaF(rgba.at(3).toDouble()); + fmt.setForeground(c); + } + } else { + fmt.setForeground(QColor(first_val)); + } + } else if (it.key() == QStringLiteral("font-variant")) { + if (StrEquals(first_val, QStringLiteral("small-caps"))) { + fmt.setFontCapitalization(QFont::SmallCaps); + } + } else if (it.key() == QStringLiteral("letter-spacing")) { + if (first_val.contains(QChar('%'))) { + fmt.setFontLetterSpacing( + first_val.chopped(1).toDouble()); + } + } else if (it.key() == QStringLiteral("font-stretch")) { + if (first_val.contains(QChar('%'))) { + fmt.setFontStretch(first_val.chopped(1).toInt()); + } + } else if (it.key() == QStringLiteral("-ove-font-style")) { + fmt.setFontStyleName(first_val); + } + } + } + } + return fmt; } QTextBlockFormat Html::ReadBlockFormat(const QXmlStreamAttributes &attributes) { - QTextBlockFormat block_fmt; + QTextBlockFormat block_fmt; - foreach (const QXmlStreamAttribute &attr, attributes) { - if (StrEquals(attr.name(), QStringLiteral("align"))) { - if (StrEquals(attr.value(), QStringLiteral("right"))) { - block_fmt.setAlignment(Qt::AlignRight); - } else if (StrEquals(attr.value(), QStringLiteral("center"))) { - block_fmt.setAlignment(Qt::AlignHCenter); - } else if (StrEquals(attr.value(), QStringLiteral("justify"))) { - block_fmt.setAlignment(Qt::AlignJustify); - } - } else if (StrEquals(attr.name(), QStringLiteral("dir"))) { - if (StrEquals(attr.value(), QStringLiteral("rtl"))) { - block_fmt.setLayoutDirection(Qt::RightToLeft); - } - } else if (StrEquals(attr.name(), QStringLiteral("style"))) { - auto css = GetCSSFromStyle(attr.value().toString()); + foreach (const QXmlStreamAttribute &attr, attributes) { + if (StrEquals(attr.name(), QStringLiteral("align"))) { + if (StrEquals(attr.value(), QStringLiteral("right"))) { + block_fmt.setAlignment(Qt::AlignRight); + } else if (StrEquals(attr.value(), QStringLiteral("center"))) { + block_fmt.setAlignment(Qt::AlignHCenter); + } else if (StrEquals(attr.value(), QStringLiteral("justify"))) { + block_fmt.setAlignment(Qt::AlignJustify); + } + } else if (StrEquals(attr.name(), QStringLiteral("dir"))) { + if (StrEquals(attr.value(), QStringLiteral("rtl"))) { + block_fmt.setLayoutDirection(Qt::RightToLeft); + } + } else if (StrEquals(attr.name(), QStringLiteral("style"))) { + auto css = GetCSSFromStyle(attr.value().toString()); - for (auto it=css.begin(); it!=css.end(); it++) { - if (it.key() == QStringLiteral("line-height")) { - const QString &first_val = it.value().constFirst(); - if (first_val.contains(QChar('%'))) { - block_fmt.setLineHeight(first_val.chopped(1).toDouble(), QTextBlockFormat::ProportionalHeight); - } - } - } - } - } + for (auto it = css.begin(); it != css.end(); it++) { + if (it.key() == QStringLiteral("line-height")) { + const QString &first_val = it.value().constFirst(); + if (first_val.contains(QChar('%'))) { + block_fmt.setLineHeight( + first_val.chopped(1).toDouble(), + QTextBlockFormat::ProportionalHeight); + } + } + } + } + } - return block_fmt; + return block_fmt; } void Html::AppendStringAutoSpace(QString *s, const QString &append) { - if (!s->isEmpty()) { - s->append(QChar(' ')); - } + if (!s->isEmpty()) { + s->append(QChar(' ')); + } - s->append(append); + s->append(append); } QMap Html::GetCSSFromStyle(const QString &s) { - QMap map; + QMap map; - QStringList list = s.split(QChar(';')); + QStringList list = s.split(QChar(';')); - foreach (const QString &a, list) { - QStringList kv = a.split(QChar(':')); + foreach (const QString &a, list) { + QStringList kv = a.split(QChar(':')); - if (kv.size() != 2) { - continue; - } + if (kv.size() != 2) { + continue; + } - // I'm sure there's regex that could do this, but I couldn't figure it out. It needs to split - // by space EXCEPT within quotes OR double-quotes, and said quotes should be EXCLUDED from each - // match. Also commas should be filtered out. - QStringList values; - const QString &val = kv.at(1); - QChar in_quote(0); - QString current_str; - for (int i=0; i #include -namespace olive { +namespace olive +{ /** * @brief Functions for converting HTML to QTextDocument and vice versa @@ -26,33 +27,37 @@ namespace olive { */ class Html { public: - static QString DocToHtml(const QTextDocument *doc); + static QString DocToHtml(const QTextDocument *doc); - static void HtmlToDoc(QTextDocument *doc, const QString &html); + static void HtmlToDoc(QTextDocument *doc, const QString &html); private: - static void WriteBlock(QXmlStreamWriter *writer, const QTextBlock &block); + static void WriteBlock(QXmlStreamWriter *writer, const QTextBlock &block); - static void WriteFragment(QXmlStreamWriter *writer, const QTextFragment &fragment); + static void WriteFragment(QXmlStreamWriter *writer, + const QTextFragment &fragment); - static void WriteCSSProperty(QString *style, const QString &key, const QStringList &value); - static void WriteCSSProperty(QString *style, const QString &key, const QString &value) - { - WriteCSSProperty(style, key, QStringList({value})); - } + static void WriteCSSProperty(QString *style, const QString &key, + const QStringList &value); + static void WriteCSSProperty(QString *style, const QString &key, + const QString &value) + { + WriteCSSProperty(style, key, QStringList({ value })); + } - static void WriteCharFormat(QString *style, const QTextCharFormat &fmt); + static void WriteCharFormat(QString *style, const QTextCharFormat &fmt); - static QTextCharFormat ReadCharFormat(const QXmlStreamAttributes &attributes); + static QTextCharFormat + ReadCharFormat(const QXmlStreamAttributes &attributes); - static QTextBlockFormat ReadBlockFormat(const QXmlStreamAttributes &attributes); + static QTextBlockFormat + ReadBlockFormat(const QXmlStreamAttributes &attributes); - static void AppendStringAutoSpace(QString *s, const QString &append); + static void AppendStringAutoSpace(QString *s, const QString &append); - static QMap GetCSSFromStyle(const QString &s); - - static const QVector kBlockTags; + static QMap GetCSSFromStyle(const QString &s); + static const QVector kBlockTags; }; } diff --git a/app/common/jobtime.cpp b/app/common/jobtime.cpp index 43077ebf1..1ad873c0c 100644 --- a/app/common/jobtime.cpp +++ b/app/common/jobtime.cpp @@ -2,29 +2,30 @@ #include -namespace olive { +namespace olive +{ uint64_t job_time_index = 0; QMutex job_time_mutex; JobTime::JobTime() { - Acquire(); + Acquire(); } void JobTime::Acquire() { - job_time_mutex.lock(); + job_time_mutex.lock(); - value_ = job_time_index; - job_time_index++; + value_ = job_time_index; + job_time_index++; - job_time_mutex.unlock(); + job_time_mutex.unlock(); } } -QDebug operator<<(QDebug debug, const olive::JobTime& r) +QDebug operator<<(QDebug debug, const olive::JobTime &r) { - return debug.space() << r.value(); + return debug.space() << r.value(); } diff --git a/app/common/jobtime.h b/app/common/jobtime.h index 27988b92e..e2334bf79 100644 --- a/app/common/jobtime.h +++ b/app/common/jobtime.h @@ -4,58 +4,57 @@ #include #include -namespace olive { - -class JobTime +namespace olive { + +class JobTime { public: - JobTime(); + JobTime(); - void Acquire(); + void Acquire(); - uint64_t value() const - { - return value_; - } + uint64_t value() const + { + return value_; + } - bool operator==(const JobTime &rhs) const - { - return value_ == rhs.value_; - } + bool operator==(const JobTime &rhs) const + { + return value_ == rhs.value_; + } - bool operator!=(const JobTime &rhs) const - { - return value_ != rhs.value_; - } + bool operator!=(const JobTime &rhs) const + { + return value_ != rhs.value_; + } - bool operator<(const JobTime &rhs) const - { - return value_ < rhs.value_; - } + bool operator<(const JobTime &rhs) const + { + return value_ < rhs.value_; + } - bool operator>(const JobTime &rhs) const - { - return value_ > rhs.value_; - } + bool operator>(const JobTime &rhs) const + { + return value_ > rhs.value_; + } - bool operator<=(const JobTime &rhs) const - { - return value_ <= rhs.value_; - } + bool operator<=(const JobTime &rhs) const + { + return value_ <= rhs.value_; + } - bool operator>=(const JobTime &rhs) const - { - return value_ >= rhs.value_; - } + bool operator>=(const JobTime &rhs) const + { + return value_ >= rhs.value_; + } private: - uint64_t value_; - + uint64_t value_; }; } -QDebug operator<<(QDebug debug, const olive::JobTime& r); +QDebug operator<<(QDebug debug, const olive::JobTime &r); Q_DECLARE_METATYPE(olive::JobTime) diff --git a/app/common/lerp.h b/app/common/lerp.h index dbed7f498..848bc8b48 100644 --- a/app/common/lerp.h +++ b/app/common/lerp.h @@ -21,20 +21,21 @@ #ifndef LERP_H #define LERP_H -template +template /** * @brief Linearly interpolate a value between a and b using t * * t should be a number between 0.0 and 1.0. 0.0 will return a, 1.0 will return b, and between will return a value * in between a and b at that point linearly. */ -T lerp(T a, T b, double t) { - return (a * (1.0 - t)) + (b * t); +T lerp(T a, T b, double t) +{ + return (a * (1.0 - t)) + (b * t); } -template -T lerp(T a, T b, float t) { - return (a * (1.0f - t)) + (b * t); +template T lerp(T a, T b, float t) +{ + return (a * (1.0f - t)) + (b * t); } #endif // LERP_H diff --git a/app/common/memorypool.h b/app/common/memorypool.h index 270e3a0a0..dbcc3531c 100644 --- a/app/common/memorypool.h +++ b/app/common/memorypool.h @@ -31,7 +31,8 @@ #include "common/define.h" -namespace olive { +namespace olive +{ /** * @brief MemoryPool base class @@ -46,386 +47,389 @@ namespace olive { * `Get()` will return an ElementPtr. The original desired data can be accessed through ElementPtr::data(). This data * will belong to the caller until ElementPtr goes out of scope and the memory is freed back into the pool. */ -class MemoryPool : public QObject -{ - Q_OBJECT +class MemoryPool : public QObject { + Q_OBJECT public: - /** + /** * @brief Constructor * @param element_count * * Number of elements per arena */ - MemoryPool(int element_count) - { - element_count_ = element_count; + MemoryPool(int element_count) + { + element_count_ = element_count; - clear_timer_ = new QTimer(); - clear_timer_->setInterval(kMaxEmptyArenaLife); - clear_timer_->moveToThread(qApp->thread()); - connect(clear_timer_, &QTimer::timeout, this, &MemoryPool::ClearEmptyArenas, Qt::DirectConnection); - QMetaObject::invokeMethod(clear_timer_, "start", Qt::QueuedConnection); - } + clear_timer_ = new QTimer(); + clear_timer_->setInterval(kMaxEmptyArenaLife); + clear_timer_->moveToThread(qApp->thread()); + connect(clear_timer_, &QTimer::timeout, this, + &MemoryPool::ClearEmptyArenas, Qt::DirectConnection); + QMetaObject::invokeMethod(clear_timer_, "start", Qt::QueuedConnection); + } - /** + /** * @brief Destructor * * Deletes all arenas. */ - virtual ~MemoryPool() - { - Clear(); - clear_timer_->deleteLater(); - } + virtual ~MemoryPool() + { + Clear(); + clear_timer_->deleteLater(); + } - DISABLE_COPY_MOVE(MemoryPool) + DISABLE_COPY_MOVE(MemoryPool) - /** + /** * @brief Clears all arenas, freeing all of their memory * * Note that this function is not safe, any elements that are still out there will be invalid * and accessing them will cause a crash. You'll need to make sure all elements are already * relinquished before then. */ - void Clear() - { - qDeleteAll(arenas_); - arenas_.clear(); - } + void Clear() + { + qDeleteAll(arenas_); + arenas_.clear(); + } - /** + /** * @brief Returns whether any arenas are successfully allocated */ - inline bool IsAllocated() const - { - return !arenas_.empty(); - } + inline bool IsAllocated() const + { + return !arenas_.empty(); + } - /** + /** * @brief Returns current number of allocated arenas */ - inline int GetArenaCount() const - { - return arenas_.size(); - } + inline int GetArenaCount() const + { + return arenas_.size(); + } - class Arena; + class Arena; - /** + /** * @brief A handle for a chunk of memory in an arena * * Calling Get() on the pool or arena will return a shared pointer to an element which will contain a pointer to * the desired object/data in data(). When Element is destroyed (i.e. when ElementPtr goes out of scope), the memory * is released back into the pool so it can be used by another class. */ - class Element { - public: - /** + class Element { + public: + /** * @brief Element Constructor * * There is no need to use this outside of the memory pool's internal functions. */ - Element(Arena* parent, uint8_t* data) - { - parent_ = parent; - data_ = data; - accessed_ = QDateTime::currentMSecsSinceEpoch(); - } + Element(Arena *parent, uint8_t *data) + { + parent_ = parent; + data_ = data; + accessed_ = QDateTime::currentMSecsSinceEpoch(); + } - /** + /** * @brief Element Destructor * * Automatically releases this element's memory back to the arena it was retrieved from. */ - ~Element() - { - release(); - } + ~Element() + { + release(); + } - DISABLE_COPY_MOVE(Element) + DISABLE_COPY_MOVE(Element) - /** + /** * @brief Access data represented in the pool */ - inline uint8_t* data() const - { - return data_; - } + inline uint8_t *data() const + { + return data_; + } - inline const int64_t& timestamp() const - { - return timestamp_; - } + inline const int64_t ×tamp() const + { + return timestamp_; + } - inline void set_timestamp(const int64_t& timestamp) - { - timestamp_ = timestamp; - } + inline void set_timestamp(const int64_t ×tamp) + { + timestamp_ = timestamp; + } - /** + /** * @brief Register that this element has been accessed * * \see last_accessed() */ - inline void access() - { - accessed_ = QDateTime::currentMSecsSinceEpoch(); - } + inline void access() + { + accessed_ = QDateTime::currentMSecsSinceEpoch(); + } - /** + /** * @brief Returns the last time `access()` was called on this function * * Useful for determining the relative age of an element (i.e. if it hasn't been accessed for a certain amount of * time, it can probably be freed back into the pool). This requires all usages to call `access()`. */ - inline const int64_t& last_accessed() const - { - return accessed_; - } + inline const int64_t &last_accessed() const + { + return accessed_; + } - void release() - { - if (data_) { - parent_->Release(this); - data_ = nullptr; - } - } + void release() + { + if (data_) { + parent_->Release(this); + data_ = nullptr; + } + } - private: - Arena* parent_; + private: + Arena *parent_; - uint8_t* data_; + uint8_t *data_; - int64_t timestamp_; + int64_t timestamp_; - int64_t accessed_; + int64_t accessed_; + }; - }; + using ElementPtr = std::shared_ptr; - using ElementPtr = std::shared_ptr; - - /** + /** * @brief A memory pool arena - a subsection of memory * * The pool itself does not store memory, it stores "arenas". This is so that the pool can handle the situation of * an arena becoming full with no more memory to lend. A pool can automatically allocate another arena and continue * providing memory (and freeing arenas when they're no longer in use). */ - class Arena { - public: - Arena(MemoryPool* parent) - { - parent_ = parent; - data_ = nullptr; - allocated_sz_ = 0; - empty_time_ = QDateTime::currentMSecsSinceEpoch(); - } + class Arena { + public: + Arena(MemoryPool *parent) + { + parent_ = parent; + data_ = nullptr; + allocated_sz_ = 0; + empty_time_ = QDateTime::currentMSecsSinceEpoch(); + } - ~Arena() - { - std::list copy = lent_elements_; - foreach (Element* e, copy) { - e->release(); - } + ~Arena() + { + std::list copy = lent_elements_; + foreach (Element *e, copy) { + e->release(); + } - delete [] data_; - } + delete[] data_; + } - DISABLE_COPY_MOVE(Arena) + DISABLE_COPY_MOVE(Arena) - /** + /** * @brief Returns an element if there is free memory to do so */ - ElementPtr Get() - { - QMutexLocker locker(&lock_); + ElementPtr Get() + { + QMutexLocker locker(&lock_); - for (int i=0;i(this, - reinterpret_cast(data_ + i * element_sz_)); - lent_elements_.push_back(e.get()); + ElementPtr e = std::make_shared( + this, + reinterpret_cast(data_ + i * element_sz_)); + lent_elements_.push_back(e.get()); - return e; - } - } + return e; + } + } - return nullptr; - } + return nullptr; + } - /** + /** * @brief Releases an element back into the pool for use elsewhere */ - void Release(Element* e) - { - QMutexLocker locker(&lock_); - quintptr diff = reinterpret_cast(e->data()) - reinterpret_cast(data_); + void Release(Element *e) + { + QMutexLocker locker(&lock_); + quintptr diff = reinterpret_cast(e->data()) - + reinterpret_cast(data_); - int index = diff / element_sz_; + int index = diff / element_sz_; - available_.replace(index, true); + available_.replace(index, true); - lent_elements_.remove(e); + lent_elements_.remove(e); - if (lent_elements_.empty()) { - empty_time_ = QDateTime::currentMSecsSinceEpoch(); - } - } + if (lent_elements_.empty()) { + empty_time_ = QDateTime::currentMSecsSinceEpoch(); + } + } - int GetUsageCount() - { - QMutexLocker locker(&lock_); - return lent_elements_.size(); - } + int GetUsageCount() + { + QMutexLocker locker(&lock_); + return lent_elements_.size(); + } - bool Allocate(size_t ele_sz, size_t nb_elements) - { - if (IsAllocated()) { - return true; - } + bool Allocate(size_t ele_sz, size_t nb_elements) + { + if (IsAllocated()) { + return true; + } - element_sz_ = ele_sz; + element_sz_ = ele_sz; - allocated_sz_ = element_sz_ * nb_elements; + allocated_sz_ = element_sz_ * nb_elements; - if ((data_ = new uint8_t[allocated_sz_])) { - available_.resize(nb_elements); - available_.fill(true); + if ((data_ = new uint8_t[allocated_sz_])) { + available_.resize(nb_elements); + available_.fill(true); - return true; - } else { - available_.clear(); + return true; + } else { + available_.clear(); - return false; - } - } + return false; + } + } - inline int GetElementCount() const - { - return available_.size(); - } + inline int GetElementCount() const + { + return available_.size(); + } - inline bool IsAllocated() const - { - return data_; - } + inline bool IsAllocated() const + { + return data_; + } - inline qint64 GetTimeArenaWasMadeEmpty() - { - QMutexLocker locker(&lock_); - return empty_time_; - } + inline qint64 GetTimeArenaWasMadeEmpty() + { + QMutexLocker locker(&lock_); + return empty_time_; + } - private: - MemoryPool* parent_; + private: + MemoryPool *parent_; - uint8_t* data_; + uint8_t *data_; - size_t allocated_sz_; + size_t allocated_sz_; - QVector available_; + QVector available_; - QMutex lock_; + QMutex lock_; - size_t element_sz_; + size_t element_sz_; - std::list lent_elements_; + std::list lent_elements_; - qint64 empty_time_; + qint64 empty_time_; + }; - }; - - /** + /** * @brief Retrieves an element from an available arena */ - ElementPtr Get() - { - QMutexLocker locker(&lock_); + ElementPtr Get() + { + QMutexLocker locker(&lock_); - // Attempt to get an element from an arena - foreach (Arena* a, arenas_) { - ElementPtr e = a->Get(); + // Attempt to get an element from an arena + foreach (Arena *a, arenas_) { + ElementPtr e = a->Get(); - if (e) { - return e; - } - } + if (e) { + return e; + } + } - // All arenas were empty, we'll need to create a new one - if (arenas_.empty()) { - qDebug() << "No arenas, creating new..."; - } else { - qDebug() << "All arenas are full, creating new..."; - } + // All arenas were empty, we'll need to create a new one + if (arenas_.empty()) { + qDebug() << "No arenas, creating new..."; + } else { + qDebug() << "All arenas are full, creating new..."; + } - size_t ele_sz = GetElementSize(); + size_t ele_sz = GetElementSize(); - if (!ele_sz) { - qCritical() << "Failed to create arena, element size was 0"; - return nullptr; - } + if (!ele_sz) { + qCritical() << "Failed to create arena, element size was 0"; + return nullptr; + } - if (element_count_ <= 0) { - qCritical() << "Failed to create arena, element count was invalid:" << element_count_; - return nullptr; - } + if (element_count_ <= 0) { + qCritical() << "Failed to create arena, element count was invalid:" + << element_count_; + return nullptr; + } - Arena* a = new Arena(this); - if (!a->Allocate(ele_sz, element_count_)) { - qCritical() << "Failed to create arena, allocation failed. Out of memory?"; - delete a; - return nullptr; - } + Arena *a = new Arena(this); + if (!a->Allocate(ele_sz, element_count_)) { + qCritical() + << "Failed to create arena, allocation failed. Out of memory?"; + delete a; + return nullptr; + } - arenas_.push_back(a); - return a->Get(); - } + arenas_.push_back(a); + return a->Get(); + } protected: - /** + /** * @brief The size of each element * * Override this to use a custom size (e.g. a char array where T = char but the element size is > 1) */ - virtual size_t GetElementSize() - { - return sizeof(uint8_t); - } + virtual size_t GetElementSize() + { + return sizeof(uint8_t); + } private: - int element_count_; + int element_count_; - std::list arenas_; + std::list arenas_; - QMutex lock_; + QMutex lock_; - QTimer *clear_timer_; + QTimer *clear_timer_; - static const qint64 kMaxEmptyArenaLife = 5000; + static const qint64 kMaxEmptyArenaLife = 5000; private slots: - void ClearEmptyArenas() - { - QMutexLocker locker(&lock_); + void ClearEmptyArenas() + { + QMutexLocker locker(&lock_); - const qint64 min_time = QDateTime::currentMSecsSinceEpoch() - kMaxEmptyArenaLife; + const qint64 min_time = + QDateTime::currentMSecsSinceEpoch() - kMaxEmptyArenaLife; - for (auto it=arenas_.begin(); it!=arenas_.end(); ) { - Arena* arena = (*it); - - if (arena->GetUsageCount() == 0 && arena->GetTimeArenaWasMadeEmpty() <= min_time) { - qDebug() << "Removing an empty arena"; - delete arena; - it = arenas_.erase(it); - } else { - it++; - } - } - } + for (auto it = arenas_.begin(); it != arenas_.end();) { + Arena *arena = (*it); + if (arena->GetUsageCount() == 0 && + arena->GetTimeArenaWasMadeEmpty() <= min_time) { + qDebug() << "Removing an empty arena"; + delete arena; + it = arenas_.erase(it); + } else { + it++; + } + } + } }; } diff --git a/app/common/ocioutils.cpp b/app/common/ocioutils.cpp index fc7cda122..d1f30081d 100644 --- a/app/common/ocioutils.cpp +++ b/app/common/ocioutils.cpp @@ -20,28 +20,29 @@ #include "ocioutils.h" -namespace olive { +namespace olive +{ OCIO::BitDepth OCIOUtils::GetOCIOBitDepthFromPixelFormat(PixelFormat format) { - switch (format) { - case PixelFormat::U8: - return OCIO::BIT_DEPTH_UINT8; - case PixelFormat::U16: - return OCIO::BIT_DEPTH_UINT16; - break; - case PixelFormat::F16: - return OCIO::BIT_DEPTH_F16; - break; - case PixelFormat::F32: - return OCIO::BIT_DEPTH_F32; - break; - case PixelFormat::INVALID: - case PixelFormat::COUNT: - break; - } + switch (format) { + case PixelFormat::U8: + return OCIO::BIT_DEPTH_UINT8; + case PixelFormat::U16: + return OCIO::BIT_DEPTH_UINT16; + break; + case PixelFormat::F16: + return OCIO::BIT_DEPTH_F16; + break; + case PixelFormat::F32: + return OCIO::BIT_DEPTH_F32; + break; + case PixelFormat::INVALID: + case PixelFormat::COUNT: + break; + } - return OCIO::BIT_DEPTH_UNKNOWN; + return OCIO::BIT_DEPTH_UNKNOWN; } } diff --git a/app/common/ocioutils.h b/app/common/ocioutils.h index 38c080077..7a8f63378 100644 --- a/app/common/ocioutils.h +++ b/app/common/ocioutils.h @@ -26,12 +26,12 @@ namespace OCIO = OCIO_NAMESPACE; #include "render/videoparams.h" -namespace olive { - -class OCIOUtils +namespace olive { + +class OCIOUtils { public: - static OCIO::BitDepth GetOCIOBitDepthFromPixelFormat(PixelFormat format); + static OCIO::BitDepth GetOCIOBitDepthFromPixelFormat(PixelFormat format); }; } diff --git a/app/common/oiioutils.cpp b/app/common/oiioutils.cpp index 9697a2f6e..38e966f9d 100644 --- a/app/common/oiioutils.cpp +++ b/app/common/oiioutils.cpp @@ -22,62 +22,58 @@ #include -namespace olive { - -void OIIOUtils::FrameToBuffer(const Frame* frame, OIIO::ImageBuf *buf) +namespace olive { - buf->set_pixels(OIIO::ROI(), - buf->spec().format, - frame->const_data(), - OIIO::AutoStride, - frame->linesize_bytes()); + +void OIIOUtils::FrameToBuffer(const Frame *frame, OIIO::ImageBuf *buf) +{ + buf->set_pixels(OIIO::ROI(), buf->spec().format, frame->const_data(), + OIIO::AutoStride, frame->linesize_bytes()); } -void OIIOUtils::BufferToFrame(OIIO::ImageBuf *buf, Frame* frame) +void OIIOUtils::BufferToFrame(OIIO::ImageBuf *buf, Frame *frame) { - buf->get_pixels(OIIO::ROI(), - buf->spec().format, - frame->data(), - OIIO::AutoStride, - frame->linesize_bytes()); + buf->get_pixels(OIIO::ROI(), buf->spec().format, frame->data(), + OIIO::AutoStride, frame->linesize_bytes()); } rational OIIOUtils::GetPixelAspectRatioFromOIIO(const OIIO::ImageSpec &spec) { - return rational::fromDouble(spec.get_float_attribute("PixelAspectRatio", 1)); + return rational::fromDouble( + spec.get_float_attribute("PixelAspectRatio", 1)); } PixelFormat OIIOUtils::GetFormatFromOIIOBasetype(OIIO::TypeDesc::BASETYPE type) { - switch (type) { - case OIIO::TypeDesc::UNKNOWN: - case OIIO::TypeDesc::NONE: - break; + switch (type) { + case OIIO::TypeDesc::UNKNOWN: + case OIIO::TypeDesc::NONE: + break; - case OIIO::TypeDesc::INT8: - case OIIO::TypeDesc::INT16: - case OIIO::TypeDesc::INT32: - case OIIO::TypeDesc::UINT32: - case OIIO::TypeDesc::INT64: - case OIIO::TypeDesc::UINT64: - case OIIO::TypeDesc::STRING: - case OIIO::TypeDesc::PTR: - case OIIO::TypeDesc::LASTBASE: - case OIIO::TypeDesc::DOUBLE: - qDebug() << "Tried to use unknown OIIO base type"; - break; + case OIIO::TypeDesc::INT8: + case OIIO::TypeDesc::INT16: + case OIIO::TypeDesc::INT32: + case OIIO::TypeDesc::UINT32: + case OIIO::TypeDesc::INT64: + case OIIO::TypeDesc::UINT64: + case OIIO::TypeDesc::STRING: + case OIIO::TypeDesc::PTR: + case OIIO::TypeDesc::LASTBASE: + case OIIO::TypeDesc::DOUBLE: + qDebug() << "Tried to use unknown OIIO base type"; + break; - case OIIO::TypeDesc::UINT8: - return PixelFormat::U8; - case OIIO::TypeDesc::UINT16: - return PixelFormat::U16; - case OIIO::TypeDesc::HALF: - return PixelFormat::F16; - case OIIO::TypeDesc::FLOAT: - return PixelFormat::F32; - } + case OIIO::TypeDesc::UINT8: + return PixelFormat::U8; + case OIIO::TypeDesc::UINT16: + return PixelFormat::U16; + case OIIO::TypeDesc::HALF: + return PixelFormat::F16; + case OIIO::TypeDesc::FLOAT: + return PixelFormat::F32; + } - return PixelFormat::INVALID; + return PixelFormat::INVALID; } } diff --git a/app/common/oiioutils.h b/app/common/oiioutils.h index 633758fe0..2c19c4b4b 100644 --- a/app/common/oiioutils.h +++ b/app/common/oiioutils.h @@ -27,37 +27,38 @@ #include "codec/frame.h" #include "render/videoparams.h" -namespace olive { +namespace olive +{ class OIIOUtils { public: - static OIIO::TypeDesc::BASETYPE GetOIIOBaseTypeFromFormat(PixelFormat format) - { - switch (format) { - case PixelFormat::U8: - return OIIO::TypeDesc::UINT8; - case PixelFormat::U16: - return OIIO::TypeDesc::UINT16; - case PixelFormat::F16: - return OIIO::TypeDesc::HALF; - case PixelFormat::F32: - return OIIO::TypeDesc::FLOAT; - case PixelFormat::INVALID: - case PixelFormat::COUNT: - break; - } + static OIIO::TypeDesc::BASETYPE + GetOIIOBaseTypeFromFormat(PixelFormat format) + { + switch (format) { + case PixelFormat::U8: + return OIIO::TypeDesc::UINT8; + case PixelFormat::U16: + return OIIO::TypeDesc::UINT16; + case PixelFormat::F16: + return OIIO::TypeDesc::HALF; + case PixelFormat::F32: + return OIIO::TypeDesc::FLOAT; + case PixelFormat::INVALID: + case PixelFormat::COUNT: + break; + } - return OIIO::TypeDesc::UNKNOWN; - } + return OIIO::TypeDesc::UNKNOWN; + } - static void FrameToBuffer(const Frame *frame, OIIO::ImageBuf* buf); + static void FrameToBuffer(const Frame *frame, OIIO::ImageBuf *buf); - static void BufferToFrame(OIIO::ImageBuf* buf, Frame* frame); + static void BufferToFrame(OIIO::ImageBuf *buf, Frame *frame); - static PixelFormat GetFormatFromOIIOBasetype(OIIO::TypeDesc::BASETYPE type); - - static rational GetPixelAspectRatioFromOIIO(const OIIO::ImageSpec& spec); + static PixelFormat GetFormatFromOIIOBasetype(OIIO::TypeDesc::BASETYPE type); + static rational GetPixelAspectRatioFromOIIO(const OIIO::ImageSpec &spec); }; } diff --git a/app/common/power.h b/app/common/power.h index 1ac6bfbeb..bcb75e887 100644 --- a/app/common/power.h +++ b/app/common/power.h @@ -25,30 +25,31 @@ #include "common/define.h" -namespace olive { +namespace olive +{ uint32_t ceil_to_power_of_2(uint32_t v) { - v--; - v |= v >> 1; - v |= v >> 2; - v |= v >> 4; - v |= v >> 8; - v |= v >> 16; - v++; + v--; + v |= v >> 1; + v |= v >> 2; + v |= v >> 4; + v |= v >> 8; + v |= v >> 16; + v++; - return v; + return v; } uint32_t floor_to_power_of_2(uint32_t x) { - x = x | (x >> 1); - x = x | (x >> 2); - x = x | (x >> 4); - x = x | (x >> 8); - x = x | (x >> 16); + x = x | (x >> 1); + x = x | (x >> 2); + x = x | (x >> 4); + x = x | (x >> 8); + x = x | (x >> 16); - return x - (x >> 1); + return x - (x >> 1); } } diff --git a/app/common/qtutils.cpp b/app/common/qtutils.cpp index 95ca7b712..8b838da22 100644 --- a/app/common/qtutils.cpp +++ b/app/common/qtutils.cpp @@ -22,192 +22,203 @@ #include -namespace olive { +namespace olive +{ -int QtUtils::QFontMetricsWidth(QFontMetrics fm, const QString& s) { +int QtUtils::QFontMetricsWidth(QFontMetrics fm, const QString &s) +{ #if QT_VERSION < QT_VERSION_CHECK(5, 11, 0) - return fm.width(s); + return fm.width(s); #else - return fm.horizontalAdvance(s); + return fm.horizontalAdvance(s); #endif } QFrame *QtUtils::CreateHorizontalLine() { - QFrame* horizontal_line = new QFrame(); - horizontal_line->setFrameShape(QFrame::HLine); - horizontal_line->setFrameShadow(QFrame::Sunken); - return horizontal_line; + QFrame *horizontal_line = new QFrame(); + horizontal_line->setFrameShape(QFrame::HLine); + horizontal_line->setFrameShadow(QFrame::Sunken); + return horizontal_line; } QFrame *QtUtils::CreateVerticalLine() { - QFrame *l = CreateHorizontalLine(); - l->setFrameShape(QFrame::VLine); - return l; + QFrame *l = CreateHorizontalLine(); + l->setFrameShape(QFrame::VLine); + return l; } -int QtUtils::MsgBox(QWidget *parent, QMessageBox::Icon icon, const QString &title, const QString &message, QMessageBox::StandardButtons buttons) +int QtUtils::MsgBox(QWidget *parent, QMessageBox::Icon icon, + const QString &title, const QString &message, + QMessageBox::StandardButtons buttons) { - QMessageBox b(parent); - b.setIcon(icon); - b.setWindowModality(Qt::WindowModal); - b.setWindowTitle(title); - b.setText(message); + QMessageBox b(parent); + b.setIcon(icon); + b.setWindowModality(Qt::WindowModal); + b.setWindowTitle(title); + b.setText(message); - uint mask = QMessageBox::FirstButton; - while (mask <= QMessageBox::LastButton) { - uint sb = buttons & mask; - if (sb) { - b.addButton(static_cast(sb)); - } - mask <<= 1; - } + uint mask = QMessageBox::FirstButton; + while (mask <= QMessageBox::LastButton) { + uint sb = buttons & mask; + if (sb) { + b.addButton(static_cast(sb)); + } + mask <<= 1; + } - return b.exec(); + return b.exec(); } QDateTime QtUtils::GetCreationDate(const QFileInfo &info) { #if QT_VERSION < QT_VERSION_CHECK(5, 10, 0) - return info.created(); + return info.created(); #else - QDateTime t = info.birthTime(); - if (!t.isValid()) { - t = info.metadataChangeTime(); - } - return t; + QDateTime t = info.birthTime(); + if (!t.isValid()) { + t = info.metadataChangeTime(); + } + return t; #endif } QString QtUtils::GetFormattedDateTime(const QDateTime &dt) { - return dt.toString(Qt::TextDate); + return dt.toString(Qt::TextDate); } -QStringList QtUtils::WordWrapString(const QString &s, const QFontMetrics &fm, int bounding_width) +QStringList QtUtils::WordWrapString(const QString &s, const QFontMetrics &fm, + int bounding_width) { - QStringList list; + QStringList list; - QStringList lines = s.split('\n'); + QStringList lines = s.split('\n'); - // Iterate every line - for (int i=0; i 1 && QFontMetricsWidth(fm, this_line) >= bounding_width) { - int old_size = this_line.size(); - int hard_break = -1; + while (this_line.size() > 1 && + QFontMetricsWidth(fm, this_line) >= bounding_width) { + int old_size = this_line.size(); + int hard_break = -1; - for (int j=this_line.size()-1; j>=0; j--) { - const QChar &char_test = this_line.at(j); + for (int j = this_line.size() - 1; j >= 0; j--) { + const QChar &char_test = this_line.at(j); - if (char_test.isSpace() - || char_test == '-') { - if (QFontMetricsWidth(fm, this_line.left(j)) < bounding_width) { - if (!char_test.isSpace()) { - j++; - } + if (char_test.isSpace() || char_test == '-') { + if (QFontMetricsWidth(fm, this_line.left(j)) < + bounding_width) { + if (!char_test.isSpace()) { + j++; + } - QString chopped = this_line.left(j); + QString chopped = this_line.left(j); - list.append(chopped); + list.append(chopped); - while (j < this_line.size() && this_line.at(j).isSpace()) { - j++; - } - this_line.remove(0, j); - break; - } - } else if (hard_break == -1 && QFontMetricsWidth(fm, this_line.left(j)) < bounding_width) { - // In case we can't find a better place to split, split at the earliest time the line - // goes under the width limit - hard_break = j; - } - } + while (j < this_line.size() && + this_line.at(j).isSpace()) { + j++; + } + this_line.remove(0, j); + break; + } + } else if (hard_break == -1 && + QFontMetricsWidth(fm, this_line.left(j)) < + bounding_width) { + // In case we can't find a better place to split, split at the earliest time the line + // goes under the width limit + hard_break = j; + } + } - if (old_size == this_line.size()) { - if (hard_break != -1) { - list.append(this_line.left(hard_break)); - this_line.remove(0, hard_break); - } else { - qWarning() << "Failed to find anywhere to wrap. Returning full line."; - break; - } - } - } + if (old_size == this_line.size()) { + if (hard_break != -1) { + list.append(this_line.left(hard_break)); + this_line.remove(0, hard_break); + } else { + qWarning() + << "Failed to find anywhere to wrap. Returning full line."; + break; + } + } + } - if (!this_line.isEmpty()) { - list.append(this_line); - } - } + if (!this_line.isEmpty()) { + list.append(this_line); + } + } - return list; + return list; } -Qt::KeyboardModifiers QtUtils::FlipControlAndShiftModifiers(Qt::KeyboardModifiers e) +Qt::KeyboardModifiers +QtUtils::FlipControlAndShiftModifiers(Qt::KeyboardModifiers e) { - if (e & Qt::ControlModifier & Qt::ShiftModifier) { - return e; - } + if (e & Qt::ControlModifier & Qt::ShiftModifier) { + return e; + } - if (e & Qt::ShiftModifier) { - e |= Qt::ControlModifier; - e &= ~Qt::ShiftModifier; - } else if (e & Qt::ControlModifier) { - e |= Qt::ShiftModifier; - e &= ~Qt::ControlModifier; - } + if (e & Qt::ShiftModifier) { + e |= Qt::ControlModifier; + e &= ~Qt::ShiftModifier; + } else if (e & Qt::ControlModifier) { + e |= Qt::ShiftModifier; + e &= ~Qt::ControlModifier; + } - return e; + return e; } void QtUtils::SetComboBoxData(QComboBox *cb, int data) { - for (int i=0; icount(); i++) { - if (cb->itemData(i).toInt() == data) { - cb->setCurrentIndex(i); - break; - } - } + for (int i = 0; i < cb->count(); i++) { + if (cb->itemData(i).toInt() == data) { + cb->setCurrentIndex(i); + break; + } + } } void QtUtils::SetComboBoxData(QComboBox *cb, const QString &data) { - for (int i=0; icount(); i++) { - if (cb->itemData(i).toString() == data) { - cb->setCurrentIndex(i); - break; - } - } + for (int i = 0; i < cb->count(); i++) { + if (cb->itemData(i).toString() == data) { + cb->setCurrentIndex(i); + break; + } + } } QColor QtUtils::toQColor(const core::Color &i) { - QColor c; + QColor c; - // QColor only supports values from 0.0 to 1.0 and are only used for UI representations - c.setRedF(std::clamp(i.red(), 0.0f, 1.0f)); - c.setGreenF(std::clamp(i.green(), 0.0f, 1.0f)); - c.setBlueF(std::clamp(i.blue(), 0.0f, 1.0f)); - c.setAlphaF(std::clamp(i.alpha(), 0.0f, 1.0f)); + // QColor only supports values from 0.0 to 1.0 and are only used for UI representations + c.setRedF(std::clamp(i.red(), 0.0f, 1.0f)); + c.setGreenF(std::clamp(i.green(), 0.0f, 1.0f)); + c.setBlueF(std::clamp(i.blue(), 0.0f, 1.0f)); + c.setAlphaF(std::clamp(i.alpha(), 0.0f, 1.0f)); - return c; + return c; } -namespace core { +namespace core +{ uint qHash(const core::rational &r, uint seed) { - return ::qHash(r.toDouble(), seed); + return ::qHash(r.toDouble(), seed); } uint qHash(const core::TimeRange &r, uint seed) { - return qHash(r.in(), seed) ^ qHash(r.out(), seed); + return qHash(r.in(), seed) ^ qHash(r.out(), seed); } - } } diff --git a/app/common/qtutils.h b/app/common/qtutils.h index 6bfad9ee3..5156c9cbd 100644 --- a/app/common/qtutils.h +++ b/app/common/qtutils.h @@ -29,76 +29,79 @@ #include #include -namespace olive { +namespace olive +{ class QtUtils { public: - /** + /** * @brief Retrieves the width of a string according to certain QFontMetrics * * QFontMetrics::width() has been deprecatd in favor of QFontMetrics::horizontalAdvance(), but the * latter was only introduced in 5.11+. This function wraps the latter for 5.11+ and the former for * earlier. */ - static int QFontMetricsWidth(QFontMetrics fm, const QString& s); + static int QFontMetricsWidth(QFontMetrics fm, const QString &s); - static QFrame* CreateHorizontalLine(); + static QFrame *CreateHorizontalLine(); - static QFrame* CreateVerticalLine(); + static QFrame *CreateVerticalLine(); - static int MsgBox(QWidget *parent, QMessageBox::Icon icon, const QString& title, const QString& message, QMessageBox::StandardButtons buttons = QMessageBox::Ok); + static int MsgBox(QWidget *parent, QMessageBox::Icon icon, + const QString &title, const QString &message, + QMessageBox::StandardButtons buttons = QMessageBox::Ok); - static QDateTime GetCreationDate(const QFileInfo &info); + static QDateTime GetCreationDate(const QFileInfo &info); - static QString GetFormattedDateTime(const QDateTime &dt); + static QString GetFormattedDateTime(const QDateTime &dt); - static QStringList WordWrapString(const QString &s, const QFontMetrics &fm, int bounding_width); + static QStringList WordWrapString(const QString &s, const QFontMetrics &fm, + int bounding_width); - static Qt::KeyboardModifiers FlipControlAndShiftModifiers(Qt::KeyboardModifiers e); + static Qt::KeyboardModifiers + FlipControlAndShiftModifiers(Qt::KeyboardModifiers e); - static void SetComboBoxData(QComboBox *cb, int data); - static void SetComboBoxData(QComboBox *cb, const QString &data); + static void SetComboBoxData(QComboBox *cb, int data); + static void SetComboBoxData(QComboBox *cb, const QString &data); - template - static T *GetParentOfType(const QObject *child) - { - QObject *t = child->parent(); + template static T *GetParentOfType(const QObject *child) + { + QObject *t = child->parent(); - while (t) { - if (T *p = dynamic_cast(t)) { - return p; - } - t = t->parent(); - } + while (t) { + if (T *p = dynamic_cast(t)) { + return p; + } + t = t->parent(); + } - return nullptr; - } + return nullptr; + } - static QColor toQColor(const core::Color &c); + static QColor toQColor(const core::Color &c); - /** + /** * @brief Convert a pointer to a value that can be sent between NodeParams */ - static QVariant PtrToValue(void* ptr) - { - return reinterpret_cast(ptr); - } + static QVariant PtrToValue(void *ptr) + { + return reinterpret_cast(ptr); + } - /** + /** * @brief Convert a NodeParam value to a pointer of any kind */ - template - static T* ValueToPtr(const QVariant &ptr) - { - return reinterpret_cast(ptr.value()); - } - + template static T *ValueToPtr(const QVariant &ptr) + { + return reinterpret_cast(ptr.value()); + } }; -namespace core { +namespace core +{ -uint qHash(const core::rational& r, uint seed = 0); -uint qHash(const core::TimeRange& r, uint seed = 0); +uint qHash(const core::rational &r, uint seed = 0); +uint qHash(const core::TimeRange &r, uint seed = 0); } diff --git a/app/common/range.h b/app/common/range.h index 1f34874a3..9ae738a16 100644 --- a/app/common/range.h +++ b/app/common/range.h @@ -21,10 +21,9 @@ #ifndef RANGE_H #define RANGE_H -template -bool InRange(T a, T b, T range) +template bool InRange(T a, T b, T range) { - return (a >= b - range && a <= b + range); + return (a >= b - range && a <= b + range); } #endif // RANGE_H diff --git a/app/common/ratiodialog.cpp b/app/common/ratiodialog.cpp index ee85582fa..4586175c7 100644 --- a/app/common/ratiodialog.cpp +++ b/app/common/ratiodialog.cpp @@ -24,69 +24,71 @@ #include #include -namespace olive { - -double GetFloatRatioFromUser(QWidget* parent, - const QString& title, - bool* ok_in) +namespace olive { - QString s; - forever { - bool ok; +double GetFloatRatioFromUser(QWidget *parent, const QString &title, bool *ok_in) +{ + QString s; - s = QInputDialog::getText(parent, - title, - QCoreApplication::translate("RatioDialog", "Enter custom ratio (e.g. \"4:3\", \"16/9\", etc.):"), - QLineEdit::Normal, - s, - &ok); + forever + { + bool ok; - if (!ok) { - // User cancelled dialog, do nothing - if (ok_in) { - *ok_in = false; - } - return qSNaN(); - } + s = QInputDialog::getText( + parent, title, + QCoreApplication::translate( + "RatioDialog", + "Enter custom ratio (e.g. \"4:3\", \"16/9\", etc.):"), + QLineEdit::Normal, s, &ok); - QStringList ratio_components = s.split(QRegularExpression(QStringLiteral(":|;|\\/"))); + if (!ok) { + // User cancelled dialog, do nothing + if (ok_in) { + *ok_in = false; + } + return qSNaN(); + } - if (ratio_components.size() == 1) { - bool float_ok; + QStringList ratio_components = + s.split(QRegularExpression(QStringLiteral(":|;|\\/"))); - double flt = ratio_components.at(0).toDouble(&float_ok); + if (ratio_components.size() == 1) { + bool float_ok; - if (float_ok && flt > 0) { - if (ok_in) { - *ok_in = true; - } - return flt; - } - } else if (ratio_components.size() == 2) { - bool numer_ok, denom_ok; + double flt = ratio_components.at(0).toDouble(&float_ok); - double num = ratio_components.at(0).toDouble(&numer_ok); - double den = ratio_components.at(1).toDouble(&denom_ok); + if (float_ok && flt > 0) { + if (ok_in) { + *ok_in = true; + } + return flt; + } + } else if (ratio_components.size() == 2) { + bool numer_ok, denom_ok; - if (numer_ok - && denom_ok - && num > 0 - && den > 0) { - // Exit loop and set this ratio - if (ok_in) { - *ok_in = true; - } - return num / den; - } - } + double num = ratio_components.at(0).toDouble(&numer_ok); + double den = ratio_components.at(1).toDouble(&denom_ok); - QMessageBox::warning(parent, - QCoreApplication::translate("RatioDialog", "Invalid custom ratio"), - QCoreApplication::translate("RatioDialog", "Failed to parse \"%1\" into an aspect ratio. Please format a " - "rational fraction with a ':' or a '/' separator.").arg(s), - QMessageBox::Ok); - } + if (numer_ok && denom_ok && num > 0 && den > 0) { + // Exit loop and set this ratio + if (ok_in) { + *ok_in = true; + } + return num / den; + } + } + + QMessageBox::warning( + parent, + QCoreApplication::translate("RatioDialog", "Invalid custom ratio"), + QCoreApplication::translate( + "RatioDialog", + "Failed to parse \"%1\" into an aspect ratio. Please format a " + "rational fraction with a ':' or a '/' separator.") + .arg(s), + QMessageBox::Ok); + } } } diff --git a/app/common/ratiodialog.h b/app/common/ratiodialog.h index b7b5debd0..fca8d0194 100644 --- a/app/common/ratiodialog.h +++ b/app/common/ratiodialog.h @@ -23,11 +23,11 @@ #include -namespace olive { +namespace olive +{ -double GetFloatRatioFromUser(QWidget* parent, - const QString& title, - bool* ok_in); +double GetFloatRatioFromUser(QWidget *parent, const QString &title, + bool *ok_in); } diff --git a/app/common/threadsafemap.h b/app/common/threadsafemap.h index 0d4a6bc7e..bcf4f15f8 100644 --- a/app/common/threadsafemap.h +++ b/app/common/threadsafemap.h @@ -4,24 +4,21 @@ #include #include -template -class ThreadSafeMap -{ +template class ThreadSafeMap { public: - ThreadSafeMap() = default; + ThreadSafeMap() = default; - void insert(K key, V value) - { - mutex_.lock(); - map_.insert(key, value); - mutex_.unlock(); - } + void insert(K key, V value) + { + mutex_.lock(); + map_.insert(key, value); + mutex_.unlock(); + } private: - QMutex mutex_; - - QMap map_; + QMutex mutex_; + QMap map_; }; #endif // THREADSAFEMAP_H diff --git a/app/common/tohex.h b/app/common/tohex.h index 600baf54d..fefc395e3 100644 --- a/app/common/tohex.h +++ b/app/common/tohex.h @@ -6,10 +6,12 @@ #include "common/define.h" -namespace olive { +namespace olive +{ -inline QString ToHex(quint64 t) { - return QStringLiteral("%1").arg(t, 0, 16); +inline QString ToHex(quint64 t) +{ + return QStringLiteral("%1").arg(t, 0, 16); } } diff --git a/app/common/util.h b/app/common/util.h index 8758621d6..0438b4490 100644 --- a/app/common/util.h +++ b/app/common/util.h @@ -21,10 +21,9 @@ #ifndef UTIL_H #define UTIL_H -template -inline T mid(T a, T b) +template inline T mid(T a, T b) { - return (a + b) * 0.5; + return (a + b) * 0.5; } #endif // UTIL_H diff --git a/app/common/xmlutils.cpp b/app/common/xmlutils.cpp index 817b6e972..9cfa09fd7 100644 --- a/app/common/xmlutils.cpp +++ b/app/common/xmlutils.cpp @@ -23,23 +23,24 @@ #include "node/block/block.h" #include "node/factory.h" -namespace olive { +namespace olive +{ bool XMLReadNextStartElement(QXmlStreamReader *reader, CancelAtom *cancel_atom) { - QXmlStreamReader::TokenType token; + QXmlStreamReader::TokenType token; - while ((token = reader->readNext()) != QXmlStreamReader::Invalid - && token != QXmlStreamReader::EndDocument - && (!cancel_atom || !cancel_atom->IsCancelled())) { - if (reader->isEndElement()) { - return false; - } else if (reader->isStartElement()) { - return true; - } - } + while ((token = reader->readNext()) != QXmlStreamReader::Invalid && + token != QXmlStreamReader::EndDocument && + (!cancel_atom || !cancel_atom->IsCancelled())) { + if (reader->isEndElement()) { + return false; + } else if (reader->isStartElement()) { + return true; + } + } - return false; + return false; } } diff --git a/app/common/xmlutils.h b/app/common/xmlutils.h index de7b54128..08b48a125 100644 --- a/app/common/xmlutils.h +++ b/app/common/xmlutils.h @@ -27,7 +27,8 @@ #include "render/cancelatom.h" #include "undo/undocommand.h" -namespace olive { +namespace olive +{ class Block; class Node; @@ -35,7 +36,7 @@ class NodeInput; class NodeGroup; #define XMLAttributeLoop(reader, item) \ - foreach (const QXmlStreamAttribute& item, reader->attributes()) + foreach (const QXmlStreamAttribute &item, reader->attributes()) /** * @brief Workaround for QXmlStreamReader::readNextStartElement not detecting the end of a document @@ -46,7 +47,8 @@ class NodeGroup; * * See also: https://stackoverflow.com/questions/46346450/qt-qxmlstreamreader-always-returns-premature-end-of-document-error */ -bool XMLReadNextStartElement(QXmlStreamReader* reader, CancelAtom *cancel_atom = nullptr); +bool XMLReadNextStartElement(QXmlStreamReader *reader, + CancelAtom *cancel_atom = nullptr); } diff --git a/app/config/config.cpp b/app/config/config.cpp index 336b1eeb4..80f3c97cc 100644 --- a/app/config/config.cpp +++ b/app/config/config.cpp @@ -37,278 +37,386 @@ #include "ui/style/style.h" #include "window/mainwindow/mainwindow.h" -namespace olive { +namespace olive +{ Config Config::current_config_; Config::Config() { - SetDefaults(); + SetDefaults(); } -void Config::SetEntryInternal(const QString &key, NodeValue::Type type, const QVariant &data) +void Config::SetEntryInternal(const QString &key, NodeValue::Type type, + const QVariant &data) { - config_map_[key] = {type, data}; + config_map_[key] = { type, data }; } QString Config::GetConfigFilePath() { - return QDir(FileFunctions::GetConfigurationLocation()).filePath(QStringLiteral("config.xml")); + return QDir(FileFunctions::GetConfigurationLocation()) + .filePath(QStringLiteral("config.xml")); } Config &Config::Current() { - return current_config_; + return current_config_; } void Config::SetDefaults() { - config_map_.clear(); - SetEntryInternal(QStringLiteral("Style"), NodeValue::kText, StyleManager::kDefaultStyle); - SetEntryInternal(QStringLiteral("TimecodeDisplay"), NodeValue::kInt, Timecode::kTimecodeDropFrame); - SetEntryInternal(QStringLiteral("DefaultStillLength"), NodeValue::kRational, QVariant::fromValue(rational(2))); - SetEntryInternal(QStringLiteral("HoverFocus"), NodeValue::kBoolean, false); - SetEntryInternal(QStringLiteral("AudioScrubbing"), NodeValue::kBoolean, true); - SetEntryInternal(QStringLiteral("AutorecoveryEnabled"), NodeValue::kBoolean, true); - SetEntryInternal(QStringLiteral("AutorecoveryInterval"), NodeValue::kInt, 1); - SetEntryInternal(QStringLiteral("AutorecoveryMaximum"), NodeValue::kInt, 20); - SetEntryInternal(QStringLiteral("DiskCacheSaveInterval"), NodeValue::kInt, 10000); - SetEntryInternal(QStringLiteral("Language"), NodeValue::kText, QString()); - SetEntryInternal(QStringLiteral("ScrollZooms"), NodeValue::kBoolean, false); - SetEntryInternal(QStringLiteral("EnableSeekToImport"), NodeValue::kBoolean, false); - SetEntryInternal(QStringLiteral("EditToolAlsoSeeks"), NodeValue::kBoolean, false); - SetEntryInternal(QStringLiteral("EditToolSelectsLinks"), NodeValue::kBoolean, false); - SetEntryInternal(QStringLiteral("EnableDragFilesToTimeline"), NodeValue::kBoolean, true); - SetEntryInternal(QStringLiteral("InvertTimelineScrollAxes"), NodeValue::kBoolean, true); - SetEntryInternal(QStringLiteral("SelectAlsoSeeks"), NodeValue::kBoolean, false); - SetEntryInternal(QStringLiteral("PasteSeeks"), NodeValue::kBoolean, true); - SetEntryInternal(QStringLiteral("SeekAlsoSelects"), NodeValue::kBoolean, false); - SetEntryInternal(QStringLiteral("SetNameWithMarker"), NodeValue::kBoolean, false); - SetEntryInternal(QStringLiteral("AutoSeekToBeginning"), NodeValue::kBoolean, true); - SetEntryInternal(QStringLiteral("DropFileOnMediaToReplace"), NodeValue::kBoolean, false); - SetEntryInternal(QStringLiteral("AddDefaultEffectsToClips"), NodeValue::kBoolean, true); - SetEntryInternal(QStringLiteral("AutoscaleByDefault"), NodeValue::kBoolean, false); - SetEntryInternal(QStringLiteral("Autoscroll"), NodeValue::kInt, AutoScroll::kPage); - SetEntryInternal(QStringLiteral("AutoSelectDivider"), NodeValue::kBoolean, true); - SetEntryInternal(QStringLiteral("SetNameWithMarker"), NodeValue::kBoolean, false); - SetEntryInternal(QStringLiteral("RectifiedWaveforms"), NodeValue::kBoolean, true); - SetEntryInternal(QStringLiteral("DropWithoutSequenceBehavior"), NodeValue::kInt, ImportTool::kDWSAsk); - SetEntryInternal(QStringLiteral("Loop"), NodeValue::kBoolean, false); - SetEntryInternal(QStringLiteral("SplitClipsCopyNodes"), NodeValue::kBoolean, true); - SetEntryInternal(QStringLiteral("UseGradients"), NodeValue::kBoolean, true); - SetEntryInternal(QStringLiteral("AutoMergeTracks"), NodeValue::kBoolean, true); - SetEntryInternal(QStringLiteral("UseSliderLadders"), NodeValue::kBoolean, true); - SetEntryInternal(QStringLiteral("ShowWelcomeDialog"), NodeValue::kBoolean, true); - SetEntryInternal(QStringLiteral("ShowClipWhileDragging"), NodeValue::kBoolean, true); - SetEntryInternal(QStringLiteral("StopPlaybackOnLastFrame"), NodeValue::kBoolean, false); - SetEntryInternal(QStringLiteral("UseLegacyColorInInputTab"), NodeValue::kBoolean, false); - SetEntryInternal(QStringLiteral("ReassocLinToNonLin"), NodeValue::kBoolean, false); - SetEntryInternal(QStringLiteral("PreviewNonFloatDontAskAgain"), NodeValue::kBoolean, false); - SetEntryInternal(QStringLiteral("UseGLFinish"), NodeValue::kBoolean, false); + config_map_.clear(); + SetEntryInternal(QStringLiteral("Style"), NodeValue::kText, + StyleManager::kDefaultStyle); + SetEntryInternal(QStringLiteral("TimecodeDisplay"), NodeValue::kInt, + Timecode::kTimecodeDropFrame); + SetEntryInternal(QStringLiteral("DefaultStillLength"), NodeValue::kRational, + QVariant::fromValue(rational(2))); + SetEntryInternal(QStringLiteral("HoverFocus"), NodeValue::kBoolean, false); + SetEntryInternal(QStringLiteral("AudioScrubbing"), NodeValue::kBoolean, + true); + SetEntryInternal(QStringLiteral("AutorecoveryEnabled"), NodeValue::kBoolean, + true); + SetEntryInternal(QStringLiteral("AutorecoveryInterval"), NodeValue::kInt, + 1); + SetEntryInternal(QStringLiteral("AutorecoveryMaximum"), NodeValue::kInt, + 20); + SetEntryInternal(QStringLiteral("DiskCacheSaveInterval"), NodeValue::kInt, + 10000); + SetEntryInternal(QStringLiteral("Language"), NodeValue::kText, QString()); + SetEntryInternal(QStringLiteral("ScrollZooms"), NodeValue::kBoolean, false); + SetEntryInternal(QStringLiteral("EnableSeekToImport"), NodeValue::kBoolean, + false); + SetEntryInternal(QStringLiteral("EditToolAlsoSeeks"), NodeValue::kBoolean, + false); + SetEntryInternal(QStringLiteral("EditToolSelectsLinks"), + NodeValue::kBoolean, false); + SetEntryInternal(QStringLiteral("EnableDragFilesToTimeline"), + NodeValue::kBoolean, true); + SetEntryInternal(QStringLiteral("InvertTimelineScrollAxes"), + NodeValue::kBoolean, true); + SetEntryInternal(QStringLiteral("SelectAlsoSeeks"), NodeValue::kBoolean, + false); + SetEntryInternal(QStringLiteral("PasteSeeks"), NodeValue::kBoolean, true); + SetEntryInternal(QStringLiteral("SeekAlsoSelects"), NodeValue::kBoolean, + false); + SetEntryInternal(QStringLiteral("SetNameWithMarker"), NodeValue::kBoolean, + false); + SetEntryInternal(QStringLiteral("AutoSeekToBeginning"), NodeValue::kBoolean, + true); + SetEntryInternal(QStringLiteral("DropFileOnMediaToReplace"), + NodeValue::kBoolean, false); + SetEntryInternal(QStringLiteral("AddDefaultEffectsToClips"), + NodeValue::kBoolean, true); + SetEntryInternal(QStringLiteral("AutoscaleByDefault"), NodeValue::kBoolean, + false); + SetEntryInternal(QStringLiteral("Autoscroll"), NodeValue::kInt, + AutoScroll::kPage); + SetEntryInternal(QStringLiteral("AutoSelectDivider"), NodeValue::kBoolean, + true); + SetEntryInternal(QStringLiteral("SetNameWithMarker"), NodeValue::kBoolean, + false); + SetEntryInternal(QStringLiteral("RectifiedWaveforms"), NodeValue::kBoolean, + true); + SetEntryInternal(QStringLiteral("DropWithoutSequenceBehavior"), + NodeValue::kInt, ImportTool::kDWSAsk); + SetEntryInternal(QStringLiteral("Loop"), NodeValue::kBoolean, false); + SetEntryInternal(QStringLiteral("SplitClipsCopyNodes"), NodeValue::kBoolean, + true); + SetEntryInternal(QStringLiteral("UseGradients"), NodeValue::kBoolean, true); + SetEntryInternal(QStringLiteral("AutoMergeTracks"), NodeValue::kBoolean, + true); + SetEntryInternal(QStringLiteral("UseSliderLadders"), NodeValue::kBoolean, + true); + SetEntryInternal(QStringLiteral("ShowWelcomeDialog"), NodeValue::kBoolean, + true); + SetEntryInternal(QStringLiteral("ShowClipWhileDragging"), + NodeValue::kBoolean, true); + SetEntryInternal(QStringLiteral("StopPlaybackOnLastFrame"), + NodeValue::kBoolean, false); + SetEntryInternal(QStringLiteral("UseLegacyColorInInputTab"), + NodeValue::kBoolean, false); + SetEntryInternal(QStringLiteral("ReassocLinToNonLin"), NodeValue::kBoolean, + false); + SetEntryInternal(QStringLiteral("PreviewNonFloatDontAskAgain"), + NodeValue::kBoolean, false); + SetEntryInternal(QStringLiteral("UseGLFinish"), NodeValue::kBoolean, false); - SetEntryInternal(QStringLiteral("TimelineThumbnailMode"), NodeValue::kInt, Timeline::kThumbnailInOut); - SetEntryInternal(QStringLiteral("TimelineWaveformMode"), NodeValue::kInt, Timeline::kWaveformsEnabled); + SetEntryInternal(QStringLiteral("TimelineThumbnailMode"), NodeValue::kInt, + Timeline::kThumbnailInOut); + SetEntryInternal(QStringLiteral("TimelineWaveformMode"), NodeValue::kInt, + Timeline::kWaveformsEnabled); - SetEntryInternal(QStringLiteral("DefaultVideoTransition"), NodeValue::kText, QStringLiteral("org.olivevideoeditor.Olive.crossdissolve")); - SetEntryInternal(QStringLiteral("DefaultAudioTransition"), NodeValue::kText, QStringLiteral("org.olivevideoeditor.Olive.crossdissolve")); - SetEntryInternal(QStringLiteral("DefaultTransitionLength"), NodeValue::kRational, QVariant::fromValue(rational(1))); + SetEntryInternal( + QStringLiteral("DefaultVideoTransition"), NodeValue::kText, + QStringLiteral("org.olivevideoeditor.Olive.crossdissolve")); + SetEntryInternal( + QStringLiteral("DefaultAudioTransition"), NodeValue::kText, + QStringLiteral("org.olivevideoeditor.Olive.crossdissolve")); + SetEntryInternal(QStringLiteral("DefaultTransitionLength"), + NodeValue::kRational, QVariant::fromValue(rational(1))); - SetEntryInternal(QStringLiteral("DefaultSubtitleSize"), NodeValue::kInt, 48); - SetEntryInternal(QStringLiteral("DefaultSubtitleFamily"), NodeValue::kText, QString()); - SetEntryInternal(QStringLiteral("DefaultSubtitleWeight"), NodeValue::kInt, QFont::Bold); - SetEntryInternal(QStringLiteral("AntialiasSubtitles"), NodeValue::kBoolean, true); + SetEntryInternal(QStringLiteral("DefaultSubtitleSize"), NodeValue::kInt, + 48); + SetEntryInternal(QStringLiteral("DefaultSubtitleFamily"), NodeValue::kText, + QString()); + SetEntryInternal(QStringLiteral("DefaultSubtitleWeight"), NodeValue::kInt, + QFont::Bold); + SetEntryInternal(QStringLiteral("AntialiasSubtitles"), NodeValue::kBoolean, + true); - SetEntryInternal(QStringLiteral("AutoCacheDelay"), NodeValue::kInt, 1000); + SetEntryInternal(QStringLiteral("AutoCacheDelay"), NodeValue::kInt, 1000); - SetEntryInternal(QStringLiteral("CatColor0"), NodeValue::kInt, ColorCoding::kRed); - SetEntryInternal(QStringLiteral("CatColor1"), NodeValue::kInt, ColorCoding::kMaroon); - SetEntryInternal(QStringLiteral("CatColor2"), NodeValue::kInt, ColorCoding::kOrange); - SetEntryInternal(QStringLiteral("CatColor3"), NodeValue::kInt, ColorCoding::kBrown); - SetEntryInternal(QStringLiteral("CatColor4"), NodeValue::kInt, ColorCoding::kYellow); - SetEntryInternal(QStringLiteral("CatColor5"), NodeValue::kInt, ColorCoding::kOlive); - SetEntryInternal(QStringLiteral("CatColor6"), NodeValue::kInt, ColorCoding::kLime); - SetEntryInternal(QStringLiteral("CatColor7"), NodeValue::kInt, ColorCoding::kGreen); - SetEntryInternal(QStringLiteral("CatColor8"), NodeValue::kInt, ColorCoding::kCyan); - SetEntryInternal(QStringLiteral("CatColor9"), NodeValue::kInt, ColorCoding::kTeal); - SetEntryInternal(QStringLiteral("CatColor10"), NodeValue::kInt, ColorCoding::kBlue); - SetEntryInternal(QStringLiteral("CatColor11"), NodeValue::kInt, ColorCoding::kNavy); + SetEntryInternal(QStringLiteral("CatColor0"), NodeValue::kInt, + ColorCoding::kRed); + SetEntryInternal(QStringLiteral("CatColor1"), NodeValue::kInt, + ColorCoding::kMaroon); + SetEntryInternal(QStringLiteral("CatColor2"), NodeValue::kInt, + ColorCoding::kOrange); + SetEntryInternal(QStringLiteral("CatColor3"), NodeValue::kInt, + ColorCoding::kBrown); + SetEntryInternal(QStringLiteral("CatColor4"), NodeValue::kInt, + ColorCoding::kYellow); + SetEntryInternal(QStringLiteral("CatColor5"), NodeValue::kInt, + ColorCoding::kOlive); + SetEntryInternal(QStringLiteral("CatColor6"), NodeValue::kInt, + ColorCoding::kLime); + SetEntryInternal(QStringLiteral("CatColor7"), NodeValue::kInt, + ColorCoding::kGreen); + SetEntryInternal(QStringLiteral("CatColor8"), NodeValue::kInt, + ColorCoding::kCyan); + SetEntryInternal(QStringLiteral("CatColor9"), NodeValue::kInt, + ColorCoding::kTeal); + SetEntryInternal(QStringLiteral("CatColor10"), NodeValue::kInt, + ColorCoding::kBlue); + SetEntryInternal(QStringLiteral("CatColor11"), NodeValue::kInt, + ColorCoding::kNavy); - SetEntryInternal(QStringLiteral("AudioOutput"), NodeValue::kText, QString()); - SetEntryInternal(QStringLiteral("AudioInput"), NodeValue::kText, QString()); + SetEntryInternal(QStringLiteral("AudioOutput"), NodeValue::kText, + QString()); + SetEntryInternal(QStringLiteral("AudioInput"), NodeValue::kText, QString()); - SetEntryInternal(QStringLiteral("AudioOutputSampleRate"), NodeValue::kInt, 48000); - SetEntryInternal(QStringLiteral("AudioOutputChannelLayout"), NodeValue::kInt, AV_CH_LAYOUT_STEREO); - SetEntryInternal(QStringLiteral("AudioOutputSampleFormat"), NodeValue::kText, QString::fromStdString(SampleFormat(SampleFormat::S16).to_string())); + SetEntryInternal(QStringLiteral("AudioOutputSampleRate"), NodeValue::kInt, + 48000); + SetEntryInternal(QStringLiteral("AudioOutputChannelLayout"), + NodeValue::kInt, AV_CH_LAYOUT_STEREO); + SetEntryInternal( + QStringLiteral("AudioOutputSampleFormat"), NodeValue::kText, + QString::fromStdString(SampleFormat(SampleFormat::S16).to_string())); - SetEntryInternal(QStringLiteral("AudioRecordingFormat"), NodeValue::kInt, ExportFormat::kFormatWAV); - SetEntryInternal(QStringLiteral("AudioRecordingCodec"), NodeValue::kInt, ExportCodec::kCodecPCM); - SetEntryInternal(QStringLiteral("AudioRecordingSampleRate"), NodeValue::kInt, 48000); - SetEntryInternal(QStringLiteral("AudioRecordingChannelLayout"), NodeValue::kInt, AV_CH_LAYOUT_STEREO); - SetEntryInternal(QStringLiteral("AudioRecordingSampleFormat"), NodeValue::kText, QString::fromStdString(SampleFormat(SampleFormat::S16).to_string())); - SetEntryInternal(QStringLiteral("AudioRecordingBitRate"), NodeValue::kInt, 320); + SetEntryInternal(QStringLiteral("AudioRecordingFormat"), NodeValue::kInt, + ExportFormat::kFormatWAV); + SetEntryInternal(QStringLiteral("AudioRecordingCodec"), NodeValue::kInt, + ExportCodec::kCodecPCM); + SetEntryInternal(QStringLiteral("AudioRecordingSampleRate"), + NodeValue::kInt, 48000); + SetEntryInternal(QStringLiteral("AudioRecordingChannelLayout"), + NodeValue::kInt, AV_CH_LAYOUT_STEREO); + SetEntryInternal( + QStringLiteral("AudioRecordingSampleFormat"), NodeValue::kText, + QString::fromStdString(SampleFormat(SampleFormat::S16).to_string())); + SetEntryInternal(QStringLiteral("AudioRecordingBitRate"), NodeValue::kInt, + 320); - SetEntryInternal(QStringLiteral("DiskCacheBehind"), NodeValue::kRational, QVariant::fromValue(rational(0))); - SetEntryInternal(QStringLiteral("DiskCacheAhead"), NodeValue::kRational, QVariant::fromValue(rational(60))); + SetEntryInternal(QStringLiteral("DiskCacheBehind"), NodeValue::kRational, + QVariant::fromValue(rational(0))); + SetEntryInternal(QStringLiteral("DiskCacheAhead"), NodeValue::kRational, + QVariant::fromValue(rational(60))); - SetEntryInternal(QStringLiteral("DefaultSequenceWidth"), NodeValue::kInt, 1920); - SetEntryInternal(QStringLiteral("DefaultSequenceHeight"), NodeValue::kInt, 1080); - SetEntryInternal(QStringLiteral("DefaultSequencePixelAspect"), NodeValue::kRational, QVariant::fromValue(rational(1))); - SetEntryInternal(QStringLiteral("DefaultSequenceFrameRate"), NodeValue::kRational, QVariant::fromValue(rational(1001, 30000))); - SetEntryInternal(QStringLiteral("DefaultSequenceInterlacing"), NodeValue::kInt, VideoParams::kInterlaceNone); - SetEntryInternal(QStringLiteral("DefaultSequenceAutoCache2"), NodeValue::kBoolean, false); - SetEntryInternal(QStringLiteral("DefaultSequenceAudioFrequency"), NodeValue::kInt, 48000); - SetEntryInternal(QStringLiteral("DefaultSequenceAudioLayout"), NodeValue::kInt, QVariant::fromValue(static_cast(AV_CH_LAYOUT_STEREO))); + SetEntryInternal(QStringLiteral("DefaultSequenceWidth"), NodeValue::kInt, + 1920); + SetEntryInternal(QStringLiteral("DefaultSequenceHeight"), NodeValue::kInt, + 1080); + SetEntryInternal(QStringLiteral("DefaultSequencePixelAspect"), + NodeValue::kRational, QVariant::fromValue(rational(1))); + SetEntryInternal(QStringLiteral("DefaultSequenceFrameRate"), + NodeValue::kRational, + QVariant::fromValue(rational(1001, 30000))); + SetEntryInternal(QStringLiteral("DefaultSequenceInterlacing"), + NodeValue::kInt, VideoParams::kInterlaceNone); + SetEntryInternal(QStringLiteral("DefaultSequenceAutoCache2"), + NodeValue::kBoolean, false); + SetEntryInternal(QStringLiteral("DefaultSequenceAudioFrequency"), + NodeValue::kInt, 48000); + SetEntryInternal( + QStringLiteral("DefaultSequenceAudioLayout"), NodeValue::kInt, + QVariant::fromValue(static_cast(AV_CH_LAYOUT_STEREO))); - // Online/offline settings - SetEntryInternal(QStringLiteral("OnlinePixelFormat"), NodeValue::kInt, PixelFormat::F32); - SetEntryInternal(QStringLiteral("OfflinePixelFormat"), NodeValue::kInt, PixelFormat::F16); + // Online/offline settings + SetEntryInternal(QStringLiteral("OnlinePixelFormat"), NodeValue::kInt, + PixelFormat::F32); + SetEntryInternal(QStringLiteral("OfflinePixelFormat"), NodeValue::kInt, + PixelFormat::F16); - SetEntryInternal(QStringLiteral("MarkerColor"), NodeValue::kInt, ColorCoding::kLime); + SetEntryInternal(QStringLiteral("MarkerColor"), NodeValue::kInt, + ColorCoding::kLime); } void Config::Load() { - QFile config_file(GetConfigFilePath()); + QFile config_file(GetConfigFilePath()); - if (!config_file.exists()) { - return; - } + if (!config_file.exists()) { + return; + } - if (!config_file.open(QFile::ReadOnly)) { - qWarning() << "Failed to load application settings. This session will use defaults."; - return; - } + if (!config_file.open(QFile::ReadOnly)) { + qWarning() + << "Failed to load application settings. This session will use defaults."; + return; + } - // Reset to defaults - current_config_.SetDefaults(); + // Reset to defaults + current_config_.SetDefaults(); - QXmlStreamReader reader(&config_file); + QXmlStreamReader reader(&config_file); - QString config_version; + QString config_version; - while (XMLReadNextStartElement(&reader)) { - if (reader.name() == QStringLiteral("Configuration")) { - while (XMLReadNextStartElement(&reader)) { - QString key = reader.name().toString(); - QString value = reader.readElementText(); + while (XMLReadNextStartElement(&reader)) { + if (reader.name() == QStringLiteral("Configuration")) { + while (XMLReadNextStartElement(&reader)) { + QString key = reader.name().toString(); + QString value = reader.readElementText(); - if (key == QStringLiteral("Version")) { - config_version = value; + if (key == QStringLiteral("Version")) { + config_version = value; - if (!value.contains(".")) { - qDebug() << "CONFIG: This is a 0.1.x config file, upconvert"; - } - } else if (key == QStringLiteral("DefaultSequenceFrameRate") && !config_version.contains('.')) { - // 0.1.x stored this value as a float while we now use rationals, we'll use a heuristic to find the closest - // supported rational - qDebug() << " CONFIG: Finding closest match to" << value; + if (!value.contains(".")) { + qDebug() + << "CONFIG: This is a 0.1.x config file, upconvert"; + } + } else if (key == QStringLiteral("DefaultSequenceFrameRate") && + !config_version.contains('.')) { + // 0.1.x stored this value as a float while we now use rationals, we'll use a heuristic to find the closest + // supported rational + qDebug() << " CONFIG: Finding closest match to" << value; - double config_fr = value.toDouble(); + double config_fr = value.toDouble(); - const QVector& supported_frame_rates = VideoParams::kSupportedFrameRates; + const QVector &supported_frame_rates = + VideoParams::kSupportedFrameRates; - rational match = supported_frame_rates.first(); - double match_diff = qAbs(match.toDouble() - config_fr); + rational match = supported_frame_rates.first(); + double match_diff = qAbs(match.toDouble() - config_fr); - for (int i=1;imain_window(), - QCoreApplication::translate("Config", "Error loading settings"), - QCoreApplication::translate("Config", "Failed to load application settings. This session will " - "use defaults.\n\n%1").arg(reader.errorString()), - QMessageBox::Ok); - current_config_.SetDefaults(); - } + if (reader.hasError()) { + QMessageBox::critical( + Core::instance()->main_window(), + QCoreApplication::translate("Config", "Error loading settings"), + QCoreApplication::translate( + "Config", + "Failed to load application settings. This session will " + "use defaults.\n\n%1") + .arg(reader.errorString()), + QMessageBox::Ok); + current_config_.SetDefaults(); + } - config_file.close(); + config_file.close(); } void Config::Save() { - QString real_filename = GetConfigFilePath(); - QString temp_filename = FileFunctions::GetSafeTemporaryFilename(real_filename); + QString real_filename = GetConfigFilePath(); + QString temp_filename = + FileFunctions::GetSafeTemporaryFilename(real_filename); - QFile config_file(temp_filename); + QFile config_file(temp_filename); - if (!config_file.open(QFile::WriteOnly)) { - QMessageBox::critical(Core::instance()->main_window(), - QCoreApplication::translate("Config", "Error saving settings"), - QCoreApplication::translate("Config", "Failed to save application settings. The application " - "may lack write permissions for this location."), - QMessageBox::Ok); - return; - } + if (!config_file.open(QFile::WriteOnly)) { + QMessageBox::critical( + Core::instance()->main_window(), + QCoreApplication::translate("Config", "Error saving settings"), + QCoreApplication::translate( + "Config", + "Failed to save application settings. The application " + "may lack write permissions for this location."), + QMessageBox::Ok); + return; + } - QXmlStreamWriter writer(&config_file); - writer.setAutoFormatting(true); + QXmlStreamWriter writer(&config_file); + writer.setAutoFormatting(true); - writer.writeStartDocument(); + writer.writeStartDocument(); - writer.writeStartElement("Configuration"); + writer.writeStartElement("Configuration"); - // Anything after the hyphen is considered "unimportant" information - writer.writeTextElement("Version", QCoreApplication::applicationVersion().split('-').first()); + // Anything after the hyphen is considered "unimportant" information + writer.writeTextElement( + "Version", QCoreApplication::applicationVersion().split('-').first()); - QMapIterator iterator(current_config_.config_map_); - while (iterator.hasNext()) { - iterator.next(); + QMapIterator iterator(current_config_.config_map_); + while (iterator.hasNext()) { + iterator.next(); - QString value = NodeValue::ValueToString(iterator.value().type, iterator.value().data, false); + QString value = NodeValue::ValueToString(iterator.value().type, + iterator.value().data, false); - if (iterator.value().type == NodeValue::kNone) { - qWarning() << "Config key" << iterator.key() << "had null type and was discarded"; - } else { - writer.writeTextElement(iterator.key(), value); - } - } + if (iterator.value().type == NodeValue::kNone) { + qWarning() << "Config key" << iterator.key() + << "had null type and was discarded"; + } else { + writer.writeTextElement(iterator.key(), value); + } + } - writer.writeEndElement(); // Configuration + writer.writeEndElement(); // Configuration - writer.writeEndDocument(); + writer.writeEndDocument(); - config_file.close(); + config_file.close(); - if (!FileFunctions::RenameFileAllowOverwrite(temp_filename, real_filename)) { - qWarning() << QStringLiteral("Failed to overwrite \"%1\". Config has been saved as \"%2\" instead.") - .arg(real_filename, temp_filename); - } + if (!FileFunctions::RenameFileAllowOverwrite(temp_filename, + real_filename)) { + qWarning() + << QStringLiteral( + "Failed to overwrite \"%1\". Config has been saved as \"%2\" instead.") + .arg(real_filename, temp_filename); + } } QVariant Config::operator[](const QString &key) const { - return config_map_[key].data; + return config_map_[key].data; } QVariant &Config::operator[](const QString &key) { - return config_map_[key].data; + return config_map_[key].data; } NodeValue::Type Config::GetConfigEntryType(const QString &key) const { - return config_map_[key].type; + return config_map_[key].type; } } diff --git a/app/config/config.h b/app/config/config.h index 4179858dc..68c7ab9d4 100644 --- a/app/config/config.h +++ b/app/config/config.h @@ -27,42 +27,44 @@ #include "node/value.h" -namespace olive { +namespace olive +{ #define OLIVE_CONFIG(x) Config::Current()[QStringLiteral(x)] #define OLIVE_CONFIG_STR(x) Config::Current()[x] class Config { public: - static Config& Current(); + static Config &Current(); - void SetDefaults(); + void SetDefaults(); - static void Load(); + static void Load(); - static void Save(); + static void Save(); - QVariant operator[](const QString&) const; + QVariant operator[](const QString &) const; - QVariant& operator[](const QString&); + QVariant &operator[](const QString &); - NodeValue::Type GetConfigEntryType(const QString& key) const; + NodeValue::Type GetConfigEntryType(const QString &key) const; private: - Config(); + Config(); - struct ConfigEntry { - NodeValue::Type type; - QVariant data; - }; + struct ConfigEntry { + NodeValue::Type type; + QVariant data; + }; - void SetEntryInternal(const QString& key, NodeValue::Type type, const QVariant& data); + void SetEntryInternal(const QString &key, NodeValue::Type type, + const QVariant &data); - QMap config_map_; + QMap config_map_; - static Config current_config_; + static Config current_config_; - static QString GetConfigFilePath(); + static QString GetConfigFilePath(); }; } diff --git a/app/core.cpp b/app/core.cpp index f8d9ef758..412c9972e 100644 --- a/app/core.cpp +++ b/app/core.cpp @@ -78,547 +78,571 @@ #include "window/mainwindow/mainstatusbar.h" #include "window/mainwindow/mainwindow.h" -namespace olive { - -Core* Core::instance_ = nullptr; - -Core::Core(const CoreParams& params) : - main_window_(nullptr), - open_project_(nullptr), - tool_(Tool::kPointer), - addable_object_(Tool::kAddableEmpty), - snapping_(true), - core_params_(params), - magic_(false), - pixel_sampling_users_(0), - shown_cache_full_warning_(false) +namespace olive { - // Store reference to this object, making the assumption that Core will only ever be made in - // main(). This will obviously break if not. - instance_ = this; - translator_ = new QTranslator(this); +Core *Core::instance_ = nullptr; + +Core::Core(const CoreParams ¶ms) + : main_window_(nullptr) + , open_project_(nullptr) + , tool_(Tool::kPointer) + , addable_object_(Tool::kAddableEmpty) + , snapping_(true) + , core_params_(params) + , magic_(false) + , pixel_sampling_users_(0) + , shown_cache_full_warning_(false) +{ + // Store reference to this object, making the assumption that Core will only ever be made in + // main(). This will obviously break if not. + instance_ = this; + + translator_ = new QTranslator(this); } Core *Core::instance() { - return instance_; + return instance_; } void Core::DeclareTypesForQt() { - qRegisterMetaType(); - qRegisterMetaType(); - qRegisterMetaType(); - qRegisterMetaType(); - qRegisterMetaType(); - qRegisterMetaType(); - qRegisterMetaType(); - qRegisterMetaType(); - qRegisterMetaType(); - qRegisterMetaType(); - qRegisterMetaType(); - qRegisterMetaType(); - qRegisterMetaType(); - qRegisterMetaType(); - qRegisterMetaType(); - qRegisterMetaType(); + qRegisterMetaType(); + qRegisterMetaType(); + qRegisterMetaType(); + qRegisterMetaType(); + qRegisterMetaType(); + qRegisterMetaType(); + qRegisterMetaType(); + qRegisterMetaType(); + qRegisterMetaType(); + qRegisterMetaType(); + qRegisterMetaType(); + qRegisterMetaType(); + qRegisterMetaType(); + qRegisterMetaType(); + qRegisterMetaType(); + qRegisterMetaType(); } void Core::Start() { - // Load application config - Config::Load(); + // Load application config + Config::Load(); - // Set locale based on either startup arg, config, or auto-detect - SetStartupLocale(); + // Set locale based on either startup arg, config, or auto-detect + SetStartupLocale(); - // Declare custom types for Qt signal/slot system - DeclareTypesForQt(); + // Declare custom types for Qt signal/slot system + DeclareTypesForQt(); - // Set up node factory/library - NodeFactory::Initialize(); + // Set up node factory/library + NodeFactory::Initialize(); - // Set up color manager's default config - ColorManager::SetUpDefaultConfig(); + // Set up color manager's default config + ColorManager::SetUpDefaultConfig(); - // Initialize task manager - TaskManager::CreateInstance(); + // Initialize task manager + TaskManager::CreateInstance(); - // Initialize ConformManager - ConformManager::CreateInstance(); + // Initialize ConformManager + ConformManager::CreateInstance(); - // Initialize RenderManager - RenderManager::CreateInstance(); + // Initialize RenderManager + RenderManager::CreateInstance(); - // Initialize FrameManager - FrameManager::CreateInstance(); + // Initialize FrameManager + FrameManager::CreateInstance(); - // Initialize project serializers - ProjectSerializer::Initialize(); + // Initialize project serializers + ProjectSerializer::Initialize(); - // - // Start application - // + // + // Start application + // - qInfo() << "Using Qt version:" << qVersion(); + qInfo() << "Using Qt version:" << qVersion(); - switch (core_params_.run_mode()) { - case CoreParams::kRunNormal: - // Start GUI - StartGUI(core_params_.fullscreen()); + switch (core_params_.run_mode()) { + case CoreParams::kRunNormal: + // Start GUI + StartGUI(core_params_.fullscreen()); - // If we have a startup - QMetaObject::invokeMethod(this, "OpenStartupProject", Qt::QueuedConnection); - break; - case CoreParams::kHeadlessExport: - qInfo() << "Headless export is not fully implemented yet"; - break; - case CoreParams::kHeadlessPreCache: - qInfo() << "Headless pre-cache is not fully implemented yet"; - break; - } + // If we have a startup + QMetaObject::invokeMethod(this, "OpenStartupProject", + Qt::QueuedConnection); + break; + case CoreParams::kHeadlessExport: + qInfo() << "Headless export is not fully implemented yet"; + break; + case CoreParams::kHeadlessPreCache: + qInfo() << "Headless pre-cache is not fully implemented yet"; + break; + } - // Manual crash triggering - if (core_params_.crash_on_startup()) { - const int interval = 5000; - qInfo() << "Manual crash was triggered. Application will crash in" << interval << "ms"; - QTimer *crash_timer = new QTimer(this); - crash_timer->setInterval(interval); - connect(crash_timer, &QTimer::timeout, this, []{ - abort(); - }); - crash_timer->start(); - } + // Manual crash triggering + if (core_params_.crash_on_startup()) { + const int interval = 5000; + qInfo() << "Manual crash was triggered. Application will crash in" + << interval << "ms"; + QTimer *crash_timer = new QTimer(this); + crash_timer->setInterval(interval); + connect(crash_timer, &QTimer::timeout, this, [] { abort(); }); + crash_timer->start(); + } } void Core::Stop() { - // Assume all projects have closed gracefully and no auto-recovery is necessary - autorecovered_projects_.clear(); - SaveUnrecoveredList(); + // Assume all projects have closed gracefully and no auto-recovery is necessary + autorecovered_projects_.clear(); + SaveUnrecoveredList(); - // Save Config - Config::Save(); + // Save Config + Config::Save(); - ProjectSerializer::Destroy(); + ProjectSerializer::Destroy(); - ConformManager::DestroyInstance(); + ConformManager::DestroyInstance(); - FrameManager::DestroyInstance(); + FrameManager::DestroyInstance(); - RenderManager::DestroyInstance(); + RenderManager::DestroyInstance(); - MenuShared::DestroyInstance(); + MenuShared::DestroyInstance(); - TaskManager::DestroyInstance(); + TaskManager::DestroyInstance(); - PanelManager::DestroyInstance(); + PanelManager::DestroyInstance(); - AudioManager::DestroyInstance(); + AudioManager::DestroyInstance(); - DiskManager::DestroyInstance(); + DiskManager::DestroyInstance(); - NodeFactory::Destroy(); + NodeFactory::Destroy(); - delete main_window_; - main_window_ = nullptr; + delete main_window_; + main_window_ = nullptr; } MainWindow *Core::main_window() { - return main_window_; + return main_window_; } UndoStack *Core::undo_stack() { - return &undo_stack_; + return &undo_stack_; } -void Core::ImportFiles(const QStringList &urls, Folder* parent) +void Core::ImportFiles(const QStringList &urls, Folder *parent) { - if (urls.isEmpty()) { - QMessageBox::critical(main_window_, tr("Import error"), tr("Nothing to import")); - return; - } + if (urls.isEmpty()) { + QMessageBox::critical(main_window_, tr("Import error"), + tr("Nothing to import")); + return; + } - ProjectImportTask* pim = new ProjectImportTask(parent, urls); + ProjectImportTask *pim = new ProjectImportTask(parent, urls); - if (!pim->GetFileCount()) { - // No files to import - delete pim; - return; - } + if (!pim->GetFileCount()) { + // No files to import + delete pim; + return; + } - TaskDialog* task_dialog = new TaskDialog(pim, tr("Importing..."), main_window()); + TaskDialog *task_dialog = + new TaskDialog(pim, tr("Importing..."), main_window()); - connect(task_dialog, &TaskDialog::TaskSucceeded, this, &Core::ImportTaskComplete); + connect(task_dialog, &TaskDialog::TaskSucceeded, this, + &Core::ImportTaskComplete); - task_dialog->open(); + task_dialog->open(); } const Tool::Item &Core::tool() const { - return tool_; + return tool_; } const Tool::AddableObject &Core::GetSelectedAddableObject() const { - return addable_object_; + return addable_object_; } const QString &Core::GetSelectedTransition() const { - return selected_transition_; + return selected_transition_; } void Core::SetSelectedAddableObject(const Tool::AddableObject &obj) { - addable_object_ = obj; - emit AddableObjectChanged(addable_object_); + addable_object_ = obj; + emit AddableObjectChanged(addable_object_); } void Core::SetSelectedTransitionObject(const QString &obj) { - selected_transition_ = obj; + selected_transition_ = obj; } void Core::ClearOpenRecentList() { - recent_projects_.clear(); - SaveRecentProjectsList(); - emit OpenRecentListChanged(); + recent_projects_.clear(); + SaveRecentProjectsList(); + emit OpenRecentListChanged(); } void Core::CreateNewProject() { - // If we already have an empty/new project, switch to it - if (CloseProject(false)) { - Project *p = new Project(); - p->Initialize(); - AddOpenProject(p); - } + // If we already have an empty/new project, switch to it + if (CloseProject(false)) { + Project *p = new Project(); + p->Initialize(); + AddOpenProject(p); + } } const bool &Core::snapping() const { - return snapping_; + return snapping_; } const QStringList &Core::GetRecentProjects() const { - return recent_projects_; + return recent_projects_; } void Core::SetTool(const Tool::Item &tool) { - tool_ = tool; + tool_ = tool; - emit ToolChanged(tool_); + emit ToolChanged(tool_); } void Core::SetSnapping(const bool &b) { - snapping_ = b; + snapping_ = b; - emit SnappingChanged(snapping_); + emit SnappingChanged(snapping_); } void Core::DialogAboutShow() { - AboutDialog a(false, main_window_); - a.exec(); + AboutDialog a(false, main_window_); + a.exec(); } void Core::DialogImportShow() { - // Open dialog for user to select files - QStringList files = QFileDialog::getOpenFileNames(main_window_, - tr("Import footage...")); + // Open dialog for user to select files + QStringList files = + QFileDialog::getOpenFileNames(main_window_, tr("Import footage...")); - // Check if the user actually selected files to import - if (!files.isEmpty()) { + // Check if the user actually selected files to import + if (!files.isEmpty()) { + // Locate the most recently focused Project panel (assume that's the panel the user wants to import into) + ProjectPanel *active_project_panel = + PanelManager::instance()->MostRecentlyFocused(); + Project *active_project; - // Locate the most recently focused Project panel (assume that's the panel the user wants to import into) - ProjectPanel* active_project_panel = PanelManager::instance()->MostRecentlyFocused(); - Project* active_project; + if (active_project_panel == + nullptr // Check that we found a Project panel + || (active_project = active_project_panel->project()) == + nullptr) { // and that we could find an active Project + QMessageBox::critical(main_window_, tr("Failed to import footage"), + tr("Failed to find active Project panel")); + return; + } - if (active_project_panel == nullptr // Check that we found a Project panel - || (active_project = active_project_panel->project()) == nullptr) { // and that we could find an active Project - QMessageBox::critical(main_window_, tr("Failed to import footage"), tr("Failed to find active Project panel")); - return; - } + // Get the selected folder in this panel + Folder *folder = active_project_panel->GetSelectedFolder(); - // Get the selected folder in this panel - Folder* folder = active_project_panel->GetSelectedFolder(); - - ImportFiles(files, folder); - } + ImportFiles(files, folder); + } } void Core::DialogPreferencesShow() { - PreferencesDialog pd(main_window_); - pd.exec(); + PreferencesDialog pd(main_window_); + pd.exec(); } void Core::DialogProjectPropertiesShow() { - Project *proj = GetActiveProject(); + Project *proj = GetActiveProject(); - if (proj) { - ProjectPropertiesDialog ppd(proj, main_window_); - ppd.exec(); - } else { - QMessageBox::critical(main_window_, - tr("No Active Project"), - tr("No project is currently open to set the properties for"), - QMessageBox::Ok); - } + if (proj) { + ProjectPropertiesDialog ppd(proj, main_window_); + ppd.exec(); + } else { + QMessageBox::critical( + main_window_, tr("No Active Project"), + tr("No project is currently open to set the properties for"), + QMessageBox::Ok); + } } void Core::DialogExportShow() { - if (ViewerOutput* viewer = GetSequenceToExport()) { - OpenExportDialogForViewer(viewer, false); - } + if (ViewerOutput *viewer = GetSequenceToExport()) { + OpenExportDialogForViewer(viewer, false); + } } #ifdef USE_OTIO -bool Core::DialogImportOTIOShow(const QList& sequences) { - Project* active_project = GetActiveProject(); - OTIOPropertiesDialog opd(sequences, active_project); - return opd.exec() == QDialog::Accepted; +bool Core::DialogImportOTIOShow(const QList &sequences) +{ + Project *active_project = GetActiveProject(); + OTIOPropertiesDialog opd(sequences, active_project); + return opd.exec() == QDialog::Accepted; } #endif void Core::CreateNewFolder() { - // Locate the most recently focused Project panel (assume that's the panel the user wants to import into) - ProjectPanel* active_project_panel = PanelManager::instance()->MostRecentlyFocused(); - Project* active_project; + // Locate the most recently focused Project panel (assume that's the panel the user wants to import into) + ProjectPanel *active_project_panel = + PanelManager::instance()->MostRecentlyFocused(); + Project *active_project; - if (active_project_panel == nullptr // Check that we found a Project panel - || (active_project = active_project_panel->project()) == nullptr) { // and that we could find an active Project - QMessageBox::critical(main_window_, tr("Failed to create new folder"), tr("Failed to find active project")); - return; - } + if (active_project_panel == nullptr // Check that we found a Project panel + || (active_project = active_project_panel->project()) == + nullptr) { // and that we could find an active Project + QMessageBox::critical(main_window_, tr("Failed to create new folder"), + tr("Failed to find active project")); + return; + } - // Get the selected folder in this panel - Folder* folder = active_project_panel->GetSelectedFolder(); + // Get the selected folder in this panel + Folder *folder = active_project_panel->GetSelectedFolder(); - // Create new folder - Folder* new_folder = new Folder(); + // Create new folder + Folder *new_folder = new Folder(); - // Set a default name - new_folder->SetLabel(tr("New Folder")); + // Set a default name + new_folder->SetLabel(tr("New Folder")); - // Create an undoable command - MultiUndoCommand* command = new MultiUndoCommand(); + // Create an undoable command + MultiUndoCommand *command = new MultiUndoCommand(); - command->add_child(new NodeAddCommand(active_project, new_folder)); - command->add_child(new FolderAddChild(folder, new_folder)); + command->add_child(new NodeAddCommand(active_project, new_folder)); + command->add_child(new FolderAddChild(folder, new_folder)); - Core::instance()->undo_stack()->push(command, tr("Created New Folder")); + Core::instance()->undo_stack()->push(command, tr("Created New Folder")); - // Trigger an automatic rename so users can enter the folder name - active_project_panel->Edit(new_folder); + // Trigger an automatic rename so users can enter the folder name + active_project_panel->Edit(new_folder); } void Core::CreateNewSequence() { - Project* active_project = GetActiveProject(); + Project *active_project = GetActiveProject(); - if (!active_project) { - QMessageBox::critical(main_window_, tr("Failed to create new sequence"), tr("Failed to find active project")); - return; - } + if (!active_project) { + QMessageBox::critical(main_window_, tr("Failed to create new sequence"), + tr("Failed to find active project")); + return; + } - // Create new sequence - Sequence* new_sequence = CreateNewSequenceForProject(active_project); + // Create new sequence + Sequence *new_sequence = CreateNewSequenceForProject(active_project); - SequenceDialog sd(new_sequence, SequenceDialog::kNew, main_window_); + SequenceDialog sd(new_sequence, SequenceDialog::kNew, main_window_); - // Make sure SequenceDialog doesn't make an undo command for editing the sequence, since we make an undo command for - // adding it later on - sd.SetUndoable(false); + // Make sure SequenceDialog doesn't make an undo command for editing the sequence, since we make an undo command for + // adding it later on + sd.SetUndoable(false); - if (sd.exec() == QDialog::Accepted) { + if (sd.exec() == QDialog::Accepted) { + // Create an undoable command + MultiUndoCommand *command = new MultiUndoCommand(); - // Create an undoable command - MultiUndoCommand* command = new MultiUndoCommand(); + command->add_child(new NodeAddCommand(active_project, new_sequence)); + command->add_child(new FolderAddChild( + GetSelectedFolderInActiveProject(), new_sequence)); + command->add_child(new NodeSetPositionCommand( + new_sequence, new_sequence, Node::Position())); + command->add_child(new OpenSequenceCommand(new_sequence)); - command->add_child(new NodeAddCommand(active_project, new_sequence)); - command->add_child(new FolderAddChild(GetSelectedFolderInActiveProject(), new_sequence)); - command->add_child(new NodeSetPositionCommand(new_sequence, new_sequence, Node::Position())); - command->add_child(new OpenSequenceCommand(new_sequence)); + // Create and connect default nodes to new sequence + new_sequence->add_default_nodes(command); - // Create and connect default nodes to new sequence - new_sequence->add_default_nodes(command); + Core::instance()->undo_stack()->push(command, + tr("Created New Sequence")); - Core::instance()->undo_stack()->push(command, tr("Created New Sequence")); - - } else { - - // If the dialog was accepted, ownership goes to the AddItemCommand. But if we get here, just delete - delete new_sequence; - - } + } else { + // If the dialog was accepted, ownership goes to the AddItemCommand. But if we get here, just delete + delete new_sequence; + } } -void Core::AddOpenProject(Project* p, bool add_to_recents) +void Core::AddOpenProject(Project *p, bool add_to_recents) { - // Ensure project is not open at the moment - if (open_project_ == p) { - return; - } + // Ensure project is not open at the moment + if (open_project_ == p) { + return; + } - // If we currently have an empty project, close it first - if (open_project_) { - CloseProject(false); - } + // If we currently have an empty project, close it first + if (open_project_) { + CloseProject(false); + } - SetActiveProject(p); + SetActiveProject(p); - if (!p->filename().isEmpty() && add_to_recents) { - PushRecentlyOpenedProject(p->filename()); - } + if (!p->filename().isEmpty() && add_to_recents) { + PushRecentlyOpenedProject(p->filename()); + } } bool Core::AddOpenProjectFromTask(Task *task, bool add_to_recents) { - ProjectLoadBaseTask* load_task = static_cast(task); + ProjectLoadBaseTask *load_task = static_cast(task); - if (!load_task->IsCancelled()) { - Project* project = load_task->GetLoadedProject(); + if (!load_task->IsCancelled()) { + Project *project = load_task->GetLoadedProject(); - if (ValidateFootageInLoadedProject(project, project->GetSavedURL())) { - AddOpenProject(project, add_to_recents); - main_window_->LoadLayout(load_task->GetLoadedLayout()); + if (ValidateFootageInLoadedProject(project, project->GetSavedURL())) { + AddOpenProject(project, add_to_recents); + main_window_->LoadLayout(load_task->GetLoadedLayout()); - return true; - } else { - delete project; - CreateNewProject(); - } - } + return true; + } else { + delete project; + CreateNewProject(); + } + } - return false; + return false; } void Core::SetActiveProject(Project *p) { - if (open_project_) { - disconnect(open_project_, &Project::ModifiedChanged, this, &Core::ProjectWasModified); - } + if (open_project_) { + disconnect(open_project_, &Project::ModifiedChanged, this, + &Core::ProjectWasModified); + } - open_project_ = p; - RenderManager::instance()->SetProject(p); - main_window_->SetProject(p); + open_project_ = p; + RenderManager::instance()->SetProject(p); + main_window_->SetProject(p); - if (open_project_) { - connect(open_project_, &Project::ModifiedChanged, this, &Core::ProjectWasModified); - } + if (open_project_) { + connect(open_project_, &Project::ModifiedChanged, this, + &Core::ProjectWasModified); + } } -void Core::ImportTaskComplete(Task* task) +void Core::ImportTaskComplete(Task *task) { - ProjectImportTask* import_task = static_cast(task); + ProjectImportTask *import_task = static_cast(task); - MultiUndoCommand *command = import_task->GetCommand(); + MultiUndoCommand *command = import_task->GetCommand(); - foreach (Footage *f, import_task->GetImportedFootage()) { - // Look for multi-layer images - if (f->GetAudioStreamCount() == 0 && f->GetVideoStreamCount() > 1) { - bool all_stills = true; + foreach (Footage *f, import_task->GetImportedFootage()) { + // Look for multi-layer images + if (f->GetAudioStreamCount() == 0 && f->GetVideoStreamCount() > 1) { + bool all_stills = true; - for (int i=0; iGetVideoStreamCount(); i++) { - const VideoParams &vs = f->GetVideoParams(i); - if (!(vs.video_type() == VideoParams::kVideoTypeStill && vs.enabled() == (i == 0))) { - all_stills = false; - } - } + for (int i = 0; i < f->GetVideoStreamCount(); i++) { + const VideoParams &vs = f->GetVideoParams(i); + if (!(vs.video_type() == VideoParams::kVideoTypeStill && + vs.enabled() == (i == 0))) { + all_stills = false; + } + } - if (all_stills) { - QMessageBox d(main_window()); + if (all_stills) { + QMessageBox d(main_window()); - d.setIcon(QMessageBox::Question); - d.setWindowTitle(tr("Multi-Layer Image")); - d.setText(tr("The file '%1' has multiple layers. Would you like these layers to be " - "separated across multiple tracks or merged into a single image?").arg(f->filename())); + d.setIcon(QMessageBox::Question); + d.setWindowTitle(tr("Multi-Layer Image")); + d.setText( + tr("The file '%1' has multiple layers. Would you like these layers to be " + "separated across multiple tracks or merged into a single image?") + .arg(f->filename())); - auto multi_btn = d.addButton(tr("Multiple Layers"), QMessageBox::YesRole); - auto single_btn = d.addButton(tr("Single Layer"), QMessageBox::NoRole); - auto cancel_btn = d.addButton(QMessageBox::Cancel); + auto multi_btn = + d.addButton(tr("Multiple Layers"), QMessageBox::YesRole); + auto single_btn = + d.addButton(tr("Single Layer"), QMessageBox::NoRole); + auto cancel_btn = d.addButton(QMessageBox::Cancel); - d.exec(); + d.exec(); - if (d.clickedButton() == multi_btn) { - for (int i=0; iGetVideoStreamCount(); i++) { - VideoParams vs = f->GetVideoParams(i); - vs.set_enabled(!vs.enabled()); - f->SetVideoParams(vs, i); - } - } else if (d.clickedButton() == single_btn) { - // Do nothing, footage will already be set up this way - } else if (d.clickedButton() == cancel_btn) { - // Cancel import - delete command; - return; - } - } - } - } + if (d.clickedButton() == multi_btn) { + for (int i = 0; i < f->GetVideoStreamCount(); i++) { + VideoParams vs = f->GetVideoParams(i); + vs.set_enabled(!vs.enabled()); + f->SetVideoParams(vs, i); + } + } else if (d.clickedButton() == single_btn) { + // Do nothing, footage will already be set up this way + } else if (d.clickedButton() == cancel_btn) { + // Cancel import + delete command; + return; + } + } + } + } - if (import_task->HasInvalidFiles()) { - ProjectImportErrorDialog d(import_task->GetInvalidFiles(), main_window_); - d.exec(); - } + if (import_task->HasInvalidFiles()) { + ProjectImportErrorDialog d(import_task->GetInvalidFiles(), + main_window_); + d.exec(); + } - undo_stack_.push(command, tr("Imported %1 File(s)").arg(import_task->GetImportedFootage().size())); + undo_stack_.push( + command, + tr("Imported %1 File(s)").arg(import_task->GetImportedFootage().size())); - main_window_->SelectFootage(import_task->GetImportedFootage()); + main_window_->SelectFootage(import_task->GetImportedFootage()); } -bool Core::ConfirmImageSequence(const QString& filename) +bool Core::ConfirmImageSequence(const QString &filename) { - QMessageBox mb(main_window_); + QMessageBox mb(main_window_); - mb.setIcon(QMessageBox::Question); - mb.setWindowTitle(tr("Possible image sequence detected")); - mb.setText(tr("The file '%1' looks like it might be part of an image " - "sequence. Would you like to import it as such?").arg(filename)); + mb.setIcon(QMessageBox::Question); + mb.setWindowTitle(tr("Possible image sequence detected")); + mb.setText(tr("The file '%1' looks like it might be part of an image " + "sequence. Would you like to import it as such?") + .arg(filename)); - mb.addButton(QMessageBox::Yes); - mb.addButton(QMessageBox::No); + mb.addButton(QMessageBox::Yes); + mb.addButton(QMessageBox::No); - return (mb.exec() == QMessageBox::Yes); + return (mb.exec() == QMessageBox::Yes); } void Core::ProjectWasModified(bool e) { - main_window_->setWindowModified(e); + main_window_->setWindowModified(e); } bool Core::StartHeadlessExport() { - const QString& startup_project = core_params_.startup_project(); + const QString &startup_project = core_params_.startup_project(); - if (startup_project.isEmpty()) { - qCritical().noquote() << tr("You must specify a project file to export"); - return false; - } + if (startup_project.isEmpty()) { + qCritical().noquote() + << tr("You must specify a project file to export"); + return false; + } - if (!QFileInfo::exists(startup_project)) { - qCritical().noquote() << tr("Specified project does not exist"); - return false; - } + if (!QFileInfo::exists(startup_project)) { + qCritical().noquote() << tr("Specified project does not exist"); + return false; + } - // Start a load task and try running it - ProjectLoadTask plm(startup_project); - CLITaskDialog task_dialog(&plm); + // Start a load task and try running it + ProjectLoadTask plm(startup_project); + CLITaskDialog task_dialog(&plm); - /* + /* if (task_dialog.Run()) { std::unique_ptr p = std::unique_ptr(plm.GetLoadedProject()); QVector items = p->get_items_of_type(Item::kSequence); @@ -683,957 +707,1019 @@ bool Core::StartHeadlessExport() } */ - return false; + return false; } void Core::OpenStartupProject() { - const QString& startup_project = core_params_.startup_project(); - bool startup_project_exists = !startup_project.isEmpty() && QFileInfo::exists(startup_project); + const QString &startup_project = core_params_.startup_project(); + bool startup_project_exists = !startup_project.isEmpty() && + QFileInfo::exists(startup_project); - // Load startup project - if (!startup_project_exists && !startup_project.isEmpty()) { - QMessageBox::warning(main_window_, - tr("Failed to open startup file"), - tr("The project \"%1\" doesn't exist. " - "A new project will be started instead.").arg(startup_project), - QMessageBox::Ok); - } + // Load startup project + if (!startup_project_exists && !startup_project.isEmpty()) { + QMessageBox::warning(main_window_, tr("Failed to open startup file"), + tr("The project \"%1\" doesn't exist. " + "A new project will be started instead.") + .arg(startup_project), + QMessageBox::Ok); + } - if (startup_project_exists) { - // If a startup project was set and exists, open it now - OpenProjectInternal(startup_project); - } else { - // If no load project is set, create a new one on open - CreateNewProject(); - } + if (startup_project_exists) { + // If a startup project was set and exists, open it now + OpenProjectInternal(startup_project); + } else { + // If no load project is set, create a new one on open + CreateNewProject(); + } } void Core::AddRecoveryProjectFromTask(Task *task) { - if (AddOpenProjectFromTask(task, false)) { - ProjectLoadBaseTask* load_task = static_cast(task); + if (AddOpenProjectFromTask(task, false)) { + ProjectLoadBaseTask *load_task = + static_cast(task); - Project* project = load_task->GetLoadedProject(); + Project *project = load_task->GetLoadedProject(); - // Clearing the filename will force the user to re-save it somewhere else - project->set_filename(QString()); + // Clearing the filename will force the user to re-save it somewhere else + project->set_filename(QString()); - // Forcing a UUID regeneration will prevent it from saving auto-recoveries in the same place - // the original project did - project->RegenerateUuid(); + // Forcing a UUID regeneration will prevent it from saving auto-recoveries in the same place + // the original project did + project->RegenerateUuid(); - // Setting modified will ensure that the program doesn't close and lose the project without - // prompting the user first - project->set_modified(true); - } + // Setting modified will ensure that the program doesn't close and lose the project without + // prompting the user first + project->set_modified(true); + } } void Core::StartGUI(bool full_screen) { - // Set UI style - StyleManager::Init(); + // Set UI style + StyleManager::Init(); - // Set up shared menus - MenuShared::CreateInstance(); + // Set up shared menus + MenuShared::CreateInstance(); - // Since we're starting GUI mode, create a PanelFocusManager (auto-deletes with QObject) - PanelManager::CreateInstance(); + // Since we're starting GUI mode, create a PanelFocusManager (auto-deletes with QObject) + PanelManager::CreateInstance(); - // Initialize audio service - AudioManager::CreateInstance(); + // Initialize audio service + AudioManager::CreateInstance(); - // Initialize disk service - DiskManager::CreateInstance(); + // Initialize disk service + DiskManager::CreateInstance(); - // Connect the PanelFocusManager to the application's focus change signal - connect(qApp, - &QApplication::focusChanged, - PanelManager::instance(), - &PanelManager::FocusChanged); + // Connect the PanelFocusManager to the application's focus change signal + connect(qApp, &QApplication::focusChanged, PanelManager::instance(), + &PanelManager::FocusChanged); - // Set KDDockWidgets flags - auto &config = KDDockWidgets::Config::self(); - auto flags = config.flags(); - flags |= KDDockWidgets::Config::Flag_TabsHaveCloseButton; - flags |= KDDockWidgets::Config::Flag_HideTitleBarWhenTabsVisible; - flags |= KDDockWidgets::Config::Flag_AlwaysShowTabs; - flags |= KDDockWidgets::Config::Flag_AllowReorderTabs; - config.setFlags(flags); - config.setAbsoluteWidgetMinSize(QSize(1, 1)); + // Set KDDockWidgets flags + auto &config = KDDockWidgets::Config::self(); + auto flags = config.flags(); + flags |= KDDockWidgets::Config::Flag_TabsHaveCloseButton; + flags |= KDDockWidgets::Config::Flag_HideTitleBarWhenTabsVisible; + flags |= KDDockWidgets::Config::Flag_AlwaysShowTabs; + flags |= KDDockWidgets::Config::Flag_AllowReorderTabs; + config.setFlags(flags); + config.setAbsoluteWidgetMinSize(QSize(1, 1)); - // Create main window and open it - main_window_ = new MainWindow(); + // Create main window and open it + main_window_ = new MainWindow(); - if (full_screen) { - main_window_->showFullScreen(); - } else { - main_window_->showMaximized(); - } + if (full_screen) { + main_window_->showFullScreen(); + } else { + main_window_->showMaximized(); + } #ifdef Q_OS_WINDOWS - // Workaround for Qt bug where menus don't appear in full screen mode - // See: https://doc.qt.io/qt-5/windows-issues.html - QWindowsWindowFunctions::setHasBorderInFullScreen(main_window_->windowHandle(), true); + // Workaround for Qt bug where menus don't appear in full screen mode + // See: https://doc.qt.io/qt-5/windows-issues.html + QWindowsWindowFunctions::setHasBorderInFullScreen( + main_window_->windowHandle(), true); #endif - // Start autorecovery timer using the config value as its interval - SetAutorecoveryInterval(OLIVE_CONFIG("AutorecoveryInterval").toInt()); - connect(&autorecovery_timer_, &QTimer::timeout, this, &Core::SaveAutorecovery); - autorecovery_timer_.start(); + // Start autorecovery timer using the config value as its interval + SetAutorecoveryInterval(OLIVE_CONFIG("AutorecoveryInterval").toInt()); + connect(&autorecovery_timer_, &QTimer::timeout, this, + &Core::SaveAutorecovery); + autorecovery_timer_.start(); - // Load recently opened projects list - { - QFile recent_projects_file(GetRecentProjectsFilePath()); - if (recent_projects_file.open(QFile::ReadOnly | QFile::Text)) { - QString r = QString::fromUtf8(recent_projects_file.readAll()); - if (!r.isEmpty()) { - recent_projects_ = r.split('\n'); - } - recent_projects_file.close(); - } + // Load recently opened projects list + { + QFile recent_projects_file(GetRecentProjectsFilePath()); + if (recent_projects_file.open(QFile::ReadOnly | QFile::Text)) { + QString r = QString::fromUtf8(recent_projects_file.readAll()); + if (!r.isEmpty()) { + recent_projects_ = r.split('\n'); + } + recent_projects_file.close(); + } - emit OpenRecentListChanged(); - } + emit OpenRecentListChanged(); + } } -void Core::SaveProjectInternal(const QString& override_filename) +void Core::SaveProjectInternal(const QString &override_filename) { - // Create save manager - Task* psm; + // Create save manager + Task *psm; - if (open_project_->filename().endsWith(QStringLiteral(".otio"), Qt::CaseInsensitive)) { + if (open_project_->filename().endsWith(QStringLiteral(".otio"), + Qt::CaseInsensitive)) { #ifdef USE_OTIO - psm = new SaveOTIOTask(open_project_); + psm = new SaveOTIOTask(open_project_); #else - QMessageBox::critical(main_window_, - tr("Missing OpenTimelineIO Libraries"), - tr("This build was compiled without OpenTimelineIO and therefore " - "cannot open OpenTimelineIO files.")); - return; + QMessageBox::critical( + main_window_, tr("Missing OpenTimelineIO Libraries"), + tr("This build was compiled without OpenTimelineIO and therefore " + "cannot open OpenTimelineIO files.")); + return; #endif - } else { - bool use_compression = !open_project_->filename().endsWith(QStringLiteral(".ovexml"), Qt::CaseInsensitive); - psm = new ProjectSaveTask(open_project_, use_compression); - static_cast(psm)->SetLayout(main_window_->SaveLayout()); + } else { + bool use_compression = !open_project_->filename().endsWith( + QStringLiteral(".ovexml"), Qt::CaseInsensitive); + psm = new ProjectSaveTask(open_project_, use_compression); + static_cast(psm)->SetLayout( + main_window_->SaveLayout()); - if (!override_filename.isEmpty()) { - // Set override filename if provided - static_cast(psm)->SetOverrideFilename(override_filename); - } - } + if (!override_filename.isEmpty()) { + // Set override filename if provided + static_cast(psm)->SetOverrideFilename( + override_filename); + } + } - // We don't use a TaskDialog here because a model save dialog is annoying, particularly when - // saving auto-recoveries that the user can't anticipate. Doing this in the main thread will - // cause a brief (but often unnoticeable) pause in the GUI, which, while not ideal, is not that - // different from what already happened (modal dialog preventing use of the GUI) and in many ways - // less annoying (doesn't disrupt any current actions or pull focus from elsewhere). - // - // Ideally we could do this in a background thread and show progress in the status bar like - // Microsoft Word, but that would be far more complex. If it becomes necessary in the future, - // we will look into an approach like that. - if (psm->Start()) { - if (override_filename.isEmpty()) { - ProjectSaveSucceeded(psm); - } - } + // We don't use a TaskDialog here because a model save dialog is annoying, particularly when + // saving auto-recoveries that the user can't anticipate. Doing this in the main thread will + // cause a brief (but often unnoticeable) pause in the GUI, which, while not ideal, is not that + // different from what already happened (modal dialog preventing use of the GUI) and in many ways + // less annoying (doesn't disrupt any current actions or pull focus from elsewhere). + // + // Ideally we could do this in a background thread and show progress in the status bar like + // Microsoft Word, but that would be far more complex. If it becomes necessary in the future, + // we will look into an approach like that. + if (psm->Start()) { + if (override_filename.isEmpty()) { + ProjectSaveSucceeded(psm); + } + } - psm->deleteLater(); + psm->deleteLater(); } ViewerOutput *Core::GetSequenceToExport() { - // First try the most recently focused time based window - TimeBasedPanel* time_panel = PanelManager::instance()->MostRecentlyFocused(); + // First try the most recently focused time based window + TimeBasedPanel *time_panel = + PanelManager::instance()->MostRecentlyFocused(); - // If that fails try defaulting to the first timeline (i.e. if a project has just been loaded). - if (!time_panel->GetConnectedViewer()) { - // Safe to assume there will always be one timeline. - time_panel = PanelManager::instance()->GetPanelsOfType().first(); - } + // If that fails try defaulting to the first timeline (i.e. if a project has just been loaded). + if (!time_panel->GetConnectedViewer()) { + // Safe to assume there will always be one timeline. + time_panel = + PanelManager::instance()->GetPanelsOfType().first(); + } - if (time_panel && time_panel->GetConnectedViewer()) { - if (time_panel->GetConnectedViewer()->GetLength() == 0) { - QMessageBox::critical(main_window_, - tr("Error"), - tr("This Sequence is empty. There is nothing to export."), - QMessageBox::Ok); - } else { - return time_panel->GetConnectedViewer(); - } - } else { - QMessageBox::critical(main_window_, - tr("Error"), - tr("No valid sequence detected.\n\nMake sure a sequence is loaded and it has a connected Viewer node."), - QMessageBox::Ok); - } + if (time_panel && time_panel->GetConnectedViewer()) { + if (time_panel->GetConnectedViewer()->GetLength() == 0) { + QMessageBox::critical( + main_window_, tr("Error"), + tr("This Sequence is empty. There is nothing to export."), + QMessageBox::Ok); + } else { + return time_panel->GetConnectedViewer(); + } + } else { + QMessageBox::critical( + main_window_, tr("Error"), + tr("No valid sequence detected.\n\nMake sure a sequence is loaded and it has a connected Viewer node."), + QMessageBox::Ok); + } - return nullptr; + return nullptr; } QString Core::GetAutoRecoveryIndexFilename() { - return QDir(QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation)).filePath(QStringLiteral("unrecovered")); + return QDir(QStandardPaths::writableLocation( + QStandardPaths::AppLocalDataLocation)) + .filePath(QStringLiteral("unrecovered")); } void Core::SaveUnrecoveredList() { - QFile autorecovery_index(GetAutoRecoveryIndexFilename()); + QFile autorecovery_index(GetAutoRecoveryIndexFilename()); - if (autorecovered_projects_.isEmpty()) { - // Recovery list is empty, delete file if exists - if (autorecovery_index.exists()) { - autorecovery_index.remove(); - } - } else if (autorecovery_index.open(QFile::WriteOnly)) { - // Overwrite recovery list with current list - QTextStream ts(&autorecovery_index); + if (autorecovered_projects_.isEmpty()) { + // Recovery list is empty, delete file if exists + if (autorecovery_index.exists()) { + autorecovery_index.remove(); + } + } else if (autorecovery_index.open(QFile::WriteOnly)) { + // Overwrite recovery list with current list + QTextStream ts(&autorecovery_index); - bool first = true; - foreach (const QUuid& uuid, autorecovered_projects_) { - if (first) { - first = false; - } else { - ts << QStringLiteral("\n"); - } - ts << uuid.toString(); - } + bool first = true; + foreach (const QUuid &uuid, autorecovered_projects_) { + if (first) { + first = false; + } else { + ts << QStringLiteral("\n"); + } + ts << uuid.toString(); + } - autorecovery_index.close(); - } else { - qWarning() << "Failed to save unrecovered list"; - } + autorecovery_index.close(); + } else { + qWarning() << "Failed to save unrecovered list"; + } } bool Core::RevertProjectInternal(bool by_opening_existing) { - if (open_project_->filename().isEmpty()) { - QMessageBox::critical(main_window_, tr("Revert"), - tr("This project has not yet been saved, therefore there is no last saved state to revert to.")); - } else { - QString msg; + if (open_project_->filename().isEmpty()) { + QMessageBox::critical( + main_window_, tr("Revert"), + tr("This project has not yet been saved, therefore there is no last saved state to revert to.")); + } else { + QString msg; - if (by_opening_existing) { - msg = tr("The project \"%1\" is already open. By re-opening it, the project will revert to " - "its last saved state. Any unsaved changes will be lost. Do you wish to continue?").arg(open_project_->filename()); - } else { - msg = tr("This will revert the project \"%1\" back to its last saved state. " - "All unsaved changes will be lost. Do you wish to continue?").arg(open_project_->name()); - } + if (by_opening_existing) { + msg = + tr("The project \"%1\" is already open. By re-opening it, the project will revert to " + "its last saved state. Any unsaved changes will be lost. Do you wish to continue?") + .arg(open_project_->filename()); + } else { + msg = + tr("This will revert the project \"%1\" back to its last saved state. " + "All unsaved changes will be lost. Do you wish to continue?") + .arg(open_project_->name()); + } - if (QMessageBox::question(main_window_, tr("Revert"), msg, QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Ok) { - // Copy filename because CloseProject is going to delete `p` - QString filename = open_project_->filename(); + if (QMessageBox::question(main_window_, tr("Revert"), msg, + QMessageBox::Ok | QMessageBox::Cancel) == + QMessageBox::Ok) { + // Copy filename because CloseProject is going to delete `p` + QString filename = open_project_->filename(); - // Close project without prompting to save it - CloseProject(false, true); + // Close project without prompting to save it + CloseProject(false, true); - // NOTE: `open_project_` will be deleted now, so don't try accessing it + // NOTE: `open_project_` will be deleted now, so don't try accessing it - // Re-open project at the filename - OpenProjectInternal(filename); + // Re-open project at the filename + OpenProjectInternal(filename); - return true; - } - } + return true; + } + } - return false; + return false; } void Core::SaveRecentProjectsList() { - // Save recently opened projects - QFile recent_projects_file(GetRecentProjectsFilePath()); - if (recent_projects_file.open(QFile::WriteOnly | QFile::Text)) { - recent_projects_file.write(recent_projects_.join('\n').toUtf8()); - recent_projects_file.close(); - } + // Save recently opened projects + QFile recent_projects_file(GetRecentProjectsFilePath()); + if (recent_projects_file.open(QFile::WriteOnly | QFile::Text)) { + recent_projects_file.write(recent_projects_.join('\n').toUtf8()); + recent_projects_file.close(); + } } void Core::SaveAutorecovery() { - if (OLIVE_CONFIG("AutorecoveryEnabled").toBool()) { - if (open_project_ && !open_project_->has_autorecovery_been_saved()) { - QDir project_autorecovery_dir(QDir(FileFunctions::GetAutoRecoveryRoot()).filePath(open_project_->GetUuid().toString())); - if (FileFunctions::DirectoryIsValid(project_autorecovery_dir)) { - QString this_autorecovery_path = project_autorecovery_dir.filePath(QStringLiteral("%1.ove").arg(QString::number(QDateTime::currentSecsSinceEpoch()))); + if (OLIVE_CONFIG("AutorecoveryEnabled").toBool()) { + if (open_project_ && !open_project_->has_autorecovery_been_saved()) { + QDir project_autorecovery_dir( + QDir(FileFunctions::GetAutoRecoveryRoot()) + .filePath(open_project_->GetUuid().toString())); + if (FileFunctions::DirectoryIsValid(project_autorecovery_dir)) { + QString this_autorecovery_path = + project_autorecovery_dir.filePath( + QStringLiteral("%1.ove").arg(QString::number( + QDateTime::currentSecsSinceEpoch()))); - SaveProjectInternal(this_autorecovery_path); + SaveProjectInternal(this_autorecovery_path); - open_project_->set_autorecovery_saved(true); + open_project_->set_autorecovery_saved(true); - // Keep track of projects that where the "newest" save is the recovery project - if (!autorecovered_projects_.contains(open_project_->GetUuid())) { - autorecovered_projects_.append(open_project_->GetUuid()); - } + // Keep track of projects that where the "newest" save is the recovery project + if (!autorecovered_projects_.contains( + open_project_->GetUuid())) { + autorecovered_projects_.append(open_project_->GetUuid()); + } - qDebug() << "Saved auto-recovery to:" << this_autorecovery_path; + qDebug() << "Saved auto-recovery to:" << this_autorecovery_path; - // Write human-readable real name so it's not just a UUID - { - QFile realname_file(project_autorecovery_dir.filePath(QStringLiteral("realname.txt"))); - realname_file.open(QFile::WriteOnly); - realname_file.write(open_project_->pretty_filename().toUtf8()); - realname_file.close(); - } + // Write human-readable real name so it's not just a UUID + { + QFile realname_file(project_autorecovery_dir.filePath( + QStringLiteral("realname.txt"))); + realname_file.open(QFile::WriteOnly); + realname_file.write( + open_project_->pretty_filename().toUtf8()); + realname_file.close(); + } - int64_t max_recoveries_per_file = OLIVE_CONFIG("AutorecoveryMaximum").toLongLong(); + int64_t max_recoveries_per_file = + OLIVE_CONFIG("AutorecoveryMaximum").toLongLong(); - // Since we write an extra file, increment total allowed files by 1 - max_recoveries_per_file++; + // Since we write an extra file, increment total allowed files by 1 + max_recoveries_per_file++; - // Delete old entries - QStringList recovery_files = project_autorecovery_dir.entryList(QDir::Files | QDir::NoDotAndDotDot, QDir::Name); - while (recovery_files.size() > max_recoveries_per_file) { - bool deleted = false; - for (int i=0; i max_recoveries_per_file) { + bool deleted = false; + for (int i = 0; i < recovery_files.size(); i++) { + const QString &f = recovery_files.at(i); - if (f.endsWith(QStringLiteral(".ove"), Qt::CaseInsensitive)) { - QString delete_full_path = project_autorecovery_dir.filePath(f); - qDebug() << "Deleted old recovery:" << delete_full_path; - QFile::remove(delete_full_path); - recovery_files.removeAt(i); - deleted = true; - break; - } - } + if (f.endsWith(QStringLiteral(".ove"), + Qt::CaseInsensitive)) { + QString delete_full_path = + project_autorecovery_dir.filePath(f); + qDebug() + << "Deleted old recovery:" << delete_full_path; + QFile::remove(delete_full_path); + recovery_files.removeAt(i); + deleted = true; + break; + } + } - if (!deleted) { - // For some reason none of the files were deletable. Break so we don't end up in - // an infinite loop. - break; - } - } - } else { - QMessageBox::critical(main_window_, tr("Auto-Recovery Error"), - tr("Failed to save auto-recovery to \"%1\". " - "Olive may not have permission to this directory.") - .arg(project_autorecovery_dir.absolutePath())); - } - } + if (!deleted) { + // For some reason none of the files were deletable. Break so we don't end up in + // an infinite loop. + break; + } + } + } else { + QMessageBox::critical( + main_window_, tr("Auto-Recovery Error"), + tr("Failed to save auto-recovery to \"%1\". " + "Olive may not have permission to this directory.") + .arg(project_autorecovery_dir.absolutePath())); + } + } - // Save index - SaveUnrecoveredList(); - } + // Save index + SaveUnrecoveredList(); + } } -void Core::ProjectSaveSucceeded(Task* task) +void Core::ProjectSaveSucceeded(Task *task) { - Project* p = static_cast(task)->GetProject(); + Project *p = static_cast(task)->GetProject(); - PushRecentlyOpenedProject(p->filename()); + PushRecentlyOpenedProject(p->filename()); - p->set_modified(false); + p->set_modified(false); - autorecovered_projects_.removeOne(p->GetUuid()); - SaveUnrecoveredList(); + autorecovered_projects_.removeOne(p->GetUuid()); + SaveUnrecoveredList(); - ShowStatusBarMessage(tr("Saved to \"%1\" successfully").arg(p->filename())); + ShowStatusBarMessage(tr("Saved to \"%1\" successfully").arg(p->filename())); } -Project* Core::GetActiveProject() const +Project *Core::GetActiveProject() const { - return open_project_; + return open_project_; } Folder *Core::GetSelectedFolderInActiveProject() const { - ProjectPanel* active_project_panel = PanelManager::instance()->MostRecentlyFocused(); + ProjectPanel *active_project_panel = + PanelManager::instance()->MostRecentlyFocused(); - if (active_project_panel) { - return active_project_panel->GetSelectedFolder(); - } else { - return nullptr; - } + if (active_project_panel) { + return active_project_panel->GetSelectedFolder(); + } else { + return nullptr; + } } Timecode::Display Core::GetTimecodeDisplay() const { - return static_cast(OLIVE_CONFIG("TimecodeDisplay").toInt()); + return static_cast( + OLIVE_CONFIG("TimecodeDisplay").toInt()); } void Core::SetTimecodeDisplay(Timecode::Display d) { - OLIVE_CONFIG("TimecodeDisplay") = d; + OLIVE_CONFIG("TimecodeDisplay") = d; - emit TimecodeDisplayChanged(d); + emit TimecodeDisplayChanged(d); } void Core::SetAutorecoveryInterval(int minutes) { - // Convert minutes to milliseconds - autorecovery_timer_.setInterval(minutes * 60000); + // Convert minutes to milliseconds + autorecovery_timer_.setInterval(minutes * 60000); } void Core::CopyStringToClipboard(const QString &s) { - QGuiApplication::clipboard()->setText(s); + QGuiApplication::clipboard()->setText(s); } QString Core::PasteStringFromClipboard() { - return QGuiApplication::clipboard()->text(); + return QGuiApplication::clipboard()->text(); } QString Core::GetProjectFilter(bool include_any_filter) { - static const QVector< QPair > FILTERS = { - // Standard compressed Olive project - {tr("Olive Project"), QStringLiteral("ove")}, + static const QVector> FILTERS = { + // Standard compressed Olive project + { tr("Olive Project"), QStringLiteral("ove") }, - // Uncompressed XML Olive project - {tr("Olive Project (Uncompressed XML)"), QStringLiteral("ovexml")}, + // Uncompressed XML Olive project + { tr("Olive Project (Uncompressed XML)"), QStringLiteral("ovexml") }, - // OpenTimelineIO project, if available + // OpenTimelineIO project, if available #ifdef USE_OTIO - {tr("OpenTimelineIO"), QStringLiteral("otio")} + { tr("OpenTimelineIO"), QStringLiteral("otio") } #endif - }; + }; - QStringList filters; - filters.reserve(FILTERS.size() + 1); + QStringList filters; + filters.reserve(FILTERS.size() + 1); - if (include_any_filter) { - QStringList combined; - for (auto it=FILTERS.cbegin(); it!=FILTERS.cend(); it++) { - combined.append(QStringLiteral("*.%1").arg(it->second)); - } - filters.append(QStringLiteral("%1 (%2)").arg(tr("All Supported Projects"), combined.join(' '))); - } + if (include_any_filter) { + QStringList combined; + for (auto it = FILTERS.cbegin(); it != FILTERS.cend(); it++) { + combined.append(QStringLiteral("*.%1").arg(it->second)); + } + filters.append(QStringLiteral("%1 (%2)").arg( + tr("All Supported Projects"), combined.join(' '))); + } - for (auto it=FILTERS.cbegin(); it!=FILTERS.cend(); it++) { - filters.append(QStringLiteral("%1 (*.%2)").arg(it->first, it->second)); - } + for (auto it = FILTERS.cbegin(); it != FILTERS.cend(); it++) { + filters.append(QStringLiteral("%1 (*.%2)").arg(it->first, it->second)); + } - return filters.join(QStringLiteral(";;")); + return filters.join(QStringLiteral(";;")); } QString Core::GetRecentProjectsFilePath() { - return QDir(FileFunctions::GetConfigurationLocation()).filePath(QStringLiteral("recent")); + return QDir(FileFunctions::GetConfigurationLocation()) + .filePath(QStringLiteral("recent")); } void Core::SetStartupLocale() { - // Set language - if (!core_params_.startup_language().isEmpty()) { - if (translator_->load(core_params_.startup_language()) && QApplication::installTranslator(translator_)) { - return; - } else { - qWarning() << "Failed to load translation file. Falling back to defaults."; - } - } + // Set language + if (!core_params_.startup_language().isEmpty()) { + if (translator_->load(core_params_.startup_language()) && + QApplication::installTranslator(translator_)) { + return; + } else { + qWarning() + << "Failed to load translation file. Falling back to defaults."; + } + } - QString use_locale = OLIVE_CONFIG("Language").toString(); + QString use_locale = OLIVE_CONFIG("Language").toString(); - if (use_locale.isEmpty()) { - // No configured locale, auto-detect the system's locale - use_locale = QLocale::system().name(); - } + if (use_locale.isEmpty()) { + // No configured locale, auto-detect the system's locale + use_locale = QLocale::system().name(); + } - if (!SetLanguage(use_locale)) { - qWarning() << "Trying to use locale" << use_locale << "but couldn't find a translation for it"; - } + if (!SetLanguage(use_locale)) { + qWarning() << "Trying to use locale" << use_locale + << "but couldn't find a translation for it"; + } } bool Core::SaveProject() { - if (open_project_->filename().isEmpty()) { - return SaveProjectAs(); - } else { - SaveProjectInternal(); + if (open_project_->filename().isEmpty()) { + return SaveProjectAs(); + } else { + SaveProjectInternal(); - return true; - } + return true; + } } void Core::ShowStatusBarMessage(const QString &s, int timeout) { - main_window_->statusBar()->showMessage(s, timeout); + main_window_->statusBar()->showMessage(s, timeout); } void Core::ClearStatusBarMessage() { - main_window_->statusBar()->clearMessage(); + main_window_->statusBar()->clearMessage(); } void Core::OpenRecoveryProject(const QString &filename) { - OpenProjectInternal(filename, true); + OpenProjectInternal(filename, true); } void Core::OpenNodeInViewer(ViewerOutput *viewer) { - main_window_->OpenNodeInViewer(viewer); + main_window_->OpenNodeInViewer(viewer); } -void Core::OpenExportDialogForViewer(ViewerOutput *viewer, bool start_still_image) +void Core::OpenExportDialogForViewer(ViewerOutput *viewer, + bool start_still_image) { - ExportDialog* ed = new ExportDialog(viewer, start_still_image, main_window_); - connect(ed, &ExportDialog::finished, ed, &ExportDialog::deleteLater); - ed->open(); - connect(ed, &ExportDialog::RequestImportFile, this, &Core::ImportSingleFile); + ExportDialog *ed = + new ExportDialog(viewer, start_still_image, main_window_); + connect(ed, &ExportDialog::finished, ed, &ExportDialog::deleteLater); + ed->open(); + connect(ed, &ExportDialog::RequestImportFile, this, + &Core::ImportSingleFile); } void Core::CheckForAutoRecoveries() { - QFile autorecovery_index(GetAutoRecoveryIndexFilename()); - if (autorecovery_index.exists()) { - // Uh-oh, we have auto-recoveries to prompt - if (autorecovery_index.open(QFile::ReadOnly)) { - QStringList recovery_filenames = QString::fromUtf8(autorecovery_index.readAll()).split('\n'); + QFile autorecovery_index(GetAutoRecoveryIndexFilename()); + if (autorecovery_index.exists()) { + // Uh-oh, we have auto-recoveries to prompt + if (autorecovery_index.open(QFile::ReadOnly)) { + QStringList recovery_filenames = + QString::fromUtf8(autorecovery_index.readAll()).split('\n'); - AutoRecoveryDialog ard(tr("The following projects had unsaved changes when Olive " - "forcefully quit. Would you like to load them?"), - recovery_filenames, true, main_window_); - ard.exec(); + AutoRecoveryDialog ard( + tr("The following projects had unsaved changes when Olive " + "forcefully quit. Would you like to load them?"), + recovery_filenames, true, main_window_); + ard.exec(); - autorecovery_index.close(); + autorecovery_index.close(); - // Delete recovery index since we don't need it anymore - QFile::remove(GetAutoRecoveryIndexFilename()); - } else { - QMessageBox::critical(main_window_, tr("Auto-Recovery Error"), - tr("Found auto-recoveries but failed to load the auto-recovery index. " - "Auto-recover projects will have to be opened manually.\n\n" - "Your recoverable projects are still available at: %1").arg(FileFunctions::GetAutoRecoveryRoot())); - } - } + // Delete recovery index since we don't need it anymore + QFile::remove(GetAutoRecoveryIndexFilename()); + } else { + QMessageBox::critical( + main_window_, tr("Auto-Recovery Error"), + tr("Found auto-recoveries but failed to load the auto-recovery index. " + "Auto-recover projects will have to be opened manually.\n\n" + "Your recoverable projects are still available at: %1") + .arg(FileFunctions::GetAutoRecoveryRoot())); + } + } } void Core::BrowseAutoRecoveries() { - // List all auto-recovery entries - AutoRecoveryDialog ard(tr("The following project versions have been auto-saved:"), - QDir(FileFunctions::GetAutoRecoveryRoot()).entryList(QDir::Dirs | QDir::NoDotAndDotDot), - false, main_window_); - ard.exec(); + // List all auto-recovery entries + AutoRecoveryDialog ard( + tr("The following project versions have been auto-saved:"), + QDir(FileFunctions::GetAutoRecoveryRoot()) + .entryList(QDir::Dirs | QDir::NoDotAndDotDot), + false, main_window_); + ard.exec(); } void Core::RequestPixelSamplingInViewers(bool e) { - if (e) { - if (pixel_sampling_users_ == 0) { - // Signal to start pixel sampling - emit ColorPickerEnabled(true); - } + if (e) { + if (pixel_sampling_users_ == 0) { + // Signal to start pixel sampling + emit ColorPickerEnabled(true); + } - pixel_sampling_users_++; - } else { - pixel_sampling_users_--; + pixel_sampling_users_++; + } else { + pixel_sampling_users_--; - if (pixel_sampling_users_ == 0) { - // Signal to end pixel sampling - emit ColorPickerEnabled(false); - } - } + if (pixel_sampling_users_ == 0) { + // Signal to end pixel sampling + emit ColorPickerEnabled(false); + } + } } void Core::WarnCacheFull() { - if (!shown_cache_full_warning_ && main_window_) { - shown_cache_full_warning_ = true; + if (!shown_cache_full_warning_ && main_window_) { + shown_cache_full_warning_ = true; - QMessageBox::warning(main_window_, tr("Disk Cache Full"), - tr("The disk cache is currently full and Olive is having to delete old " - "frames to keep it within the limits set in the Disk preferences. This " - "will result in SIGNIFICANTLY reduced cache performance.\n\n" - "To remedy this, please do one of the following:\n\n" - "1. Manually clear the disk cache in Disk preferences.\n" - "2. Increase the maximum disk cache size in Disk preferences.\n" - "3. Reduce usage of the disk cache (e.g. disable auto-cache or only cache specific sections of your sequence).")); - } + QMessageBox::warning( + main_window_, tr("Disk Cache Full"), + tr("The disk cache is currently full and Olive is having to delete old " + "frames to keep it within the limits set in the Disk preferences. This " + "will result in SIGNIFICANTLY reduced cache performance.\n\n" + "To remedy this, please do one of the following:\n\n" + "1. Manually clear the disk cache in Disk preferences.\n" + "2. Increase the maximum disk cache size in Disk preferences.\n" + "3. Reduce usage of the disk cache (e.g. disable auto-cache or only cache specific sections of your sequence).")); + } } bool Core::SaveProjectAs() { - QFileDialog fd(main_window_, tr("Save Project As")); + QFileDialog fd(main_window_, tr("Save Project As")); - fd.setAcceptMode(QFileDialog::AcceptSave); - fd.setNameFilter(GetProjectFilter(false)); + fd.setAcceptMode(QFileDialog::AcceptSave); + fd.setNameFilter(GetProjectFilter(false)); - if (fd.exec() == QDialog::Accepted) { - QString fn = fd.selectedFiles().first(); + if (fd.exec() == QDialog::Accepted) { + QString fn = fd.selectedFiles().first(); - // Somewhat hacky method of extracting the extension from the name filter - const QString& name_filter = fd.selectedNameFilter(); - int ext_index = name_filter.indexOf(QStringLiteral("(*.")) + 3; - QString extension = name_filter.mid(ext_index, name_filter.size() - ext_index - 1); + // Somewhat hacky method of extracting the extension from the name filter + const QString &name_filter = fd.selectedNameFilter(); + int ext_index = name_filter.indexOf(QStringLiteral("(*.")) + 3; + QString extension = + name_filter.mid(ext_index, name_filter.size() - ext_index - 1); - fn = FileFunctions::EnsureFilenameExtension(fn, extension); + fn = FileFunctions::EnsureFilenameExtension(fn, extension); - open_project_->set_filename(fn); + open_project_->set_filename(fn); - SaveProjectInternal(); + SaveProjectInternal(); - return true; - } + return true; + } - return false; + return false; } void Core::RevertProject() { - RevertProjectInternal(false); + RevertProjectInternal(false); } -void Core::PushRecentlyOpenedProject(const QString& s) +void Core::PushRecentlyOpenedProject(const QString &s) { - if (s.isEmpty()) { - return; - } + if (s.isEmpty()) { + return; + } - int existing_index = recent_projects_.indexOf(s); + int existing_index = recent_projects_.indexOf(s); - if (existing_index >= 0) { - recent_projects_.move(existing_index, 0); - } else { - recent_projects_.prepend(s); + if (existing_index >= 0) { + recent_projects_.move(existing_index, 0); + } else { + recent_projects_.prepend(s); - const int kMaximumRecentProjects = 10; - while (recent_projects_.size() > kMaximumRecentProjects) { - recent_projects_.removeLast(); - } - } + const int kMaximumRecentProjects = 10; + while (recent_projects_.size() > kMaximumRecentProjects) { + recent_projects_.removeLast(); + } + } - SaveRecentProjectsList(); + SaveRecentProjectsList(); - emit OpenRecentListChanged(); + emit OpenRecentListChanged(); } void Core::OpenProjectInternal(const QString &filename, bool recovery_project) { - if (open_project_) { - // Comparing QFileInfos will handle case insensitivity and both slash directions on platforms - // where this is necessary (not naming any names *cough* Windows) - if (QFileInfo(open_project_->filename()) == QFileInfo(filename)) { - // This project is already open - bool reverted = RevertProjectInternal(true); + if (open_project_) { + // Comparing QFileInfos will handle case insensitivity and both slash directions on platforms + // where this is necessary (not naming any names *cough* Windows) + if (QFileInfo(open_project_->filename()) == QFileInfo(filename)) { + // This project is already open + bool reverted = RevertProjectInternal(true); - if (!reverted) { - // Calling this will focus attention to the project that the user just tried to re-open - AddOpenProject(open_project_); - } + if (!reverted) { + // Calling this will focus attention to the project that the user just tried to re-open + AddOpenProject(open_project_); + } - // Don't do anything else - return; - } - } + // Don't do anything else + return; + } + } - Task* load_task; + Task *load_task; - if (filename.endsWith(QStringLiteral(".otio"), Qt::CaseInsensitive)) { - // Load OpenTimelineIO project + if (filename.endsWith(QStringLiteral(".otio"), Qt::CaseInsensitive)) { + // Load OpenTimelineIO project #ifdef USE_OTIO - load_task = new LoadOTIOTask(filename); + load_task = new LoadOTIOTask(filename); #else - QMessageBox::critical(main_window_, - tr("Missing OpenTimelineIO Libraries"), - tr("This build was compiled without OpenTimelineIO and therefore " - "cannot open OpenTimelineIO files.")); - return; + QMessageBox::critical( + main_window_, tr("Missing OpenTimelineIO Libraries"), + tr("This build was compiled without OpenTimelineIO and therefore " + "cannot open OpenTimelineIO files.")); + return; #endif - } else { - // Fallback to regular OVE project - load_task = new ProjectLoadTask(filename); - } + } else { + // Fallback to regular OVE project + load_task = new ProjectLoadTask(filename); + } - TaskDialog* task_dialog = new TaskDialog(load_task, tr("Load Project"), main_window()); + TaskDialog *task_dialog = + new TaskDialog(load_task, tr("Load Project"), main_window()); - if (recovery_project) { - connect(task_dialog, &TaskDialog::TaskSucceeded, this, &Core::AddRecoveryProjectFromTask); - } else { - connect(task_dialog, &TaskDialog::TaskSucceeded, this, &Core::AddOpenProjectFromTaskAndAddToRecents); - } + if (recovery_project) { + connect(task_dialog, &TaskDialog::TaskSucceeded, this, + &Core::AddRecoveryProjectFromTask); + } else { + connect(task_dialog, &TaskDialog::TaskSucceeded, this, + &Core::AddOpenProjectFromTaskAndAddToRecents); + } - task_dialog->open(); + task_dialog->open(); } void Core::ImportSingleFile(const QString &f) { - if (Project *p = GetActiveProject()) { - ImportFiles({f}, p->root()); - } + if (Project *p = GetActiveProject()) { + ImportFiles({ f }, p->root()); + } } int Core::CountFilesInFileList(const QFileInfoList &filenames) { - int file_count = 0; + int file_count = 0; - foreach (const QFileInfo& f, filenames) { - // For some reason QDir::NoDotAndDotDot doesn't work with entryInfoList, so we have to check manually - if (f.fileName() == "." || f.fileName() == "..") { - continue; - } else if (f.isDir()) { - QFileInfoList info_list = QDir(f.absoluteFilePath()).entryInfoList(); + foreach (const QFileInfo &f, filenames) { + // For some reason QDir::NoDotAndDotDot doesn't work with entryInfoList, so we have to check manually + if (f.fileName() == "." || f.fileName() == "..") { + continue; + } else if (f.isDir()) { + QFileInfoList info_list = + QDir(f.absoluteFilePath()).entryInfoList(); - file_count += CountFilesInFileList(info_list); - } else { - file_count++; - } - } + file_count += CountFilesInFileList(info_list); + } else { + file_count++; + } + } - return file_count; + return file_count; } bool Core::LabelNodes(const QVector &nodes, MultiUndoCommand *parent) { - if (nodes.isEmpty()) { - return false; - } + if (nodes.isEmpty()) { + return false; + } - bool ok; + bool ok; - QString start_label = nodes.first()->GetLabel(); + QString start_label = nodes.first()->GetLabel(); - for (int i=1; iGetLabel() != start_label) { - // Not all the nodes share the same name, so we'll start with a blank one - start_label.clear(); - break; - } - } + for (int i = 1; i < nodes.size(); i++) { + if (nodes.at(i)->GetLabel() != start_label) { + // Not all the nodes share the same name, so we'll start with a blank one + start_label.clear(); + break; + } + } - QString s = QInputDialog::getText(main_window_, - tr("Label Node"), - tr("Set node label"), - QLineEdit::Normal, - start_label, - &ok); + QString s = QInputDialog::getText(main_window_, tr("Label Node"), + tr("Set node label"), QLineEdit::Normal, + start_label, &ok); - if (ok) { - NodeRenameCommand* rename_command = new NodeRenameCommand(); + if (ok) { + NodeRenameCommand *rename_command = new NodeRenameCommand(); - foreach (Node* n, nodes) { - rename_command->AddNode(n, s); - } + foreach (Node *n, nodes) { + rename_command->AddNode(n, s); + } - if (parent) { - parent->add_child(rename_command); - } else { - undo_stack_.push(rename_command, tr("Renamed %1 Node(s)").arg(nodes.size())); - } + if (parent) { + parent->add_child(rename_command); + } else { + undo_stack_.push(rename_command, + tr("Renamed %1 Node(s)").arg(nodes.size())); + } - return true; - } + return true; + } - return false; + return false; } -Sequence *Core::CreateNewSequenceForProject(const QString &format, Project* project) +Sequence *Core::CreateNewSequenceForProject(const QString &format, + Project *project) { - Sequence* new_sequence = new Sequence(); + Sequence *new_sequence = new Sequence(); - // Get default name for this sequence (in the format "Sequence N", the first that doesn't exist) - int sequence_number = 1; - QString sequence_name; - do { - sequence_name = format.arg(sequence_number); - sequence_number++; - } while (project->root()->ChildExistsWithName(sequence_name)); - new_sequence->SetLabel(sequence_name); + // Get default name for this sequence (in the format "Sequence N", the first that doesn't exist) + int sequence_number = 1; + QString sequence_name; + do { + sequence_name = format.arg(sequence_number); + sequence_number++; + } while (project->root()->ChildExistsWithName(sequence_name)); + new_sequence->SetLabel(sequence_name); - return new_sequence; + return new_sequence; } void Core::OpenProjectFromRecentList(int index) { - const QString& open_fn = recent_projects_.at(index); + const QString &open_fn = recent_projects_.at(index); - if (QFileInfo::exists(open_fn)) { - OpenProjectInternal(open_fn); - } else if (QMessageBox::information(main_window(), - tr("Cannot open recent project"), - tr("The project \"%1\" doesn't exist. Would you like to remove this file from the recent list?").arg(open_fn), - QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) { - recent_projects_.removeAt(index); + if (QFileInfo::exists(open_fn)) { + OpenProjectInternal(open_fn); + } else if ( + QMessageBox::information( + main_window(), tr("Cannot open recent project"), + tr("The project \"%1\" doesn't exist. Would you like to remove this file from the recent list?") + .arg(open_fn), + QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) { + recent_projects_.removeAt(index); - SaveRecentProjectsList(); + SaveRecentProjectsList(); - emit OpenRecentListChanged(); - } + emit OpenRecentListChanged(); + } } bool Core::CloseProject(bool auto_open_new, bool ignore_modified) { - if (open_project_) { - if (open_project_->is_modified() && !ignore_modified) { - QMessageBox mb(main_window_); + if (open_project_) { + if (open_project_->is_modified() && !ignore_modified) { + QMessageBox mb(main_window_); - mb.setWindowModality(Qt::WindowModal); - mb.setIcon(QMessageBox::Question); - mb.setWindowTitle(tr("Unsaved Changes")); - mb.setText(tr("The project '%1' has unsaved changes. Would you like to save them?") - .arg(open_project_->name())); + mb.setWindowModality(Qt::WindowModal); + mb.setIcon(QMessageBox::Question); + mb.setWindowTitle(tr("Unsaved Changes")); + mb.setText( + tr("The project '%1' has unsaved changes. Would you like to save them?") + .arg(open_project_->name())); - QPushButton* yes_btn = mb.addButton(tr("Save"), QMessageBox::YesRole); + QPushButton *yes_btn = + mb.addButton(tr("Save"), QMessageBox::YesRole); - mb.addButton(tr("Don't Save"), QMessageBox::NoRole); + mb.addButton(tr("Don't Save"), QMessageBox::NoRole); - QPushButton* cancel_btn = mb.addButton(QMessageBox::Cancel); + QPushButton *cancel_btn = mb.addButton(QMessageBox::Cancel); - mb.exec(); + mb.exec(); - if (mb.clickedButton() == cancel_btn) { - // Stop closing projects if the user clicked cancel - return false; - } + if (mb.clickedButton() == cancel_btn) { + // Stop closing projects if the user clicked cancel + return false; + } - if (mb.clickedButton() == yes_btn && !SaveProject()) { - // The save failed, stop closing projects - return false; - } - } + if (mb.clickedButton() == yes_btn && !SaveProject()) { + // The save failed, stop closing projects + return false; + } + } - // For safety, the undo stack is cleared so no commands try to affect a freed project - undo_stack_.clear(); + // For safety, the undo stack is cleared so no commands try to affect a freed project + undo_stack_.clear(); - Project *tmp = open_project_; - SetActiveProject(nullptr); - delete tmp; - } + Project *tmp = open_project_; + SetActiveProject(nullptr); + delete tmp; + } - // Ensure a project is always active - if (auto_open_new) { - CreateNewProject(); - } + // Ensure a project is always active + if (auto_open_new) { + CreateNewProject(); + } - return true; + return true; } void Core::CacheActiveSequence(bool in_out_only) { - TimeBasedPanel* p = PanelManager::instance()->MostRecentlyFocused(); + TimeBasedPanel *p = + PanelManager::instance()->MostRecentlyFocused(); - if (p && p->GetConnectedViewer()) { - // Hacky but works for now + if (p && p->GetConnectedViewer()) { + // Hacky but works for now - // Find Viewer attached to this TimeBasedPanel - QList all_viewers = PanelManager::instance()->GetPanelsOfType(); + // Find Viewer attached to this TimeBasedPanel + QList all_viewers = + PanelManager::instance()->GetPanelsOfType(); - ViewerPanel* found_panel = nullptr; + ViewerPanel *found_panel = nullptr; - foreach (ViewerPanel* viewer, all_viewers) { - if (viewer->GetConnectedViewer() == p->GetConnectedViewer()) { - found_panel = viewer; - break; - } - } + foreach (ViewerPanel *viewer, all_viewers) { + if (viewer->GetConnectedViewer() == p->GetConnectedViewer()) { + found_panel = viewer; + break; + } + } - if (found_panel) { - if (in_out_only) { - found_panel->CacheSequenceInOut(); - } else { - found_panel->CacheEntireSequence(); - } - } else { - QMessageBox::critical(main_window_, - tr("Failed to cache sequence"), - tr("No active viewer found with this sequence."), - QMessageBox::Ok); - } - } + if (found_panel) { + if (in_out_only) { + found_panel->CacheSequenceInOut(); + } else { + found_panel->CacheEntireSequence(); + } + } else { + QMessageBox::critical( + main_window_, tr("Failed to cache sequence"), + tr("No active viewer found with this sequence."), + QMessageBox::Ok); + } + } } QString StripWindowsDriveLetter(QString s) { - // HACK: On Windows, absolute paths are saved with a drive letter (e.g. "C:\video.mp4"). Below, - // we use Qt's relative path system to resolve when an entire project may be in a different - // folder, but the files are all in the same place relatively to the project. Unfortunately, - // Qt chooses not to understand paths from Windows on non-Windows platforms, which causes - // this to break when a project is moving from Windows to non-Windows. To resolve that, if - // we're on a non-Windows platform and we detect a Windows path (i.e. a path with a drive - // letter at the start), we strip it off. We also convert any back-slashes to forward-slashes - // because on Windows they are interchangeable and on non-Windows they are not. + // HACK: On Windows, absolute paths are saved with a drive letter (e.g. "C:\video.mp4"). Below, + // we use Qt's relative path system to resolve when an entire project may be in a different + // folder, but the files are all in the same place relatively to the project. Unfortunately, + // Qt chooses not to understand paths from Windows on non-Windows platforms, which causes + // this to break when a project is moving from Windows to non-Windows. To resolve that, if + // we're on a non-Windows platform and we detect a Windows path (i.e. a path with a drive + // letter at the start), we strip it off. We also convert any back-slashes to forward-slashes + // because on Windows they are interchangeable and on non-Windows they are not. #ifndef Q_OS_WINDOWS - if (s.size() >= 2) { - if (s.at(0).isLetter() && s.at(1) == ':') { - s = s.mid(2); - s.replace('\\', '/'); - } - } + if (s.size() >= 2) { + if (s.at(0).isLetter() && s.at(1) == ':') { + s = s.mid(2); + s.replace('\\', '/'); + } + } #endif - return s; + return s; } -bool Core::ValidateFootageInLoadedProject(Project* project, const QString& project_saved_url) +bool Core::ValidateFootageInLoadedProject(Project *project, + const QString &project_saved_url) { - QVector footage_we_couldnt_validate; + QVector footage_we_couldnt_validate; - for (Node *n : project->nodes()) { - if (Footage *footage = dynamic_cast(n)) { - QString footage_fn = StripWindowsDriveLetter(footage->filename()); - QString project_fn = StripWindowsDriveLetter(project_saved_url); + for (Node *n : project->nodes()) { + if (Footage *footage = dynamic_cast(n)) { + QString footage_fn = StripWindowsDriveLetter(footage->filename()); + QString project_fn = StripWindowsDriveLetter(project_saved_url); - if (!QFileInfo::exists(footage_fn) && !project_saved_url.isEmpty()) { - // If the footage doesn't exist, it might have moved with the project - const QString& project_current_url = project->filename(); + if (!QFileInfo::exists(footage_fn) && + !project_saved_url.isEmpty()) { + // If the footage doesn't exist, it might have moved with the project + const QString &project_current_url = project->filename(); - if (project_current_url != project_fn) { - // Project has definitely moved, try to resolve relative paths - QDir saved_dir(QFileInfo(project_fn).dir()); - QDir true_dir(QFileInfo(project_current_url).dir()); + if (project_current_url != project_fn) { + // Project has definitely moved, try to resolve relative paths + QDir saved_dir(QFileInfo(project_fn).dir()); + QDir true_dir(QFileInfo(project_current_url).dir()); - QString relative_filename = saved_dir.relativeFilePath(footage_fn); - QString transformed_abs_filename = true_dir.filePath(relative_filename); + QString relative_filename = + saved_dir.relativeFilePath(footage_fn); + QString transformed_abs_filename = + true_dir.filePath(relative_filename); - if (QFileInfo::exists(transformed_abs_filename)) { - // Use this file instead - qInfo() << "Resolved" << footage_fn << "relatively to" << transformed_abs_filename; - footage->set_filename(transformed_abs_filename); - } - } - } + if (QFileInfo::exists(transformed_abs_filename)) { + // Use this file instead + qInfo() << "Resolved" << footage_fn << "relatively to" + << transformed_abs_filename; + footage->set_filename(transformed_abs_filename); + } + } + } - if (QFileInfo::exists(footage->filename())) { - // Assume valid - footage->SetValid(); - } else { - footage_we_couldnt_validate.append(footage); - } - } - } + if (QFileInfo::exists(footage->filename())) { + // Assume valid + footage->SetValid(); + } else { + footage_we_couldnt_validate.append(footage); + } + } + } - if (!footage_we_couldnt_validate.isEmpty()) { - FootageRelinkDialog frd(footage_we_couldnt_validate, main_window_); - if (frd.exec() == QDialog::Rejected) { - return false; - } - } + if (!footage_we_couldnt_validate.isEmpty()) { + FootageRelinkDialog frd(footage_we_couldnt_validate, main_window_); + if (frd.exec() == QDialog::Rejected) { + return false; + } + } - return true; + return true; } bool Core::SetLanguage(const QString &locale) { - QApplication::removeTranslator(translator_); + QApplication::removeTranslator(translator_); - QString resource_path = QStringLiteral(":/ts/%1").arg(locale); - if (translator_->load(resource_path) && QApplication::installTranslator(translator_)) { - return true; - } + QString resource_path = QStringLiteral(":/ts/%1").arg(locale); + if (translator_->load(resource_path) && + QApplication::installTranslator(translator_)) { + return true; + } - return false; + return false; } void Core::OpenProject() { - QString file = QFileDialog::getOpenFileName(main_window_, - tr("Open Project"), - QString(), - GetProjectFilter(true)); + QString file = QFileDialog::getOpenFileName( + main_window_, tr("Open Project"), QString(), GetProjectFilter(true)); - if (!file.isEmpty()) { - OpenProjectInternal(file); - } + if (!file.isEmpty()) { + OpenProjectInternal(file); + } } -Core::CoreParams::CoreParams() : - mode_(kRunNormal), - run_fullscreen_(false), - crash_(false) +Core::CoreParams::CoreParams() + : mode_(kRunNormal) + , run_fullscreen_(false) + , crash_(false) { } diff --git a/app/core.h b/app/core.h index 10018e7ba..55c77766b 100644 --- a/app/core.h +++ b/app/core.h @@ -35,7 +35,8 @@ #include "undo/undostack.h" #include "widget/projectexplorer/projectviewmodel.h" -namespace olive { +namespace olive +{ class MainWindow; @@ -48,132 +49,125 @@ class MainWindow; * The "public slots" are usually user-triggered actions and can be connected to UI elements (e.g. creating a folder, * opening the import dialog, etc.) */ -class Core : public QObject -{ - Q_OBJECT +class Core : public QObject { + Q_OBJECT public: - class CoreParams - { - public: - CoreParams(); + class CoreParams { + public: + CoreParams(); - enum RunMode { - kRunNormal, - kHeadlessExport, - kHeadlessPreCache - }; + enum RunMode { kRunNormal, kHeadlessExport, kHeadlessPreCache }; - bool fullscreen() const - { - return run_fullscreen_; - } + bool fullscreen() const + { + return run_fullscreen_; + } - void set_fullscreen(bool e) - { - run_fullscreen_ = e; - } + void set_fullscreen(bool e) + { + run_fullscreen_ = e; + } - RunMode run_mode() const - { - return mode_; - } + RunMode run_mode() const + { + return mode_; + } - void set_run_mode(RunMode m) - { - mode_ = m; - } + void set_run_mode(RunMode m) + { + mode_ = m; + } - const QString startup_project() const - { - return startup_project_; - } + const QString startup_project() const + { + return startup_project_; + } - void set_startup_project(const QString& p) - { - startup_project_ = p; - } + void set_startup_project(const QString &p) + { + startup_project_ = p; + } - const QString& startup_language() const - { - return startup_language_; - } + const QString &startup_language() const + { + return startup_language_; + } - void set_startup_language(const QString& s) - { - startup_language_ = s; - } + void set_startup_language(const QString &s) + { + startup_language_ = s; + } - bool crash_on_startup() const - { - return crash_; - } + bool crash_on_startup() const + { + return crash_; + } - void set_crash_on_startup(bool e) - { - crash_ = true; - } + void set_crash_on_startup(bool e) + { + crash_ = true; + } - private: - RunMode mode_; + private: + RunMode mode_; - QString startup_project_; + QString startup_project_; - QString startup_language_; + QString startup_language_; - bool run_fullscreen_; + bool run_fullscreen_; - bool crash_; + bool crash_; + }; - }; - - /** + /** * @brief Core Constructor * * Currently empty */ - Core(const CoreParams& params); + Core(const CoreParams ¶ms); - /** + /** * @brief Core object accessible from anywhere in the code * * Use this to access Core functions. */ - static Core* instance(); + static Core *instance(); - const CoreParams& core_params() const - { - return core_params_; - } + const CoreParams &core_params() const + { + return core_params_; + } - /** + /** * @brief Start Olive Core * * Main application launcher. Parses command line arguments and constructs main window (if entering a GUI mode). */ - void Start(); + void Start(); - /** + /** * @brief Stop Olive Core * * Ends all threads and frees all memory ready for the application to exit. */ - void Stop(); + void Stop(); - /** + /** * @brief Retrieve main window instance * * @return * * Pointer to the olive::MainWindow object, or nullptr if running in CLI mode. */ - MainWindow* main_window(); + MainWindow *main_window(); - /** + /** * @brief Retrieve UndoStack object */ - UndoStack* undo_stack(); + UndoStack *undo_stack(); - /** + /** * @brief Import a list of files * * FIXME: I kind of hate this, it needs a model to update correctly. Is there a way that Items can signal enough to @@ -181,34 +175,34 @@ public: * * @param urls */ - void ImportFiles(const QStringList& urls, Folder *parent); + void ImportFiles(const QStringList &urls, Folder *parent); - /** + /** * @brief Get the currently active tool */ - const Tool::Item& tool() const; + const Tool::Item &tool() const; - /** + /** * @brief Get the currently selected object that the add tool should make (if the add tool is active) */ - const Tool::AddableObject& GetSelectedAddableObject() const; + const Tool::AddableObject &GetSelectedAddableObject() const; - /** + /** * @brief Get the currently selected node that the transition tool should make (if the transition tool is active) */ - const QString& GetSelectedTransition() const; + const QString &GetSelectedTransition() const; - /** + /** * @brief Get current snapping value */ - const bool& snapping() const; + const bool &snapping() const; - /** + /** * @brief Returns a list of the most recently opened/saved projects */ - const QStringList& GetRecentProjects() const; + const QStringList &GetRecentProjects() const; - /** + /** * @brief Get the currently active project * * Uses the UI/Panel system to determine which Project was the last focused on and assumes this is the active Project @@ -218,402 +212,409 @@ public: * * The active Project file, or nullptr if the heuristic couldn't find one. */ - Project* GetActiveProject() const; - Folder* GetSelectedFolderInActiveProject() const; + Project *GetActiveProject() const; + Folder *GetSelectedFolderInActiveProject() const; - /** + /** * @brief Gets current timecode display mode */ - Timecode::Display GetTimecodeDisplay() const; + Timecode::Display GetTimecodeDisplay() const; - /** + /** * @brief Sets current timecode display mode */ - void SetTimecodeDisplay(Timecode::Display d); + void SetTimecodeDisplay(Timecode::Display d); - /** + /** * @brief Set how frequently an autorecovery should be saved (if the project has changed, see SetProjectModified()) */ - void SetAutorecoveryInterval(int minutes); + void SetAutorecoveryInterval(int minutes); - static void CopyStringToClipboard(const QString& s); + static void CopyStringToClipboard(const QString &s); - static QString PasteStringFromClipboard(); + static QString PasteStringFromClipboard(); - /** + /** * @brief Recursively count files in a file/directory list */ - static int CountFilesInFileList(const QFileInfoList &filenames); + static int CountFilesInFileList(const QFileInfoList &filenames); - /** + /** * @brief Show a dialog to the user to rename a set of nodes */ - bool LabelNodes(const QVector &nodes, MultiUndoCommand *parent = nullptr); + bool LabelNodes(const QVector &nodes, + MultiUndoCommand *parent = nullptr); - /** + /** * @brief Create a new sequence named appropriately for the active project */ - static Sequence* CreateNewSequenceForProject(const QString &format, Project *project); - static Sequence* CreateNewSequenceForProject(Project *project) - { - return CreateNewSequenceForProject(tr("Sequence %1"), project); - } + static Sequence *CreateNewSequenceForProject(const QString &format, + Project *project); + static Sequence *CreateNewSequenceForProject(Project *project) + { + return CreateNewSequenceForProject(tr("Sequence %1"), project); + } - /** + /** * @brief Opens a project from the recently opened list */ - void OpenProjectFromRecentList(int index); + void OpenProjectFromRecentList(int index); - /** + /** * @brief Closes a project */ - bool CloseProject(bool auto_open_new, bool ignore_modified = false); + bool CloseProject(bool auto_open_new, bool ignore_modified = false); - /** + /** * @brief Runs a modal cache task on the currently active sequence */ - void CacheActiveSequence(bool in_out_only); + void CacheActiveSequence(bool in_out_only); - /** + /** * @brief Check each footage object for whether it still exists or has changed */ - bool ValidateFootageInLoadedProject(Project* project, const QString &project_saved_url); + bool ValidateFootageInLoadedProject(Project *project, + const QString &project_saved_url); - /** + /** * @brief Changes the current language */ - bool SetLanguage(const QString& locale); + bool SetLanguage(const QString &locale); - /** + /** * @brief Show message in main window's status bar * * Shorthand for Core::instance()->main_window()->statusBar()->showMessage(); */ - void ShowStatusBarMessage(const QString& s, int timeout = 0); + void ShowStatusBarMessage(const QString &s, int timeout = 0); - void ClearStatusBarMessage(); + void ClearStatusBarMessage(); - void OpenRecoveryProject(const QString& filename); + void OpenRecoveryProject(const QString &filename); - void OpenNodeInViewer(ViewerOutput* viewer); + void OpenNodeInViewer(ViewerOutput *viewer); - void OpenExportDialogForViewer(ViewerOutput *viewer, bool start_still_image); + void OpenExportDialogForViewer(ViewerOutput *viewer, + bool start_still_image); - bool IsMagicEnabled() const { return magic_; } + bool IsMagicEnabled() const + { + return magic_; + } public slots: - /** + /** * @brief Starts an open file dialog to load a project from file */ - void OpenProject(); + void OpenProject(); - /** + /** * @brief Saves the current project */ - bool SaveProject(); + bool SaveProject(); - /** + /** * @brief Performs a "save as" on the current project */ - bool SaveProjectAs(); + bool SaveProjectAs(); - void RevertProject(); + void RevertProject(); - /** + /** * @brief Set the current application-wide tool * * @param tool */ - void SetTool(const Tool::Item& tool); + void SetTool(const Tool::Item &tool); - /** + /** * @brief Set the current snapping setting */ - void SetSnapping(const bool& b); + void SetSnapping(const bool &b); - /** + /** * @brief Show an About dialog */ - void DialogAboutShow(); + void DialogAboutShow(); - /** + /** * @brief Open the import footage dialog and import the files selected (runs ImportFiles()) */ - void DialogImportShow(); + void DialogImportShow(); - /** + /** * @brief Show Preferences dialog */ - void DialogPreferencesShow(); + void DialogPreferencesShow(); - /** + /** * @brief Show Project Properties dialog */ - void DialogProjectPropertiesShow(); + void DialogProjectPropertiesShow(); - /** + /** * @brief Show Export dialog */ - void DialogExportShow(); + void DialogExportShow(); - /** + /** * @brief Show OTIO import dialog */ #ifdef USE_OTIO - bool DialogImportOTIOShow(const QList& sequences); + bool DialogImportOTIOShow(const QList &sequences); #endif - /** + /** * @brief Create a new folder in the currently active project */ - void CreateNewFolder(); + void CreateNewFolder(); - /** + /** * @brief Create a new sequence in the currently active project */ - void CreateNewSequence(); + void CreateNewSequence(); - /** + /** * @brief Set the currently selected object that the add tool should make */ - void SetSelectedAddableObject(const Tool::AddableObject& obj); + void SetSelectedAddableObject(const Tool::AddableObject &obj); - /** + /** * @brief Set the currently selected object that the add tool should make */ - void SetSelectedTransitionObject(const QString& obj); + void SetSelectedTransitionObject(const QString &obj); - /** + /** * @brief Clears the list of recently opened/saved projects */ - void ClearOpenRecentList(); + void ClearOpenRecentList(); - /** + /** * @brief Creates a new empty project and opens it */ - void CreateNewProject(); + void CreateNewProject(); - void CheckForAutoRecoveries(); + void CheckForAutoRecoveries(); - void BrowseAutoRecoveries(); + void BrowseAutoRecoveries(); - void RequestPixelSamplingInViewers(bool e); + void RequestPixelSamplingInViewers(bool e); - void WarnCacheFull(); + void WarnCacheFull(); - void SetMagic(bool e) - { - magic_ = e; - } + void SetMagic(bool e) + { + magic_ = e; + } signals: - /** + /** * @brief Signal emitted when the tool is changed from somewhere */ - void ToolChanged(const Tool::Item& tool); + void ToolChanged(const Tool::Item &tool); - /** + /** * @brief Signal emitted when addable object changes through SetSelectedAddableObject */ - void AddableObjectChanged(Tool::AddableObject o); + void AddableObjectChanged(Tool::AddableObject o); - /** + /** * @brief Signal emitted when the snapping setting is changed */ - void SnappingChanged(const bool& b); + void SnappingChanged(const bool &b); - /** + /** * @brief Signal emitted when the default timecode display mode changed */ - void TimecodeDisplayChanged(Timecode::Display d); + void TimecodeDisplayChanged(Timecode::Display d); - /** + /** * @brief Signal emitted when a change is made to the open recent list */ - void OpenRecentListChanged(); + void OpenRecentListChanged(); - /** + /** * @brief Enable mouse color sampling functionality on all viewers * * This can be slow, so we only turn it on when we need it. */ - void ColorPickerEnabled(bool e); + void ColorPickerEnabled(bool e); - /** + /** * @brief A viewer with color picked enabled has emitted a color */ - void ColorPickerColorEmitted(const Color &reference, const Color &display); + void ColorPickerColorEmitted(const Color &reference, const Color &display); private: - /** + /** * @brief Get the file filter than can be used with QFileDialog to open and save compatible projects */ - static QString GetProjectFilter(bool include_any_filter); + static QString GetProjectFilter(bool include_any_filter); - /** + /** * @brief Returns the filename where the recently opened/saved projects should be stored */ - static QString GetRecentProjectsFilePath(); + static QString GetRecentProjectsFilePath(); - /** + /** * @brief Called only on startup to set the locale */ - void SetStartupLocale(); + void SetStartupLocale(); - /** + /** * @brief Adds a filename to the top of the recently opened projects list (or moves it if it already exists) */ - void PushRecentlyOpenedProject(const QString &s); + void PushRecentlyOpenedProject(const QString &s); - /** + /** * @brief Declare custom types/classes for Qt's signal/slot system * * Qt's signal/slot system requires types to be declared. In the interest of doing this only at startup, we contain * them all in a function here. */ - void DeclareTypesForQt(); + void DeclareTypesForQt(); - /** + /** * @brief Start GUI portion of Olive * * Starts services and objects required for the GUI of Olive. It's guaranteed that running without this function will * create an application instance that is completely valid minus the UI (e.g. for CLI modes). */ - void StartGUI(bool full_screen); + void StartGUI(bool full_screen); - /** + /** * @brief Internal function for saving a project to a file */ - void SaveProjectInternal(const QString &override_filename = QString()); + void SaveProjectInternal(const QString &override_filename = QString()); - /** + /** * @brief Retrieves the currently most active sequence for exporting */ - ViewerOutput *GetSequenceToExport(); + ViewerOutput *GetSequenceToExport(); - static QString GetAutoRecoveryIndexFilename(); + static QString GetAutoRecoveryIndexFilename(); - void SaveUnrecoveredList(); + void SaveUnrecoveredList(); - bool RevertProjectInternal(bool by_opening_existing); + bool RevertProjectInternal(bool by_opening_existing); - void SaveRecentProjectsList(); + void SaveRecentProjectsList(); - /** + /** * @brief Adds a project to the "open projects" list */ - void AddOpenProject(olive::Project* p, bool add_to_recents = false); + void AddOpenProject(olive::Project *p, bool add_to_recents = false); - bool AddOpenProjectFromTask(Task* task, bool add_to_recents); + bool AddOpenProjectFromTask(Task *task, bool add_to_recents); - void SetActiveProject(Project *p); + void SetActiveProject(Project *p); - /** + /** * @brief Internal main window object */ - MainWindow* main_window_; + MainWindow *main_window_; - /** + /** * @brief List of currently open projects */ - Project *open_project_; + Project *open_project_; - /** + /** * @brief Currently active tool */ - Tool::Item tool_; + Tool::Item tool_; - /** + /** * @brief Currently active addable object */ - Tool::AddableObject addable_object_; + Tool::AddableObject addable_object_; - /** + /** * @brief Currently selected transition */ - QString selected_transition_; + QString selected_transition_; - /** + /** * @brief Current snapping setting */ - bool snapping_; + bool snapping_; - /** + /** * @brief Internal timer for saving autorecovery files */ - QTimer autorecovery_timer_; + QTimer autorecovery_timer_; - /** + /** * @brief Application-wide undo stack instance */ - UndoStack undo_stack_; + UndoStack undo_stack_; - /** + /** * @brief List of most recently opened/saved projects */ - QStringList recent_projects_; + QStringList recent_projects_; - /** + /** * @brief Parameters set up in main() determining how the program should run */ - CoreParams core_params_; + CoreParams core_params_; - /** + /** * @brief Static singleton core instance */ - static Core* instance_; + static Core *instance_; - /** + /** * @brief Internal translator */ - QTranslator* translator_; + QTranslator *translator_; - /** + /** * @brief List of projects that are unsaved but have autorecovery projects */ - QVector autorecovered_projects_; + QVector autorecovered_projects_; - /** + /** * @brief Do something debug related */ - bool magic_; + bool magic_; - /** + /** * @brief How many widgets currently need pixel sampling access */ - int pixel_sampling_users_; + int pixel_sampling_users_; - bool shown_cache_full_warning_; + bool shown_cache_full_warning_; private slots: - void SaveAutorecovery(); + void SaveAutorecovery(); - void ProjectSaveSucceeded(Task *task); + void ProjectSaveSucceeded(Task *task); - bool AddOpenProjectFromTaskAndAddToRecents(Task* task) - { - return AddOpenProjectFromTask(task, true); - } + bool AddOpenProjectFromTaskAndAddToRecents(Task *task) + { + return AddOpenProjectFromTask(task, true); + } - void ImportTaskComplete(Task *task); + void ImportTaskComplete(Task *task); - bool ConfirmImageSequence(const QString &filename); + bool ConfirmImageSequence(const QString &filename); - void ProjectWasModified(bool e); + void ProjectWasModified(bool e); - bool StartHeadlessExport(); + bool StartHeadlessExport(); - void OpenStartupProject(); + void OpenStartupProject(); - void AddRecoveryProjectFromTask(Task* task); + void AddRecoveryProjectFromTask(Task *task); - /** + /** * @brief Internal project open */ - void OpenProjectInternal(const QString& filename, bool recovery_project = false); - - void ImportSingleFile(const QString &f); + void OpenProjectInternal(const QString &filename, + bool recovery_project = false); + void ImportSingleFile(const QString &f); }; } diff --git a/app/crashhandler/crashhandler.cpp b/app/crashhandler/crashhandler.cpp index 5fe8cfb75..b1b8a0971 100644 --- a/app/crashhandler/crashhandler.cpp +++ b/app/crashhandler/crashhandler.cpp @@ -40,335 +40,370 @@ #include "common/filefunctions.h" #include "version.h" -namespace olive { - -CrashHandlerDialog::CrashHandlerDialog(const QString& report_path) +namespace olive { - setWindowTitle(tr("Olive")); - setWindowFlags(Qt::WindowStaysOnTopHint); - report_filename_ = report_path; - waiting_for_upload_ = false; +CrashHandlerDialog::CrashHandlerDialog(const QString &report_path) +{ + setWindowTitle(tr("Olive")); + setWindowFlags(Qt::WindowStaysOnTopHint); - QVBoxLayout* layout = new QVBoxLayout(this); + report_filename_ = report_path; + waiting_for_upload_ = false; - layout->addWidget(new QLabel(tr("We're sorry, Olive has crashed. Please help us fix it by " - "sending an error report."))); + QVBoxLayout *layout = new QVBoxLayout(this); - QSplitter* splitter = new QSplitter(Qt::Vertical); - splitter->setChildrenCollapsible(false); - layout->addWidget(splitter); + layout->addWidget(new QLabel( + tr("We're sorry, Olive has crashed. Please help us fix it by " + "sending an error report."))); - summary_edit_ = new QTextEdit(); - summary_edit_->setPlaceholderText(tr("Describe what you were doing in as much detail as " - "possible. If you can, provide steps to reproduce this crash.")); + QSplitter *splitter = new QSplitter(Qt::Vertical); + splitter->setChildrenCollapsible(false); + layout->addWidget(splitter); - splitter->addWidget(summary_edit_); + summary_edit_ = new QTextEdit(); + summary_edit_->setPlaceholderText( + tr("Describe what you were doing in as much detail as " + "possible. If you can, provide steps to reproduce this crash.")); - QWidget* crash_widget = new QWidget(); - QVBoxLayout* crash_widget_layout = new QVBoxLayout(crash_widget); - crash_widget_layout->setMargin(0); + splitter->addWidget(summary_edit_); - crash_widget_layout->addWidget(new QLabel(tr("Crash Report:"))); + QWidget *crash_widget = new QWidget(); + QVBoxLayout *crash_widget_layout = new QVBoxLayout(crash_widget); + crash_widget_layout->setMargin(0); - crash_report_ = new QTextEdit(); - crash_report_->setReadOnly(true); - crash_report_->setFont(QFontDatabase::systemFont(QFontDatabase::FixedFont)); - crash_widget_layout->addWidget(crash_report_); + crash_widget_layout->addWidget(new QLabel(tr("Crash Report:"))); - splitter->addWidget(crash_widget); + crash_report_ = new QTextEdit(); + crash_report_->setReadOnly(true); + crash_report_->setFont(QFontDatabase::systemFont(QFontDatabase::FixedFont)); + crash_widget_layout->addWidget(crash_report_); - QHBoxLayout* btn_layout = new QHBoxLayout(); - btn_layout->setMargin(0); - btn_layout->addStretch(); + splitter->addWidget(crash_widget); - send_report_btn_ = new QPushButton(tr("Send Error Report")); - connect(send_report_btn_, &QPushButton::clicked, this, &CrashHandlerDialog::SendErrorReport); - btn_layout->addWidget(send_report_btn_); + QHBoxLayout *btn_layout = new QHBoxLayout(); + btn_layout->setMargin(0); + btn_layout->addStretch(); - dont_send_btn_ = new QPushButton(tr("Don't Send")); - connect(dont_send_btn_, &QPushButton::clicked, this, &CrashHandlerDialog::reject); - btn_layout->addWidget(dont_send_btn_); + send_report_btn_ = new QPushButton(tr("Send Error Report")); + connect(send_report_btn_, &QPushButton::clicked, this, + &CrashHandlerDialog::SendErrorReport); + btn_layout->addWidget(send_report_btn_); - layout->addLayout(btn_layout); + dont_send_btn_ = new QPushButton(tr("Don't Send")); + connect(dont_send_btn_, &QPushButton::clicked, this, + &CrashHandlerDialog::reject); + btn_layout->addWidget(dont_send_btn_); - crash_report_->setEnabled(false); - send_report_btn_->setEnabled(false); + layout->addLayout(btn_layout); - crash_report_->setText(tr("Waiting for crash report to be generated...")); + crash_report_->setEnabled(false); + send_report_btn_->setEnabled(false); - GenerateReport(); + crash_report_->setText(tr("Waiting for crash report to be generated...")); + + GenerateReport(); } void CrashHandlerDialog::SetGUIObjectsEnabled(bool e) { - summary_edit_->setEnabled(e); - crash_report_->setEnabled(e); - send_report_btn_->setEnabled(e); - dont_send_btn_->setEnabled(e); + summary_edit_->setEnabled(e); + crash_report_->setEnabled(e); + send_report_btn_->setEnabled(e); + dont_send_btn_->setEnabled(e); } QString CrashHandlerDialog::GetSymbolPath() { - QDir app_path(qApp->applicationDirPath()); - QString symbols_path; + QDir app_path(qApp->applicationDirPath()); + QString symbols_path; #if BUILDFLAG(IS_WIN) - symbols_path = app_path.filePath(QStringLiteral("symbols")); + symbols_path = app_path.filePath(QStringLiteral("symbols")); #elif BUILDFLAG(IS_LINUX) - app_path.cdUp(); - symbols_path = app_path.filePath(QStringLiteral("share/olive-editor/symbols")); + app_path.cdUp(); + symbols_path = + app_path.filePath(QStringLiteral("share/olive-editor/symbols")); #elif BUILDFLAG(IS_APPLE) - app_path.cdUp(); - symbols_path = app_path.filePath(QStringLiteral("Resources/symbols")); + app_path.cdUp(); + symbols_path = app_path.filePath(QStringLiteral("Resources/symbols")); #endif - return symbols_path; + return symbols_path; } void CrashHandlerDialog::GenerateReport() { - QProcess* p = new QProcess(); + QProcess *p = new QProcess(); - connect(p, QOverload::of(&QProcess::finished), - this, &CrashHandlerDialog::ReadProcessFinished); - connect(p, &QProcess::readyReadStandardOutput, this, &CrashHandlerDialog::ReadProcessHasData); + connect(p, QOverload::of(&QProcess::finished), + this, &CrashHandlerDialog::ReadProcessFinished); + connect(p, &QProcess::readyReadStandardOutput, this, + &CrashHandlerDialog::ReadProcessHasData); - QString stackwalk_filename = FileFunctions::GetFormattedExecutableForPlatform(QStringLiteral("minidump_stackwalk")); + QString stackwalk_filename = + FileFunctions::GetFormattedExecutableForPlatform( + QStringLiteral("minidump_stackwalk")); - QString stackwalk_bin = QDir(qApp->applicationDirPath()).filePath(stackwalk_filename); - p->start(stackwalk_bin, {report_filename_, GetSymbolPath()}); - crash_report_->setText(QStringLiteral("Trying to run: %1").arg(stackwalk_bin)); + QString stackwalk_bin = + QDir(qApp->applicationDirPath()).filePath(stackwalk_filename); + p->start(stackwalk_bin, { report_filename_, GetSymbolPath() }); + crash_report_->setText( + QStringLiteral("Trying to run: %1").arg(stackwalk_bin)); } -void CrashHandlerDialog::ReplyFinished(QNetworkReply* reply) +void CrashHandlerDialog::ReplyFinished(QNetworkReply *reply) { - waiting_for_upload_ = false; + waiting_for_upload_ = false; - if (reply->error() == QNetworkReply::NoError) { - // Close dialog - QDialog::accept(); - } else { - QMessageBox b(this); - b.setIcon(QMessageBox::Critical); - b.setWindowModality(Qt::WindowModal); - b.setWindowTitle(tr("Upload Failed")); - b.setText(tr("Failed to send error report (%1). Please try again later.").arg(QString::number(reply->error()))); - b.addButton(QMessageBox::Ok); - b.exec(); + if (reply->error() == QNetworkReply::NoError) { + // Close dialog + QDialog::accept(); + } else { + QMessageBox b(this); + b.setIcon(QMessageBox::Critical); + b.setWindowModality(Qt::WindowModal); + b.setWindowTitle(tr("Upload Failed")); + b.setText( + tr("Failed to send error report (%1). Please try again later.") + .arg(QString::number(reply->error()))); + b.addButton(QMessageBox::Ok); + b.exec(); - SetGUIObjectsEnabled(true); - } + SetGUIObjectsEnabled(true); + } } -void CrashHandlerDialog::HandleSslErrors(QNetworkReply *reply, const QList &se) +void CrashHandlerDialog::HandleSslErrors(QNetworkReply *reply, + const QList &se) { - QStringList errors; - for (const QSslError &err : se) { - errors.append(err.errorString()); - } + QStringList errors; + for (const QSslError &err : se) { + errors.append(err.errorString()); + } - QMessageBox b(this); - b.setIcon(QMessageBox::Critical); - b.setWindowModality(Qt::WindowModal); - b.setWindowTitle(tr("SSL Error")); - b.setText(tr("Encountered the following SSL errors:\n\n%1").arg(errors.join('\n'))); - b.addButton(QMessageBox::Ok); - b.exec(); + QMessageBox b(this); + b.setIcon(QMessageBox::Critical); + b.setWindowModality(Qt::WindowModal); + b.setWindowTitle(tr("SSL Error")); + b.setText(tr("Encountered the following SSL errors:\n\n%1") + .arg(errors.join('\n'))); + b.addButton(QMessageBox::Ok); + b.exec(); } void CrashHandlerDialog::AttemptToFindReport() { - // If we found it, use it, otherwise wait a second and try again - if (report_filename_.isEmpty()) { - // Couldn't find report, try again in one second - QTimer::singleShot(500, this, &CrashHandlerDialog::AttemptToFindReport); - } else { - GenerateReport(); - } + // If we found it, use it, otherwise wait a second and try again + if (report_filename_.isEmpty()) { + // Couldn't find report, try again in one second + QTimer::singleShot(500, this, &CrashHandlerDialog::AttemptToFindReport); + } else { + GenerateReport(); + } } void CrashHandlerDialog::ReadProcessHasData() { - report_data_.append(static_cast(sender())->readAllStandardOutput()); + report_data_.append( + static_cast(sender())->readAllStandardOutput()); } void CrashHandlerDialog::ReadProcessFinished() { - SetGUIObjectsEnabled(true); - crash_report_->setText(report_data_); - delete sender(); + SetGUIObjectsEnabled(true); + crash_report_->setText(report_data_); + delete sender(); } void CrashHandlerDialog::SendErrorReport() { - if (summary_edit_->document()->isEmpty()) { - QMessageBox b(this); - b.setIcon(QMessageBox::Question); - b.setWindowModality(Qt::WindowModal); - b.setText(tr("You must write a description to submit this crash report.")); - b.addButton(QMessageBox::Ok); - b.exec(); - return; - } + if (summary_edit_->document()->isEmpty()) { + QMessageBox b(this); + b.setIcon(QMessageBox::Question); + b.setWindowModality(Qt::WindowModal); + b.setText( + tr("You must write a description to submit this crash report.")); + b.addButton(QMessageBox::Ok); + b.exec(); + return; + } - QNetworkAccessManager* manager = new QNetworkAccessManager(); - connect(manager, &QNetworkAccessManager::finished, this, &CrashHandlerDialog::ReplyFinished); - connect(manager, &QNetworkAccessManager::sslErrors, this, &CrashHandlerDialog::HandleSslErrors); + QNetworkAccessManager *manager = new QNetworkAccessManager(); + connect(manager, &QNetworkAccessManager::finished, this, + &CrashHandlerDialog::ReplyFinished); + connect(manager, &QNetworkAccessManager::sslErrors, this, + &CrashHandlerDialog::HandleSslErrors); - QNetworkRequest request; - request.setSslConfiguration(QSslConfiguration::defaultConfiguration()); - request.setUrl(QStringLiteral("https://olivevideoeditor.org/crashpad/report.php")); + QNetworkRequest request; + request.setSslConfiguration(QSslConfiguration::defaultConfiguration()); + request.setUrl( + QStringLiteral("https://olivevideoeditor.org/crashpad/report.php")); - // Create HTTP form - QHttpMultiPart* multipart = new QHttpMultiPart(QHttpMultiPart::FormDataType); + // Create HTTP form + QHttpMultiPart *multipart = + new QHttpMultiPart(QHttpMultiPart::FormDataType); - // Create description section - QHttpPart desc_part; - desc_part.setHeader(QNetworkRequest::ContentTypeHeader, QStringLiteral("text/plain; charset=UTF-8")); - desc_part.setHeader(QNetworkRequest::ContentDispositionHeader, QStringLiteral("form-data; name=\"description\"")); - desc_part.setBody(summary_edit_->toPlainText().toUtf8()); - multipart->append(desc_part); + // Create description section + QHttpPart desc_part; + desc_part.setHeader(QNetworkRequest::ContentTypeHeader, + QStringLiteral("text/plain; charset=UTF-8")); + desc_part.setHeader(QNetworkRequest::ContentDispositionHeader, + QStringLiteral("form-data; name=\"description\"")); + desc_part.setBody(summary_edit_->toPlainText().toUtf8()); + multipart->append(desc_part); - // Create report section - QHttpPart report_part; - report_part.setHeader(QNetworkRequest::ContentTypeHeader, QStringLiteral("text/plain; charset=UTF-8")); - report_part.setHeader(QNetworkRequest::ContentDispositionHeader, QStringLiteral("form-data; name=\"report\"")); - report_part.setBody(report_data_); - multipart->append(report_part); + // Create report section + QHttpPart report_part; + report_part.setHeader(QNetworkRequest::ContentTypeHeader, + QStringLiteral("text/plain; charset=UTF-8")); + report_part.setHeader(QNetworkRequest::ContentDispositionHeader, + QStringLiteral("form-data; name=\"report\"")); + report_part.setBody(report_data_); + multipart->append(report_part); - // Create commit section - QHttpPart commit_part; - commit_part.setHeader(QNetworkRequest::ContentTypeHeader, QStringLiteral("text/plain; charset=UTF-8")); - commit_part.setHeader(QNetworkRequest::ContentDispositionHeader, QStringLiteral("form-data; name=\"commit\"")); - commit_part.setBody(kAppVersionLong.toUtf8()); - multipart->append(commit_part); + // Create commit section + QHttpPart commit_part; + commit_part.setHeader(QNetworkRequest::ContentTypeHeader, + QStringLiteral("text/plain; charset=UTF-8")); + commit_part.setHeader(QNetworkRequest::ContentDispositionHeader, + QStringLiteral("form-data; name=\"commit\"")); + commit_part.setBody(kAppVersionLong.toUtf8()); + multipart->append(commit_part); - // Create dump section - QHttpPart dump_part; - dump_part.setHeader(QNetworkRequest::ContentTypeHeader, QStringLiteral("application/octet-stream")); - dump_part.setHeader(QNetworkRequest::ContentDispositionHeader, QStringLiteral("form-data; name=\"dump\"; filename=\"%1\"") - .arg(QFileInfo(report_filename_).fileName())); - QFile* dump_file = new QFile(report_filename_); - dump_file->open(QFile::ReadOnly); - dump_part.setBodyDevice(dump_file); - dump_file->setParent(multipart); // Delete file with multipart - multipart->append(dump_part); + // Create dump section + QHttpPart dump_part; + dump_part.setHeader(QNetworkRequest::ContentTypeHeader, + QStringLiteral("application/octet-stream")); + dump_part.setHeader( + QNetworkRequest::ContentDispositionHeader, + QStringLiteral("form-data; name=\"dump\"; filename=\"%1\"") + .arg(QFileInfo(report_filename_).fileName())); + QFile *dump_file = new QFile(report_filename_); + dump_file->open(QFile::ReadOnly); + dump_part.setBodyDevice(dump_file); + dump_file->setParent(multipart); // Delete file with multipart + multipart->append(dump_part); - // Find symbol file - QDir symbol_dir(GetSymbolPath()); + // Find symbol file + QDir symbol_dir(GetSymbolPath()); - QString symbol_bin_name; + QString symbol_bin_name; #if BUILDFLAG(IS_WIN) - symbol_bin_name = QStringLiteral("olive-editor.pdb"); + symbol_bin_name = QStringLiteral("olive-editor.pdb"); #elif BUILDFLAG(IS_APPLE) - symbol_bin_name = QStringLiteral("Olive"); + symbol_bin_name = QStringLiteral("Olive"); #else - symbol_bin_name = QStringLiteral("olive-editor"); + symbol_bin_name = QStringLiteral("olive-editor"); #endif - symbol_dir = QDir(symbol_dir.filePath(symbol_bin_name)); + symbol_dir = QDir(symbol_dir.filePath(symbol_bin_name)); - QStringList folders_in_symbol_path = symbol_dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot); + QStringList folders_in_symbol_path = + symbol_dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot); - if (folders_in_symbol_path.size() > 0) { - symbol_dir = QDir(symbol_dir.filePath(folders_in_symbol_path.first())); - } else { - QMessageBox b(this); - b.setIcon(QMessageBox::Critical); - b.setWindowModality(Qt::WindowModal); - b.setWindowTitle(tr("Failed to send report")); - b.setText(tr("Failed to find symbols necessary to send report. " - "This is a packaging issue. Please notify " - "the maintainers of this package.")); - b.addButton(QMessageBox::Ok); - b.exec(); - return; - } + if (folders_in_symbol_path.size() > 0) { + symbol_dir = QDir(symbol_dir.filePath(folders_in_symbol_path.first())); + } else { + QMessageBox b(this); + b.setIcon(QMessageBox::Critical); + b.setWindowModality(Qt::WindowModal); + b.setWindowTitle(tr("Failed to send report")); + b.setText(tr("Failed to find symbols necessary to send report. " + "This is a packaging issue. Please notify " + "the maintainers of this package.")); + b.addButton(QMessageBox::Ok); + b.exec(); + return; + } - // Create sym section - QString symbol_filename; + // Create sym section + QString symbol_filename; #if BUILDFLAG(IS_APPLE) - symbol_filename = QStringLiteral("Olive.sym"); + symbol_filename = QStringLiteral("Olive.sym"); #else - symbol_filename = QStringLiteral("olive-editor.sym"); + symbol_filename = QStringLiteral("olive-editor.sym"); #endif - QString symbol_full_path = symbol_dir.filePath(symbol_filename); - QHttpPart sym_part; - sym_part.setHeader(QNetworkRequest::ContentTypeHeader, QStringLiteral("application/octet-stream")); - sym_part.setHeader(QNetworkRequest::ContentDispositionHeader, QStringLiteral("form-data; name=\"sym\"; filename=\"%1\"") - .arg(symbol_filename)); - QFile sym_file(symbol_full_path); + QString symbol_full_path = symbol_dir.filePath(symbol_filename); + QHttpPart sym_part; + sym_part.setHeader(QNetworkRequest::ContentTypeHeader, + QStringLiteral("application/octet-stream")); + sym_part.setHeader( + QNetworkRequest::ContentDispositionHeader, + QStringLiteral("form-data; name=\"sym\"; filename=\"%1\"") + .arg(symbol_filename)); + QFile sym_file(symbol_full_path); - if (!sym_file.open(QFile::ReadOnly)) { - QMessageBox b(this); - b.setIcon(QMessageBox::Critical); - b.setWindowModality(Qt::WindowModal); - b.setWindowTitle(tr("Failed to send report")); - b.setText(tr("Failed to open symbol file. You may not have " - "permission to access it.")); - b.addButton(QMessageBox::Ok); - b.exec(); - return; - } + if (!sym_file.open(QFile::ReadOnly)) { + QMessageBox b(this); + b.setIcon(QMessageBox::Critical); + b.setWindowModality(Qt::WindowModal); + b.setWindowTitle(tr("Failed to send report")); + b.setText(tr("Failed to open symbol file. You may not have " + "permission to access it.")); + b.addButton(QMessageBox::Ok); + b.exec(); + return; + } - QByteArray symbol_data = qCompress(sym_file.readAll(), 9); - sym_file.close(); + QByteArray symbol_data = qCompress(sym_file.readAll(), 9); + sym_file.close(); - sym_part.setBody(symbol_data); - multipart->append(sym_part); + sym_part.setBody(symbol_data); + multipart->append(sym_part); - manager->post(request, multipart); + manager->post(request, multipart); - SetGUIObjectsEnabled(false); - waiting_for_upload_ = true; + SetGUIObjectsEnabled(false); + waiting_for_upload_ = true; } -void CrashHandlerDialog::closeEvent(QCloseEvent* e) +void CrashHandlerDialog::closeEvent(QCloseEvent *e) { - QMessageBox b(this); - b.setIcon(QMessageBox::Warning); - b.setWindowModality(Qt::WindowModal); - b.setWindowTitle(tr("Confirm Close")); - b.setText(tr("Crash report is still uploading. Closing now may result in no " - "report being sent. Are you sure you wish to close?")); - b.addButton(QMessageBox::Ok); - b.addButton(QMessageBox::Cancel); + QMessageBox b(this); + b.setIcon(QMessageBox::Warning); + b.setWindowModality(Qt::WindowModal); + b.setWindowTitle(tr("Confirm Close")); + b.setText( + tr("Crash report is still uploading. Closing now may result in no " + "report being sent. Are you sure you wish to close?")); + b.addButton(QMessageBox::Ok); + b.addButton(QMessageBox::Cancel); - if (waiting_for_upload_ && b.exec() == QMessageBox::Cancel) { - e->ignore(); - } else { - e->accept(); - } + if (waiting_for_upload_ && b.exec() == QMessageBox::Cancel) { + e->ignore(); + } else { + e->accept(); + } } } int main(int argc, char *argv[]) { - QString report; + QString report; #ifdef Q_OS_WINDOWS - int num_args; - LPWSTR *args = CommandLineToArgvW(GetCommandLineW(), &num_args); - if (num_args < 2) { - LocalFree(args); - return 1; - } + int num_args; + LPWSTR *args = CommandLineToArgvW(GetCommandLineW(), &num_args); + if (num_args < 2) { + LocalFree(args); + return 1; + } - report = QString::fromWCharArray(args[1]); - LocalFree(args); + report = QString::fromWCharArray(args[1]); + LocalFree(args); #else - if (argc < 2) { - return 1; - } + if (argc < 2) { + return 1; + } - report = argv[1]; + report = argv[1]; #endif - QApplication a(argc, argv); + QApplication a(argc, argv); - olive::CrashHandlerDialog chd(report); - chd.open(); + olive::CrashHandlerDialog chd(report); + chd.open(); - return a.exec(); + return a.exec(); } diff --git a/app/crashhandler/crashhandler.h b/app/crashhandler/crashhandler.h index d377061e2..1876ca3e9 100644 --- a/app/crashhandler/crashhandler.h +++ b/app/crashhandler/crashhandler.h @@ -30,51 +30,50 @@ #include "common/define.h" -namespace olive { - -class CrashHandlerDialog : public QDialog +namespace olive { - Q_OBJECT + +class CrashHandlerDialog : public QDialog { + Q_OBJECT public: - CrashHandlerDialog(const QString& report_path); + CrashHandlerDialog(const QString &report_path); private: - void SetGUIObjectsEnabled(bool e); + void SetGUIObjectsEnabled(bool e); - void GenerateReport(); + void GenerateReport(); - static QString GetSymbolPath(); + static QString GetSymbolPath(); - QTextEdit* summary_edit_; + QTextEdit *summary_edit_; - QTextEdit* crash_report_; + QTextEdit *crash_report_; - QPushButton* send_report_btn_; + QPushButton *send_report_btn_; - QPushButton* dont_send_btn_; + QPushButton *dont_send_btn_; - QString report_filename_; + QString report_filename_; - QByteArray report_data_; + QByteArray report_data_; - bool waiting_for_upload_; + bool waiting_for_upload_; protected: - virtual void closeEvent(QCloseEvent* e) override; + virtual void closeEvent(QCloseEvent *e) override; private slots: - void ReplyFinished(QNetworkReply *reply); + void ReplyFinished(QNetworkReply *reply); - void HandleSslErrors(QNetworkReply *reply, const QList &errors); + void HandleSslErrors(QNetworkReply *reply, const QList &errors); - void AttemptToFindReport(); + void AttemptToFindReport(); - void ReadProcessHasData(); + void ReadProcessHasData(); - void ReadProcessFinished(); - - void SendErrorReport(); + void ReadProcessFinished(); + void SendErrorReport(); }; } diff --git a/app/dialog/about/about.cpp b/app/dialog/about/about.cpp index 4fb526944..d8fd4a652 100644 --- a/app/dialog/about/about.cpp +++ b/app/dialog/about/about.cpp @@ -30,114 +30,127 @@ #include "patreon.h" #include "scrollinglabel.h" -namespace olive { - -AboutDialog::AboutDialog(bool welcome_dialog, QWidget *parent) : - QDialog(parent) +namespace olive { - if (welcome_dialog) { - setWindowTitle(tr("Welcome to %1").arg(QApplication::applicationName())); - } else { - setWindowTitle(tr("About %1").arg(QApplication::applicationName())); - } - QFontMetrics fm = fontMetrics(); +AboutDialog::AboutDialog(bool welcome_dialog, QWidget *parent) + : QDialog(parent) +{ + if (welcome_dialog) { + setWindowTitle( + tr("Welcome to %1").arg(QApplication::applicationName())); + } else { + setWindowTitle(tr("About %1").arg(QApplication::applicationName())); + } - QVBoxLayout* layout = new QVBoxLayout(this); - layout->setContentsMargins(fm.height(), fm.height(), fm.height(), fm.height()); + QFontMetrics fm = fontMetrics(); - QHBoxLayout *horiz_layout = new QHBoxLayout(); - horiz_layout->setContentsMargins(fm.height(), fm.height(), fm.height(), fm.height()); - horiz_layout->setSpacing(fm.height()*2); + QVBoxLayout *layout = new QVBoxLayout(this); + layout->setContentsMargins(fm.height(), fm.height(), fm.height(), + fm.height()); - QLabel* icon = new QLabel(QStringLiteral("")); - icon->setAlignment(Qt::AlignCenter); - horiz_layout->addWidget(icon); + QHBoxLayout *horiz_layout = new QHBoxLayout(); + horiz_layout->setContentsMargins(fm.height(), fm.height(), fm.height(), + fm.height()); + horiz_layout->setSpacing(fm.height() * 2); - // Construct About text - QLabel* label = - new QLabel(QStringLiteral("" - "

%1 %2

" // AppName (version identifier) - "

" - "https://www.olivevideoeditor.org/" - "

" - "

%3

" // First statement - "").arg(QApplication::applicationName(), - QApplication::applicationVersion(), - tr("Olive is a free open source non-linear video editor. " - "This software is licensed under the GNU GPL Version 3."))); + QLabel *icon = new QLabel( + QStringLiteral("")); + icon->setAlignment(Qt::AlignCenter); + horiz_layout->addWidget(icon); - // Set text formatting - label->setAlignment(Qt::AlignLeft | Qt::AlignVCenter); - label->setWordWrap(true); - label->setOpenExternalLinks(true); - label->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum); - label->setTextInteractionFlags(Qt::TextSelectableByMouse | Qt::LinksAccessibleByMouse); - label->setCursor(Qt::IBeamCursor); - horiz_layout->addWidget(label); + // Construct About text + QLabel *label = new QLabel( + QStringLiteral("" + "

%1 %2

" // AppName (version identifier) + "

" + "https://www.olivevideoeditor.org/" + "

" + "

%3

" // First statement + "") + .arg(QApplication::applicationName(), + QApplication::applicationVersion(), + tr("Olive is a free open source non-linear video editor. " + "This software is licensed under the GNU GPL Version 3."))); - layout->addLayout(horiz_layout); + // Set text formatting + label->setAlignment(Qt::AlignLeft | Qt::AlignVCenter); + label->setWordWrap(true); + label->setOpenExternalLinks(true); + label->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum); + label->setTextInteractionFlags(Qt::TextSelectableByMouse | + Qt::LinksAccessibleByMouse); + label->setCursor(Qt::IBeamCursor); + horiz_layout->addWidget(label); - // Patrons where possible - layout->addWidget(new QLabel()); + layout->addLayout(horiz_layout); - QString opening_statement; + // Patrons where possible + layout->addWidget(new QLabel()); - if (welcome_dialog || patrons.isEmpty()) { - opening_statement = tr("Olive relies on support from the community to continue its development."); - } else { - opening_statement = tr("Olive wouldn't be possible without the support of gracious donations from the following people."); - } + QString opening_statement; - QLabel* support_lbl = new QLabel(tr("%1 " - "If you like this project, please consider making a " - "one-time donation or " - "pledging monthly to " - "support its development.").arg(opening_statement)); - support_lbl->setWordWrap(true); - support_lbl->setAlignment(Qt::AlignCenter); - support_lbl->setOpenExternalLinks(true); - layout->addWidget(support_lbl); + if (welcome_dialog || patrons.isEmpty()) { + opening_statement = tr( + "Olive relies on support from the community to continue its development."); + } else { + opening_statement = tr( + "Olive wouldn't be possible without the support of gracious donations from the following people."); + } - if (!patrons.isEmpty()) { - ScrollingLabel* scroll = new ScrollingLabel(patrons); - scroll->StartAnimating(); - layout->addWidget(scroll); - } + QLabel *support_lbl = new QLabel( + tr("%1 " + "If you like this project, please consider making a " + "one-time donation or " + "pledging monthly to " + "support its development.") + .arg(opening_statement)); + support_lbl->setWordWrap(true); + support_lbl->setAlignment(Qt::AlignCenter); + support_lbl->setOpenExternalLinks(true); + layout->addWidget(support_lbl); - layout->addWidget(new QLabel()); + if (!patrons.isEmpty()) { + ScrollingLabel *scroll = new ScrollingLabel(patrons); + scroll->StartAnimating(); + layout->addWidget(scroll); + } - QHBoxLayout *btn_layout = new QHBoxLayout(); - btn_layout->setContentsMargins(0, 0, 0, 0); - btn_layout->setSpacing(0); + layout->addWidget(new QLabel()); - if (welcome_dialog) { - dont_show_again_checkbox_ = new QCheckBox(tr("Don't show this message again")); - btn_layout->addWidget(dont_show_again_checkbox_); - } else { - dont_show_again_checkbox_ = nullptr; - } + QHBoxLayout *btn_layout = new QHBoxLayout(); + btn_layout->setContentsMargins(0, 0, 0, 0); + btn_layout->setSpacing(0); - QDialogButtonBox* buttons = new QDialogButtonBox(QDialogButtonBox::Ok, this); - if (!welcome_dialog) { - buttons->setCenterButtons(true); - } - btn_layout->addWidget(buttons); + if (welcome_dialog) { + dont_show_again_checkbox_ = + new QCheckBox(tr("Don't show this message again")); + btn_layout->addWidget(dont_show_again_checkbox_); + } else { + dont_show_again_checkbox_ = nullptr; + } - layout->addLayout(btn_layout); + QDialogButtonBox *buttons = + new QDialogButtonBox(QDialogButtonBox::Ok, this); + if (!welcome_dialog) { + buttons->setCenterButtons(true); + } + btn_layout->addWidget(buttons); - connect(buttons, &QDialogButtonBox::accepted, this, &QDialog::accept); + layout->addLayout(btn_layout); - setFixedSize(sizeHint()); + connect(buttons, &QDialogButtonBox::accepted, this, &QDialog::accept); + + setFixedSize(sizeHint()); } void AboutDialog::accept() { - if (dont_show_again_checkbox_ && dont_show_again_checkbox_->isChecked()) { - OLIVE_CONFIG("ShowWelcomeDialog") = false; - } + if (dont_show_again_checkbox_ && dont_show_again_checkbox_->isChecked()) { + OLIVE_CONFIG("ShowWelcomeDialog") = false; + } - QDialog::accept(); + QDialog::accept(); } } diff --git a/app/dialog/about/about.h b/app/dialog/about/about.h index 24e0881f6..ccea2bac6 100644 --- a/app/dialog/about/about.h +++ b/app/dialog/about/about.h @@ -26,7 +26,8 @@ #include "common/define.h" -namespace olive { +namespace olive +{ /** * @brief The AboutDialog class @@ -34,11 +35,10 @@ namespace olive { * The About dialog (accessible through Help > About). Contains license and version information. This can be run from * anywhere */ -class AboutDialog : public QDialog -{ - Q_OBJECT +class AboutDialog : public QDialog { + Q_OBJECT public: - /** + /** * @brief AboutDialog Constructor * * Creates About dialog. @@ -47,14 +47,13 @@ public: * * QWidget parent object. Usually this will be MainWindow. */ - explicit AboutDialog(bool welcome_dialog, QWidget *parent = nullptr); + explicit AboutDialog(bool welcome_dialog, QWidget *parent = nullptr); public slots: - virtual void accept() override; + virtual void accept() override; private: - QCheckBox *dont_show_again_checkbox_; - + QCheckBox *dont_show_again_checkbox_; }; } diff --git a/app/dialog/about/scrollinglabel.cpp b/app/dialog/about/scrollinglabel.cpp index 8384e00cb..a426a30a5 100644 --- a/app/dialog/about/scrollinglabel.cpp +++ b/app/dialog/about/scrollinglabel.cpp @@ -24,98 +24,101 @@ #include "common/qtutils.h" -namespace olive { +namespace olive +{ const int ScrollingLabel::kMinLineHeight = 10; -ScrollingLabel::ScrollingLabel(QWidget *parent) : - QWidget(parent), - animate_(0) +ScrollingLabel::ScrollingLabel(QWidget *parent) + : QWidget(parent) + , animate_(0) { - timer_.setInterval(50); - connect(&timer_, &QTimer::timeout, this, &ScrollingLabel::AnimationUpdate); + timer_.setInterval(50); + connect(&timer_, &QTimer::timeout, this, &ScrollingLabel::AnimationUpdate); } -ScrollingLabel::ScrollingLabel(const QStringList &text, QWidget *parent) : - ScrollingLabel(parent) +ScrollingLabel::ScrollingLabel(const QStringList &text, QWidget *parent) + : ScrollingLabel(parent) { - SetText(text); + SetText(text); } void ScrollingLabel::SetText(const QStringList &text) { - text_ = text; + text_ = text; - QFontMetrics fm = fontMetrics(); - text_height_ = fm.height(); + QFontMetrics fm = fontMetrics(); + text_height_ = fm.height(); - int width = 0; - foreach (const QString& s, text_) { - width = qMax(width, QtUtils::QFontMetricsWidth(fm, s)); - } + int width = 0; + foreach (const QString &s, text_) { + width = qMax(width, QtUtils::QFontMetricsWidth(fm, s)); + } - setMinimumSize(width, text_height_ * kMinLineHeight); + setMinimumSize(width, text_height_ * kMinLineHeight); } void ScrollingLabel::paintEvent(QPaintEvent *e) { - QImage map(width(), height(), QImage::Format_RGBA8888_Premultiplied); - map.fill(Qt::transparent); + QImage map(width(), height(), QImage::Format_RGBA8888_Premultiplied); + map.fill(Qt::transparent); - { - QPainter p(&map); - p.setPen(palette().text().color()); + { + QPainter p(&map); + p.setPen(palette().text().color()); - QFontMetrics fm = p.fontMetrics(); - int half_width = width(); + QFontMetrics fm = p.fontMetrics(); + int half_width = width(); - for (int i=0; i= height()) { - continue; - } + if (text_bottom < 0 || text_top >= height()) { + continue; + } - const QString& s = text_.at(i); + const QString &s = text_.at(i); - int width = QtUtils::QFontMetricsWidth(fm, s); - p.drawText(half_width/2 - width/2, text_y, s); - } + int width = QtUtils::QFontMetricsWidth(fm, s); + p.drawText(half_width / 2 - width / 2, text_y, s); + } - for (int y=0; y= height() + text_.size() * text_height_) { - animate_ = 0; - } + if (animate_ >= height() + text_.size() * text_height_) { + animate_ = 0; + } - update(); + update(); } } diff --git a/app/dialog/about/scrollinglabel.h b/app/dialog/about/scrollinglabel.h index 6671b2d6c..cf43e63ce 100644 --- a/app/dialog/about/scrollinglabel.h +++ b/app/dialog/about/scrollinglabel.h @@ -24,46 +24,46 @@ #include #include -namespace olive { - -class ScrollingLabel : public QWidget +namespace olive { - Q_OBJECT + +class ScrollingLabel : public QWidget { + Q_OBJECT public: - ScrollingLabel(QWidget* parent = nullptr); - ScrollingLabel(const QStringList& text, QWidget* parent = nullptr); + ScrollingLabel(QWidget *parent = nullptr); + ScrollingLabel(const QStringList &text, QWidget *parent = nullptr); - void SetText(const QStringList& text); + void SetText(const QStringList &text); - void StartAnimating() - { - timer_.start(); - } + void StartAnimating() + { + timer_.start(); + } - void StopAnimating() - { - timer_.stop(); - } + void StopAnimating() + { + timer_.stop(); + } protected: - virtual void paintEvent(QPaintEvent* e) override; + virtual void paintEvent(QPaintEvent *e) override; private: - static void SetOpacityOfScanLine(uchar* scan_line, int width, int channels, double mul); + static void SetOpacityOfScanLine(uchar *scan_line, int width, int channels, + double mul); - static const int kMinLineHeight; + static const int kMinLineHeight; - QStringList text_; + QStringList text_; - int text_height_; + int text_height_; - QTimer timer_; + QTimer timer_; - int animate_; + int animate_; private slots: - void AnimationUpdate(); - + void AnimationUpdate(); }; } diff --git a/app/dialog/actionsearch/actionsearch.cpp b/app/dialog/actionsearch/actionsearch.cpp index e2732460b..7728f4575 100644 --- a/app/dialog/actionsearch/actionsearch.cpp +++ b/app/dialog/actionsearch/actionsearch.cpp @@ -25,247 +25,251 @@ #include #include -namespace olive { - -ActionSearch::ActionSearch(QWidget *parent) : - QDialog(parent), - menu_bar_(nullptr) +namespace olive { - // ActionSearch requires a parent widget - Q_ASSERT(parent != nullptr); - // Set styling (object name is required for CSS specific to this object) - setObjectName("ASDiag"); - setStyleSheet("#ASDiag{border: 2px solid #808080;}"); +ActionSearch::ActionSearch(QWidget *parent) + : QDialog(parent) + , menu_bar_(nullptr) +{ + // ActionSearch requires a parent widget + Q_ASSERT(parent != nullptr); - // Size proportionally to the parent (usually MainWindow). - resize(parent->width()/3, parent->height()/3); + // Set styling (object name is required for CSS specific to this object) + setObjectName("ASDiag"); + setStyleSheet("#ASDiag{border: 2px solid #808080;}"); - // Show dialog as a "popup", which will make the dialog close if the user clicks out of it. - setWindowFlags(Qt::Popup); + // Size proportionally to the parent (usually MainWindow). + resize(parent->width() / 3, parent->height() / 3); - QVBoxLayout* layout = new QVBoxLayout(this); + // Show dialog as a "popup", which will make the dialog close if the user clicks out of it. + setWindowFlags(Qt::Popup); - // Construct the main entry text field. - ActionSearchEntry* entry_field = new ActionSearchEntry(this); + QVBoxLayout *layout = new QVBoxLayout(this); - // Set the main entry field font size to 1.2x its standard font size. - QFont entry_field_font = entry_field->font(); - entry_field_font.setPointSize(qRound(entry_field_font.pointSize()*1.2)); - entry_field->setFont(entry_field_font); + // Construct the main entry text field. + ActionSearchEntry *entry_field = new ActionSearchEntry(this); - // Set placeholder text for the main entry field - entry_field->setPlaceholderText(tr("Search for action...")); + // Set the main entry field font size to 1.2x its standard font size. + QFont entry_field_font = entry_field->font(); + entry_field_font.setPointSize(qRound(entry_field_font.pointSize() * 1.2)); + entry_field->setFont(entry_field_font); - // Connect signals/slots - connect(entry_field, SIGNAL(textChanged(const QString&)), this, SLOT(search_update(const QString &))); - connect(entry_field, SIGNAL(returnPressed()), this, SLOT(perform_action())); + // Set placeholder text for the main entry field + entry_field->setPlaceholderText(tr("Search for action...")); - // moveSelectionUp() and moveSelectionDown() are emitted when the user pressed up or down on the text field. - // We override it here to select the upper or lower item in the list. - connect(entry_field, SIGNAL(moveSelectionUp()), this, SLOT(move_selection_up())); - connect(entry_field, SIGNAL(moveSelectionDown()), this, SLOT(move_selection_down())); - layout->addWidget(entry_field); + // Connect signals/slots + connect(entry_field, SIGNAL(textChanged(const QString &)), this, + SLOT(search_update(const QString &))); + connect(entry_field, SIGNAL(returnPressed()), this, SLOT(perform_action())); - // Construct list of actions - list_widget = new ActionSearchList(this); + // moveSelectionUp() and moveSelectionDown() are emitted when the user pressed up or down on the text field. + // We override it here to select the upper or lower item in the list. + connect(entry_field, SIGNAL(moveSelectionUp()), this, + SLOT(move_selection_up())); + connect(entry_field, SIGNAL(moveSelectionDown()), this, + SLOT(move_selection_down())); + layout->addWidget(entry_field); - // Set list's font to 1.2x its standard font size - QFont list_widget_font = list_widget->font(); - list_widget_font.setPointSize(qRound(list_widget_font.pointSize()*1.2)); - list_widget->setFont(list_widget_font); + // Construct list of actions + list_widget = new ActionSearchList(this); - layout->addWidget(list_widget); + // Set list's font to 1.2x its standard font size + QFont list_widget_font = list_widget->font(); + list_widget_font.setPointSize(qRound(list_widget_font.pointSize() * 1.2)); + list_widget->setFont(list_widget_font); - connect(list_widget, SIGNAL(dbl_click()), this, SLOT(perform_action())); + layout->addWidget(list_widget); - // Instantly focus on the entry field to allow for fully keyboard operation (if this popup was initiated by keyboard - // shortcut for example). - entry_field->setFocus(); + connect(list_widget, SIGNAL(dbl_click()), this, SLOT(perform_action())); + + // Instantly focus on the entry field to allow for fully keyboard operation (if this popup was initiated by keyboard + // shortcut for example). + entry_field->setFocus(); } void ActionSearch::SetMenuBar(QMenuBar *menu_bar) { - menu_bar_ = menu_bar; + menu_bar_ = menu_bar; } -void ActionSearch::search_update(const QString &s, const QString &p, QMenu *parent) +void ActionSearch::search_update(const QString &s, const QString &p, + QMenu *parent) { - // Do nothing if there's no menu bar to work with - if (menu_bar_ == nullptr) { - return; - } + // Do nothing if there's no menu bar to work with + if (menu_bar_ == nullptr) { + return; + } - // This function is recursive, using the `parent` parameter to loop through a menu's items. It functions in two - // modes - the parent being NULL, meaning it'll get MainWindow's menubar and loop over its menus, and the parent - // referring to a menu at which point it'll loop over its actions (and call itself recursively if it finds any - // submenus). + // This function is recursive, using the `parent` parameter to loop through a menu's items. It functions in two + // modes - the parent being NULL, meaning it'll get MainWindow's menubar and loop over its menus, and the parent + // referring to a menu at which point it'll loop over its actions (and call itself recursively if it finds any + // submenus). - if (parent == nullptr) { + if (parent == nullptr) { + // If parent is NULL, we'll pull from the MainWindow's menubar and call this recursively on all of its submenus + // (and their submenus). - // If parent is NULL, we'll pull from the MainWindow's menubar and call this recursively on all of its submenus - // (and their submenus). + // We'll clear all the current items in the list since if we're here, we're just starting. + list_widget->clear(); - // We'll clear all the current items in the list since if we're here, we're just starting. - list_widget->clear(); + QList menus = menu_bar_->actions(); - QList menus = menu_bar_->actions(); + // Loop through all menus from the menubar and run this function on each one. + for (int i = 0; i < menus.size(); i++) { + QMenu *menu = menus.at(i)->menu(); - // Loop through all menus from the menubar and run this function on each one. - for (int i=0;imenu(); + search_update(s, p, menu); + } - search_update(s, p, menu); - } + // Once we're here, all the recursion/item retrieval is complete. We auto-select the first item for better + // keyboard-exclusive functionality. + if (list_widget->count() > 0) { + list_widget->item(0)->setSelected(true); + } - // Once we're here, all the recursion/item retrieval is complete. We auto-select the first item for better - // keyboard-exclusive functionality. - if (list_widget->count() > 0) { - list_widget->item(0)->setSelected(true); - } + } else { + // Parent was not NULL, so we loop over the actions in the menu we were given in `parent`. - } else { + // The list shows a '>' delimited hierarchy of the menus in which this action came from. We construct it here by + // adding the current menu's text to the existing hierarchy (passed in `p`). + QString menu_text; + if (!p.isEmpty()) + menu_text += p + " > "; + menu_text += parent->title().replace( + "&", ""); // Strip out any &s used in menu action names - // Parent was not NULL, so we loop over the actions in the menu we were given in `parent`. + // Loop over the menu's actions + QList actions = parent->actions(); + for (int i = 0; i < actions.size(); i++) { + QAction *a = actions.at(i); - // The list shows a '>' delimited hierarchy of the menus in which this action came from. We construct it here by - // adding the current menu's text to the existing hierarchy (passed in `p`). - QString menu_text; - if (!p.isEmpty()) menu_text += p + " > "; - menu_text += parent->title().replace("&", ""); // Strip out any &s used in menu action names + // Ignore separator actions + if (!a->isSeparator()) { + if (a->menu() != nullptr) { + // If the action is a menu, run this function recursively on it + search_update(s, menu_text, a->menu()); - // Loop over the menu's actions - QList actions = parent->actions(); - for (int i=0;itext().replace("&", ""); - // Ignore separator actions - if (!a->isSeparator()) { + // See if the action's name contains any of the currently entered string + if (comp.contains(s, Qt::CaseInsensitive)) { + // If so, we add it to the list widget. + QListWidgetItem *item = new QListWidgetItem( + QStringLiteral("%1\n(%2)").arg(comp, menu_text), + list_widget); - if (a->menu() != nullptr) { + // Add a pointer to the original QAction in the item's data + item->setData(Qt::UserRole + 1, + reinterpret_cast(a)); - // If the action is a menu, run this function recursively on it - search_update(s, menu_text, a->menu()); - - } else { - - // This is a valid non-separator non-menu action, so check it against the currently entered string. - - // Strip out all &s from the action's name - QString comp = a->text().replace("&", ""); - - // See if the action's name contains any of the currently entered string - if (comp.contains(s, Qt::CaseInsensitive)) { - - // If so, we add it to the list widget. - QListWidgetItem* item = new QListWidgetItem(QStringLiteral("%1\n(%2)").arg(comp, menu_text), list_widget); - - // Add a pointer to the original QAction in the item's data - item->setData(Qt::UserRole+1, reinterpret_cast(a)); - - list_widget->addItem(item); - - } - - } - } - } - } + list_widget->addItem(item); + } + } + } + } + } } -void ActionSearch::perform_action() { +void ActionSearch::perform_action() +{ + // Loop over all the items in the list and if we find one that's selected, we trigger it. + QList selected_items = list_widget->selectedItems(); + if (list_widget->count() > 0 && selected_items.size() > 0) { + QListWidgetItem *item = selected_items.at(0); - // Loop over all the items in the list and if we find one that's selected, we trigger it. - QList selected_items = list_widget->selectedItems(); - if (list_widget->count() > 0 && selected_items.size() > 0) { + // Get QAction pointer from item's data + QAction *a = reinterpret_cast( + item->data(Qt::UserRole + 1).value()); - QListWidgetItem* item = selected_items.at(0); - - // Get QAction pointer from item's data - QAction* a = reinterpret_cast(item->data(Qt::UserRole+1).value()); - - a->trigger(); - - } - - // Close this popup - accept(); + a->trigger(); + } + // Close this popup + accept(); } -void ActionSearch::move_selection_up() { +void ActionSearch::move_selection_up() +{ + // Here we loop over all the items to find the currently selected one, and then select the one above it. We start + // iterating at 1 (instead of 0) to efficiently ignore the first item (since the selection can't go below the very + // bottom item). - // Here we loop over all the items to find the currently selected one, and then select the one above it. We start - // iterating at 1 (instead of 0) to efficiently ignore the first item (since the selection can't go below the very - // bottom item). - - int lim = list_widget->count(); - for (int i=1;iitem(i)->isSelected()) { - list_widget->item(i-1)->setSelected(true); - list_widget->scrollToItem(list_widget->item(i-1)); - break; - } - } + int lim = list_widget->count(); + for (int i = 1; i < lim; i++) { + if (list_widget->item(i)->isSelected()) { + list_widget->item(i - 1)->setSelected(true); + list_widget->scrollToItem(list_widget->item(i - 1)); + break; + } + } } -void ActionSearch::move_selection_down() { +void ActionSearch::move_selection_down() +{ + // Here we loop over all the items to find the currently selected one, and then select the one below it. We limit it + // one entry before count() to efficiently ignore the item at the end (since the selection can't go below the very + // bottom item). - // Here we loop over all the items to find the currently selected one, and then select the one below it. We limit it - // one entry before count() to efficiently ignore the item at the end (since the selection can't go below the very - // bottom item). - - int lim = list_widget->count()-1; - for (int i=0;iitem(i)->isSelected()) { - list_widget->item(i+1)->setSelected(true); - list_widget->scrollToItem(list_widget->item(i+1)); - break; - } - } + int lim = list_widget->count() - 1; + for (int i = 0; i < lim; i++) { + if (list_widget->item(i)->isSelected()) { + list_widget->item(i + 1)->setSelected(true); + list_widget->scrollToItem(list_widget->item(i + 1)); + break; + } + } } -ActionSearchEntry::ActionSearchEntry(QWidget *parent) : QLineEdit(parent) {} +ActionSearchEntry::ActionSearchEntry(QWidget *parent) + : QLineEdit(parent) +{ +} bool ActionSearchEntry::event(QEvent *e) { - switch (e->type()) { - case QEvent::ShortcutOverride: - switch (static_cast(e)->key()) { - case Qt::Key_Up: - case Qt::Key_Down: - e->accept(); - return true; - } - break; - case QEvent::KeyPress: - // Listen for up/down, otherwise pass the key event to the base class. - switch (static_cast(e)->key()) { - case Qt::Key_Up: - e->accept(); - emit moveSelectionUp(); - return true; - case Qt::Key_Down: - e->accept(); - emit moveSelectionDown(); - return true; - } - break; - default: - break; - } + switch (e->type()) { + case QEvent::ShortcutOverride: + switch (static_cast(e)->key()) { + case Qt::Key_Up: + case Qt::Key_Down: + e->accept(); + return true; + } + break; + case QEvent::KeyPress: + // Listen for up/down, otherwise pass the key event to the base class. + switch (static_cast(e)->key()) { + case Qt::Key_Up: + e->accept(); + emit moveSelectionUp(); + return true; + case Qt::Key_Down: + e->accept(); + emit moveSelectionDown(); + return true; + } + break; + default: + break; + } - return QLineEdit::event(e); + return QLineEdit::event(e); } -ActionSearchList::ActionSearchList(QWidget *parent) : QListWidget(parent) {} - -void ActionSearchList::mouseDoubleClickEvent(QMouseEvent *) { - - // Indiscriminately emit a signal on any double click - emit dbl_click(); +ActionSearchList::ActionSearchList(QWidget *parent) + : QListWidget(parent) +{ +} +void ActionSearchList::mouseDoubleClickEvent(QMouseEvent *) +{ + // Indiscriminately emit a signal on any double click + emit dbl_click(); } } diff --git a/app/dialog/actionsearch/actionsearch.h b/app/dialog/actionsearch/actionsearch.h index 96829e579..70f31a8bc 100644 --- a/app/dialog/actionsearch/actionsearch.h +++ b/app/dialog/actionsearch/actionsearch.h @@ -29,7 +29,8 @@ #include "common/define.h" -namespace olive { +namespace olive +{ class ActionSearchList; @@ -39,11 +40,10 @@ class ActionSearchList; * A popup window (accessible through Help > Action Search) that allows users to search for a menu command by typing * rather than browsing through the menu bar. This can be created from anywhere provided olive::MainWindow is valid. */ -class ActionSearch : public QDialog -{ - Q_OBJECT +class ActionSearch : public QDialog { + Q_OBJECT public: - /** + /** * @brief ActionSearch Constructor * * Create ActionSearch popup. @@ -52,14 +52,14 @@ public: * * QWidget parent. Usually MainWindow. */ - ActionSearch(QWidget* parent); + ActionSearch(QWidget *parent); - /** + /** * @brief Set the menu bar to use in this action search */ - void SetMenuBar(QMenuBar* menu_bar); + void SetMenuBar(QMenuBar *menu_bar); private slots: - /** + /** * @brief Update the list of actions according to a search query * * This function adds/removes actions in the action list according to a given search query entered by the user. @@ -82,42 +82,44 @@ private slots: * The current menu to loop over. In most cases, this should be left as nullptr when called externally. * search_update() will fill this automatically as it needs while calling itself recursively. */ - void search_update(const QString& s, const QString &p = nullptr, QMenu *parent = nullptr); + void search_update(const QString &s, const QString &p = nullptr, + QMenu *parent = nullptr); - /** + /** * @brief Perform the currently selected action * * Usually triggered by pressing Enter on the ActionSearchEntry field, this will trigger whatever action is currently * highlighted and then close this popup. If no entries are highlighted (i.e. the list is empty), no action is * triggered and the popup closes anyway. */ - void perform_action(); + void perform_action(); - /** + /** * @brief Move selection up * * A slot for pressing up on the ActionSearchEntry field. Moves the selection in the list up once. If the * selection is already at the top of the list, this is a no-op. */ - void move_selection_up(); + void move_selection_up(); - /** + /** * @brief Move selection down * * A slot for pressing down on the ActionSearchEntry field. Moves the selection in the list down once. If the * selection is already at the bottom of the list, this is a no-op. */ - void move_selection_down(); + void move_selection_down(); + private: - /** + /** * @brief Main widget that shows the list of commands */ - ActionSearchList* list_widget; + ActionSearchList *list_widget; - /** + /** * @brief Attached menu bar object */ - QMenuBar* menu_bar_; + QMenuBar *menu_bar_; }; /** @@ -127,25 +129,26 @@ private: * to a slot that triggers the currently selected action. */ class ActionSearchList : public QListWidget { - Q_OBJECT + Q_OBJECT public: - /** + /** * @brief ActionSearchList Constructor * @param parent * * Usually ActionSearch. */ - ActionSearchList(QWidget* parent); + ActionSearchList(QWidget *parent); + protected: - /** + /** * @brief Override of QListWidget's double click event that emits a signal. */ - void mouseDoubleClickEvent(QMouseEvent *); + void mouseDoubleClickEvent(QMouseEvent *); signals: - /** + /** * @brief Signal emitted when a QListWidget item is double clicked. */ - void dbl_click(); + void dbl_click(); }; /** @@ -155,32 +158,33 @@ signals: * can connect them to moving the current selection up or down. */ class ActionSearchEntry : public QLineEdit { - Q_OBJECT + Q_OBJECT public: - /** + /** * @brief ActionSearchEntry * @param parent * * Usually ActionSearch. */ - ActionSearchEntry(QWidget* parent); + ActionSearchEntry(QWidget *parent); + protected: - /** + /** * @brief Override of QLineEdit's key press event that listens for up/down key presses. * @param event */ - virtual bool event(QEvent *e) override; + virtual bool event(QEvent *e) override; signals: - /** + /** * @brief Emitted when the user presses the up arrow key. */ - void moveSelectionUp(); + void moveSelectionUp(); - /** + /** * @brief Emitted when the user presses the down arrow key. */ - void moveSelectionDown(); + void moveSelectionDown(); }; } diff --git a/app/dialog/autorecovery/autorecoverydialog.cpp b/app/dialog/autorecovery/autorecoverydialog.cpp index 1e4354ed1..835365cd0 100644 --- a/app/dialog/autorecovery/autorecoverydialog.cpp +++ b/app/dialog/autorecovery/autorecoverydialog.cpp @@ -29,108 +29,127 @@ #include "core.h" -namespace olive { +namespace olive +{ #define super QDialog -AutoRecoveryDialog::AutoRecoveryDialog(const QString &message, const QStringList &recoveries, bool autocheck_latest, QWidget* parent) : - QDialog(parent) +AutoRecoveryDialog::AutoRecoveryDialog(const QString &message, + const QStringList &recoveries, + bool autocheck_latest, QWidget *parent) + : QDialog(parent) { - Init(message); + Init(message); - PopulateTree(recoveries, autocheck_latest); + PopulateTree(recoveries, autocheck_latest); } void AutoRecoveryDialog::accept() { - foreach (QTreeWidgetItem* checkable, checkable_items_) { - if (checkable->checkState(0) == Qt::Checked) { - QString filename = checkable->data(0, kFilenameRole).toString(); - Core::instance()->OpenRecoveryProject(filename); - } - } + foreach (QTreeWidgetItem *checkable, checkable_items_) { + if (checkable->checkState(0) == Qt::Checked) { + QString filename = checkable->data(0, kFilenameRole).toString(); + Core::instance()->OpenRecoveryProject(filename); + } + } - super::accept(); + super::accept(); } -void AutoRecoveryDialog::Init(const QString& header_text) +void AutoRecoveryDialog::Init(const QString &header_text) { - QVBoxLayout* layout = new QVBoxLayout(this); + QVBoxLayout *layout = new QVBoxLayout(this); - setWindowTitle(tr("Auto-Recovery")); + setWindowTitle(tr("Auto-Recovery")); - layout->addWidget(new QLabel(header_text)); + layout->addWidget(new QLabel(header_text)); - tree_widget_ = new QTreeWidget(); - tree_widget_->setHeaderHidden(true); - layout->addWidget(tree_widget_); + tree_widget_ = new QTreeWidget(); + tree_widget_->setHeaderHidden(true); + layout->addWidget(tree_widget_); - QDialogButtonBox* buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); - buttons->button(QDialogButtonBox::Ok)->setText(tr("Load")); - connect(buttons, &QDialogButtonBox::accepted, this, &AutoRecoveryDialog::accept); - connect(buttons, &QDialogButtonBox::rejected, this, &AutoRecoveryDialog::reject); - layout->addWidget(buttons); + QDialogButtonBox *buttons = + new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); + buttons->button(QDialogButtonBox::Ok)->setText(tr("Load")); + connect(buttons, &QDialogButtonBox::accepted, this, + &AutoRecoveryDialog::accept); + connect(buttons, &QDialogButtonBox::rejected, this, + &AutoRecoveryDialog::reject); + layout->addWidget(buttons); } -void AutoRecoveryDialog::PopulateTree(const QStringList& recoveries, bool autocheck_latest) +void AutoRecoveryDialog::PopulateTree(const QStringList &recoveries, + bool autocheck_latest) { - // Each entry in `recoveries` is a directory with 1+ recovery projects in it - QDir autorecovery_root(FileFunctions::GetAutoRecoveryRoot()); + // Each entry in `recoveries` is a directory with 1+ recovery projects in it + QDir autorecovery_root(FileFunctions::GetAutoRecoveryRoot()); - foreach (const QString& recovery_folder, recoveries) { - QDir recovery_dir(autorecovery_root.filePath(recovery_folder)); + foreach (const QString &recovery_folder, recoveries) { + QDir recovery_dir(autorecovery_root.filePath(recovery_folder)); - QString pretty_name; - { - // Retrieve pretty name - QFile pretty_name_file(recovery_dir.filePath(QStringLiteral("realname.txt"))); - if (pretty_name_file.open(QFile::ReadOnly)) { - // Read pretty name that we should have written in the autorecovery process - pretty_name = QString::fromUtf8(pretty_name_file.readAll()); - pretty_name_file.close(); - } + QString pretty_name; + { + // Retrieve pretty name + QFile pretty_name_file( + recovery_dir.filePath(QStringLiteral("realname.txt"))); + if (pretty_name_file.open(QFile::ReadOnly)) { + // Read pretty name that we should have written in the autorecovery process + pretty_name = QString::fromUtf8(pretty_name_file.readAll()); + pretty_name_file.close(); + } - if (pretty_name.isEmpty()) { - // Fallback to just the UUID. While it won't mean much to the user, it's better than nothing. - pretty_name = recovery_dir.dirName(); - } - } + if (pretty_name.isEmpty()) { + // Fallback to just the UUID. While it won't mean much to the user, it's better than nothing. + pretty_name = recovery_dir.dirName(); + } + } - QTreeWidgetItem* top_level = new QTreeWidgetItem(tree_widget_); - top_level->setText(0, pretty_name); + QTreeWidgetItem *top_level = new QTreeWidgetItem(tree_widget_); + top_level->setText(0, pretty_name); - { - // Populate with recoveries - QStringList entries = recovery_dir.entryList(QDir::Files | QDir::NoDotAndDotDot, QDir::Name | QDir::Reversed); - for (int i=0; isetText(0, entry_name); - entry_item->setData(0, kFilenameRole, recovery_dir.filePath(entry)); + entry_item->setText(0, entry_name); + entry_item->setData(0, kFilenameRole, + recovery_dir.filePath(entry)); - // Allow to be checked, auto-checking the first entry - entry_item->setCheckState(0, (autocheck_latest && top_level->childCount() == 1) ? Qt::Checked : Qt::Unchecked); + // Allow to be checked, auto-checking the first entry + entry_item->setCheckState( + 0, (autocheck_latest && top_level->childCount() == 1) ? + Qt::Checked : + Qt::Unchecked); - checkable_items_.append(entry_item); - } - } - } - } + checkable_items_.append(entry_item); + } + } + } + } } } diff --git a/app/dialog/autorecovery/autorecoverydialog.h b/app/dialog/autorecovery/autorecoverydialog.h index aec025e03..d7add3e45 100644 --- a/app/dialog/autorecovery/autorecoverydialog.h +++ b/app/dialog/autorecovery/autorecoverydialog.h @@ -26,30 +26,28 @@ #include "common/define.h" -namespace olive { - -class AutoRecoveryDialog : public QDialog +namespace olive { - Q_OBJECT + +class AutoRecoveryDialog : public QDialog { + Q_OBJECT public: - AutoRecoveryDialog(const QString& message, const QStringList& recoveries, bool autocheck_latest, QWidget* parent); + AutoRecoveryDialog(const QString &message, const QStringList &recoveries, + bool autocheck_latest, QWidget *parent); public slots: - virtual void accept() override; + virtual void accept() override; private: - void Init(const QString &header_text); + void Init(const QString &header_text); - void PopulateTree(const QStringList &recoveries, bool autocheck); + void PopulateTree(const QStringList &recoveries, bool autocheck); - QTreeWidget* tree_widget_; + QTreeWidget *tree_widget_; - QVector checkable_items_; - - enum DataRole { - kFilenameRole = Qt::UserRole - }; + QVector checkable_items_; + enum DataRole { kFilenameRole = Qt::UserRole }; }; } diff --git a/app/dialog/color/colordialog.cpp b/app/dialog/color/colordialog.cpp index 360a8445d..b04717a07 100644 --- a/app/dialog/color/colordialog.cpp +++ b/app/dialog/color/colordialog.cpp @@ -26,167 +26,186 @@ #include "common/qtutils.h" -namespace olive { - -ColorDialog::ColorDialog(ColorManager* color_manager, const ManagedColor& start, QWidget *parent) : - QDialog(parent), - color_manager_(color_manager) +namespace olive { - setWindowTitle(tr("Select Color")); - QVBoxLayout* layout = new QVBoxLayout(this); +ColorDialog::ColorDialog(ColorManager *color_manager, const ManagedColor &start, + QWidget *parent) + : QDialog(parent) + , color_manager_(color_manager) +{ + setWindowTitle(tr("Select Color")); - QSplitter* splitter = new QSplitter(Qt::Horizontal); - splitter->setChildrenCollapsible(false); - layout->addWidget(splitter); + QVBoxLayout *layout = new QVBoxLayout(this); - QWidget* graphics_area = new QWidget(); - splitter->addWidget(graphics_area); + QSplitter *splitter = new QSplitter(Qt::Horizontal); + splitter->setChildrenCollapsible(false); + layout->addWidget(splitter); - QVBoxLayout *graphics_layout = new QVBoxLayout(graphics_area); + QWidget *graphics_area = new QWidget(); + splitter->addWidget(graphics_area); - QHBoxLayout* wheel_layout = new QHBoxLayout(); - graphics_layout->addLayout(wheel_layout); + QVBoxLayout *graphics_layout = new QVBoxLayout(graphics_area); - color_wheel_ = new ColorWheelWidget(); - wheel_layout->addWidget(color_wheel_); + QHBoxLayout *wheel_layout = new QHBoxLayout(); + graphics_layout->addLayout(wheel_layout); - hsv_value_gradient_ = new ColorGradientWidget(Qt::Vertical); - hsv_value_gradient_->setFixedWidth(QtUtils::QFontMetricsWidth(fontMetrics(), QStringLiteral("HHH"))); - wheel_layout->addWidget(hsv_value_gradient_); + color_wheel_ = new ColorWheelWidget(); + wheel_layout->addWidget(color_wheel_); - QHBoxLayout *swatch_layout = new QHBoxLayout(); - graphics_layout->addLayout(swatch_layout); + hsv_value_gradient_ = new ColorGradientWidget(Qt::Vertical); + hsv_value_gradient_->setFixedWidth( + QtUtils::QFontMetricsWidth(fontMetrics(), QStringLiteral("HHH"))); + wheel_layout->addWidget(hsv_value_gradient_); - swatch_layout->addStretch(); + QHBoxLayout *swatch_layout = new QHBoxLayout(); + graphics_layout->addLayout(swatch_layout); - swatch_ = new ColorSwatchChooser(color_manager_); - swatch_->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum); - swatch_layout->addWidget(swatch_); + swatch_layout->addStretch(); - swatch_layout->addStretch(); + swatch_ = new ColorSwatchChooser(color_manager_); + swatch_->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum); + swatch_layout->addWidget(swatch_); - QWidget* value_area = new QWidget(); - QVBoxLayout* value_layout = new QVBoxLayout(value_area); - value_layout->setSpacing(0); - splitter->addWidget(value_area); + swatch_layout->addStretch(); - color_values_widget_ = new ColorValuesWidget(color_manager_); - color_values_widget_->IgnorePickFrom(this); - value_layout->addWidget(color_values_widget_); + QWidget *value_area = new QWidget(); + QVBoxLayout *value_layout = new QVBoxLayout(value_area); + value_layout->setSpacing(0); + splitter->addWidget(value_area); - chooser_ = new ColorSpaceChooser(color_manager_); + color_values_widget_ = new ColorValuesWidget(color_manager_); + color_values_widget_->IgnorePickFrom(this); + value_layout->addWidget(color_values_widget_); - value_layout->addWidget(chooser_); + chooser_ = new ColorSpaceChooser(color_manager_); - // Split window 50/50 - splitter->setSizes({INT_MAX, INT_MAX}); + value_layout->addWidget(chooser_); - connect(color_wheel_, &ColorWheelWidget::SelectedColorChanged, color_values_widget_, &ColorValuesWidget::SetColor); - connect(color_wheel_, &ColorWheelWidget::SelectedColorChanged, hsv_value_gradient_, &ColorGradientWidget::SetSelectedColor); - connect(color_wheel_, &ColorWheelWidget::SelectedColorChanged, swatch_, &ColorSwatchChooser::SetCurrentColor); - connect(hsv_value_gradient_, &ColorGradientWidget::SelectedColorChanged, color_values_widget_, &ColorValuesWidget::SetColor); - connect(hsv_value_gradient_, &ColorGradientWidget::SelectedColorChanged, color_wheel_, &ColorWheelWidget::SetSelectedColor); - connect(hsv_value_gradient_, &ColorGradientWidget::SelectedColorChanged, swatch_, &ColorSwatchChooser::SetCurrentColor); - connect(color_values_widget_, &ColorValuesWidget::ColorChanged, hsv_value_gradient_, &ColorGradientWidget::SetSelectedColor); - connect(color_values_widget_, &ColorValuesWidget::ColorChanged, color_wheel_, &ColorWheelWidget::SetSelectedColor); - connect(color_values_widget_, &ColorValuesWidget::ColorChanged, swatch_, &ColorSwatchChooser::SetCurrentColor); - connect(swatch_, &ColorSwatchChooser::ColorClicked, hsv_value_gradient_, &ColorGradientWidget::SetSelectedColor); - connect(swatch_, &ColorSwatchChooser::ColorClicked, color_wheel_, &ColorWheelWidget::SetSelectedColor); - connect(swatch_, &ColorSwatchChooser::ColorClicked, color_values_widget_, &ColorValuesWidget::SetColor); + // Split window 50/50 + splitter->setSizes({ INT_MAX, INT_MAX }); - connect(color_wheel_, &ColorWheelWidget::DiameterChanged, hsv_value_gradient_, &ColorGradientWidget::setFixedHeight); + connect(color_wheel_, &ColorWheelWidget::SelectedColorChanged, + color_values_widget_, &ColorValuesWidget::SetColor); + connect(color_wheel_, &ColorWheelWidget::SelectedColorChanged, + hsv_value_gradient_, &ColorGradientWidget::SetSelectedColor); + connect(color_wheel_, &ColorWheelWidget::SelectedColorChanged, swatch_, + &ColorSwatchChooser::SetCurrentColor); + connect(hsv_value_gradient_, &ColorGradientWidget::SelectedColorChanged, + color_values_widget_, &ColorValuesWidget::SetColor); + connect(hsv_value_gradient_, &ColorGradientWidget::SelectedColorChanged, + color_wheel_, &ColorWheelWidget::SetSelectedColor); + connect(hsv_value_gradient_, &ColorGradientWidget::SelectedColorChanged, + swatch_, &ColorSwatchChooser::SetCurrentColor); + connect(color_values_widget_, &ColorValuesWidget::ColorChanged, + hsv_value_gradient_, &ColorGradientWidget::SetSelectedColor); + connect(color_values_widget_, &ColorValuesWidget::ColorChanged, + color_wheel_, &ColorWheelWidget::SetSelectedColor); + connect(color_values_widget_, &ColorValuesWidget::ColorChanged, swatch_, + &ColorSwatchChooser::SetCurrentColor); + connect(swatch_, &ColorSwatchChooser::ColorClicked, hsv_value_gradient_, + &ColorGradientWidget::SetSelectedColor); + connect(swatch_, &ColorSwatchChooser::ColorClicked, color_wheel_, + &ColorWheelWidget::SetSelectedColor); + connect(swatch_, &ColorSwatchChooser::ColorClicked, color_values_widget_, + &ColorValuesWidget::SetColor); - QDialogButtonBox* buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); - connect(buttons, &QDialogButtonBox::accepted, this, &QDialog::accept); - connect(buttons, &QDialogButtonBox::rejected, this, &QDialog::reject); - layout->addWidget(buttons); + connect(color_wheel_, &ColorWheelWidget::DiameterChanged, + hsv_value_gradient_, &ColorGradientWidget::setFixedHeight); - SetColor(start); + QDialogButtonBox *buttons = + new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); + connect(buttons, &QDialogButtonBox::accepted, this, &QDialog::accept); + connect(buttons, &QDialogButtonBox::rejected, this, &QDialog::reject); + layout->addWidget(buttons); - connect(chooser_, &ColorSpaceChooser::ColorSpaceChanged, this, &ColorDialog::ColorSpaceChanged); - ColorSpaceChanged(chooser_->input(), chooser_->output()); + SetColor(start); - // Set default size ratio to 2:1 - resize(sizeHint().height() * 2, sizeHint().height()); + connect(chooser_, &ColorSpaceChooser::ColorSpaceChanged, this, + &ColorDialog::ColorSpaceChanged); + ColorSpaceChanged(chooser_->input(), chooser_->output()); + + // Set default size ratio to 2:1 + resize(sizeHint().height() * 2, sizeHint().height()); } void ColorDialog::SetColor(const ManagedColor &start) { - chooser_->set_input(start.color_input()); - chooser_->set_output(start.color_output()); + chooser_->set_input(start.color_input()); + chooser_->set_output(start.color_output()); - Color managed_start; + Color managed_start; - if (start.color_input().isEmpty()) { + if (start.color_input().isEmpty()) { + managed_start = start; - managed_start = start; + } else { + // Convert reference color to the input space + ColorProcessorPtr linear_to_input = ColorProcessor::Create( + color_manager_, color_manager_->GetReferenceColorSpace(), + start.color_input()); - } else { + managed_start = linear_to_input->ConvertColor(start); + } - // Convert reference color to the input space - ColorProcessorPtr linear_to_input = ColorProcessor::Create(color_manager_, - color_manager_->GetReferenceColorSpace(), - start.color_input()); - - managed_start = linear_to_input->ConvertColor(start); - - } - - color_wheel_->SetSelectedColor(managed_start); - hsv_value_gradient_->SetSelectedColor(managed_start); - color_values_widget_->SetColor(managed_start); - swatch_->SetCurrentColor(managed_start); + color_wheel_->SetSelectedColor(managed_start); + hsv_value_gradient_->SetSelectedColor(managed_start); + color_values_widget_->SetColor(managed_start); + swatch_->SetCurrentColor(managed_start); } ManagedColor ColorDialog::GetSelectedColor() const { - ManagedColor selected = color_wheel_->GetSelectedColor(); + ManagedColor selected = color_wheel_->GetSelectedColor(); - // Convert to linear and return a linear color - if (input_to_ref_processor_) { - selected = input_to_ref_processor_->ConvertColor(selected); - } + // Convert to linear and return a linear color + if (input_to_ref_processor_) { + selected = input_to_ref_processor_->ConvertColor(selected); + } - selected.set_color_input(GetColorSpaceInput()); - selected.set_color_output(GetColorSpaceOutput()); + selected.set_color_input(GetColorSpaceInput()); + selected.set_color_output(GetColorSpaceOutput()); - return selected; + return selected; } QString ColorDialog::GetColorSpaceInput() const { - return chooser_->input(); + return chooser_->input(); } ColorTransform ColorDialog::GetColorSpaceOutput() const { - return chooser_->output(); + return chooser_->output(); } -void ColorDialog::ColorSpaceChanged(const QString &input, const ColorTransform &output) +void ColorDialog::ColorSpaceChanged(const QString &input, + const ColorTransform &output) { - input_to_ref_processor_ = ColorProcessor::Create(color_manager_, input, color_manager_->GetReferenceColorSpace()); + input_to_ref_processor_ = ColorProcessor::Create( + color_manager_, input, color_manager_->GetReferenceColorSpace()); - ColorProcessorPtr ref_to_display = ColorProcessor::Create(color_manager_, - color_manager_->GetReferenceColorSpace(), - output); + ColorProcessorPtr ref_to_display = ColorProcessor::Create( + color_manager_, color_manager_->GetReferenceColorSpace(), output); - ColorProcessorPtr ref_to_input = ColorProcessor::Create(color_manager_, color_manager_->GetReferenceColorSpace(), input); + ColorProcessorPtr ref_to_input = ColorProcessor::Create( + color_manager_, color_manager_->GetReferenceColorSpace(), input); - // FIXME: For some reason, using OCIO::TRANSFORM_DIR_INVERSE (wrapped by ColorProcessor::kInverse) causes OCIO to - // crash. We've disabled that functionality for now (also disabling display_tab_ in ColorValuesWidget) + // FIXME: For some reason, using OCIO::TRANSFORM_DIR_INVERSE (wrapped by ColorProcessor::kInverse) causes OCIO to + // crash. We've disabled that functionality for now (also disabling display_tab_ in ColorValuesWidget) - /*ColorProcessorPtr display_to_ref = ColorProcessor::Create(color_manager_->GetConfig(), + /*ColorProcessorPtr display_to_ref = ColorProcessor::Create(color_manager_->GetConfig(), color_manager_->GetReferenceColorSpace(), display, view, look, ColorProcessor::kInverse);*/ - color_wheel_->SetColorProcessor(input_to_ref_processor_, ref_to_display); - hsv_value_gradient_->SetColorProcessor(input_to_ref_processor_, ref_to_display); - color_values_widget_->SetColorProcessor(input_to_ref_processor_, ref_to_display, nullptr, ref_to_input); + color_wheel_->SetColorProcessor(input_to_ref_processor_, ref_to_display); + hsv_value_gradient_->SetColorProcessor(input_to_ref_processor_, + ref_to_display); + color_values_widget_->SetColorProcessor( + input_to_ref_processor_, ref_to_display, nullptr, ref_to_input); } } diff --git a/app/dialog/color/colordialog.h b/app/dialog/color/colordialog.h index 00edb730b..109001841 100644 --- a/app/dialog/color/colordialog.h +++ b/app/dialog/color/colordialog.h @@ -31,13 +31,13 @@ #include "widget/colorwheel/colorvalueswidget.h" #include "widget/colorwheel/colorwheelwidget.h" -namespace olive { - -class ColorDialog : public QDialog +namespace olive { - Q_OBJECT + +class ColorDialog : public QDialog { + Q_OBJECT public: - /** + /** * @brief ColorDialog Constructor * * @param color_manager @@ -56,40 +56,41 @@ public: * * QWidget parent. */ - ColorDialog(ColorManager* color_manager, const ManagedColor &start = Color(1.0f, 1.0f, 1.0f), QWidget* parent = nullptr); + ColorDialog(ColorManager *color_manager, + const ManagedColor &start = Color(1.0f, 1.0f, 1.0f), + QWidget *parent = nullptr); - /** + /** * @brief Retrieves the color selected by the user * * The color is always returned in the ColorManager's reference space (usually scene linear). */ - ManagedColor GetSelectedColor() const; + ManagedColor GetSelectedColor() const; - QString GetColorSpaceInput() const; + QString GetColorSpaceInput() const; - ColorTransform GetColorSpaceOutput() const; + ColorTransform GetColorSpaceOutput() const; public slots: - void SetColor(const ManagedColor &c); + void SetColor(const ManagedColor &c); private: - ColorManager* color_manager_; + ColorManager *color_manager_; - ColorWheelWidget* color_wheel_; + ColorWheelWidget *color_wheel_; - ColorValuesWidget* color_values_widget_; + ColorValuesWidget *color_values_widget_; - ColorGradientWidget* hsv_value_gradient_; + ColorGradientWidget *hsv_value_gradient_; - ColorProcessorPtr input_to_ref_processor_; + ColorProcessorPtr input_to_ref_processor_; - ColorSpaceChooser* chooser_; + ColorSpaceChooser *chooser_; - ColorSwatchChooser *swatch_; + ColorSwatchChooser *swatch_; private slots: - void ColorSpaceChanged(const QString& input, const ColorTransform &output); - + void ColorSpaceChanged(const QString &input, const ColorTransform &output); }; } diff --git a/app/dialog/configbase/configdialogbase.cpp b/app/dialog/configbase/configdialogbase.cpp index 152d5979a..cd237fa7e 100644 --- a/app/dialog/configbase/configdialogbase.cpp +++ b/app/dialog/configbase/configdialogbase.cpp @@ -26,66 +26,68 @@ #include "core.h" -namespace olive { - -ConfigDialogBase::ConfigDialogBase(QWidget* parent) : - QDialog(parent) +namespace olive { - QVBoxLayout* layout = new QVBoxLayout(this); - QSplitter* splitter = new QSplitter(); - splitter->setChildrenCollapsible(false); - layout->addWidget(splitter); +ConfigDialogBase::ConfigDialogBase(QWidget *parent) + : QDialog(parent) +{ + QVBoxLayout *layout = new QVBoxLayout(this); - list_widget_ = new QListWidget(); + QSplitter *splitter = new QSplitter(); + splitter->setChildrenCollapsible(false); + layout->addWidget(splitter); - preference_pane_stack_ = new QStackedWidget(this); + list_widget_ = new QListWidget(); - splitter->addWidget(list_widget_); - splitter->addWidget(preference_pane_stack_); + preference_pane_stack_ = new QStackedWidget(this); - QDialogButtonBox* button_box = new QDialogButtonBox(this); - button_box->setOrientation(Qt::Horizontal); - button_box->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::Ok); + splitter->addWidget(list_widget_); + splitter->addWidget(preference_pane_stack_); - layout->addWidget(button_box); + QDialogButtonBox *button_box = new QDialogButtonBox(this); + button_box->setOrientation(Qt::Horizontal); + button_box->setStandardButtons(QDialogButtonBox::Cancel | + QDialogButtonBox::Ok); - connect(button_box, &QDialogButtonBox::accepted, this, &ConfigDialogBase::accept); - connect(button_box, &QDialogButtonBox::rejected, this, &ConfigDialogBase::reject); + layout->addWidget(button_box); - connect(list_widget_, - &QListWidget::currentRowChanged, - preference_pane_stack_, - &QStackedWidget::setCurrentIndex); + connect(button_box, &QDialogButtonBox::accepted, this, + &ConfigDialogBase::accept); + connect(button_box, &QDialogButtonBox::rejected, this, + &ConfigDialogBase::reject); + + connect(list_widget_, &QListWidget::currentRowChanged, + preference_pane_stack_, &QStackedWidget::setCurrentIndex); } void ConfigDialogBase::accept() { - foreach (ConfigDialogBaseTab* tab, tabs_) { - if (!tab->Validate()) { - return; - } - } + foreach (ConfigDialogBaseTab *tab, tabs_) { + if (!tab->Validate()) { + return; + } + } - MultiUndoCommand* command = new MultiUndoCommand(); + MultiUndoCommand *command = new MultiUndoCommand(); - foreach (ConfigDialogBaseTab* tab, tabs_) { - tab->Accept(command); - } + foreach (ConfigDialogBaseTab *tab, tabs_) { + tab->Accept(command); + } - Core::instance()->undo_stack()->push(command, tr("Set Configuration")); + Core::instance()->undo_stack()->push(command, tr("Set Configuration")); - AcceptEvent(); + AcceptEvent(); - QDialog::accept(); + QDialog::accept(); } void ConfigDialogBase::AddTab(ConfigDialogBaseTab *tab, const QString &title) { - list_widget_->addItem(title); - preference_pane_stack_->addWidget(tab); + list_widget_->addItem(title); + preference_pane_stack_->addWidget(tab); - tabs_.append(tab); + tabs_.append(tab); } } diff --git a/app/dialog/configbase/configdialogbase.h b/app/dialog/configbase/configdialogbase.h index 35592175e..001abd5dc 100644 --- a/app/dialog/configbase/configdialogbase.h +++ b/app/dialog/configbase/configdialogbase.h @@ -27,32 +27,33 @@ #include "configdialogbasetab.h" -namespace olive { - -class ConfigDialogBase : public QDialog +namespace olive { - Q_OBJECT + +class ConfigDialogBase : public QDialog { + Q_OBJECT public: - ConfigDialogBase(QWidget* parent = nullptr); + ConfigDialogBase(QWidget *parent = nullptr); private slots: - /** + /** * @brief Override of accept to save preferences to Config. */ - virtual void accept() override; + virtual void accept() override; protected: - void AddTab(ConfigDialogBaseTab* tab, const QString& title); + void AddTab(ConfigDialogBaseTab *tab, const QString &title); - virtual void AcceptEvent(){} + virtual void AcceptEvent() + { + } private: - QListWidget* list_widget_; + QListWidget *list_widget_; - QStackedWidget* preference_pane_stack_; - - QList tabs_; + QStackedWidget *preference_pane_stack_; + QList tabs_; }; } diff --git a/app/dialog/configbase/configdialogbasetab.cpp b/app/dialog/configbase/configdialogbasetab.cpp index b40254912..f616cb34d 100644 --- a/app/dialog/configbase/configdialogbasetab.cpp +++ b/app/dialog/configbase/configdialogbasetab.cpp @@ -20,11 +20,12 @@ #include "configdialogbasetab.h" -namespace olive { +namespace olive +{ bool ConfigDialogBaseTab::Validate() { - return true; + return true; } } diff --git a/app/dialog/configbase/configdialogbasetab.h b/app/dialog/configbase/configdialogbasetab.h index cb31c0c43..9301b11dd 100644 --- a/app/dialog/configbase/configdialogbasetab.h +++ b/app/dialog/configbase/configdialogbasetab.h @@ -26,16 +26,16 @@ #include "config/config.h" #include "undo/undocommand.h" -namespace olive { - -class ConfigDialogBaseTab : public QWidget +namespace olive { + +class ConfigDialogBaseTab : public QWidget { public: - ConfigDialogBaseTab() = default; + ConfigDialogBaseTab() = default; - virtual bool Validate(); + virtual bool Validate(); - virtual void Accept(MultiUndoCommand *parent) = 0; + virtual void Accept(MultiUndoCommand *parent) = 0; }; } diff --git a/app/dialog/diskcache/diskcachedialog.cpp b/app/dialog/diskcache/diskcachedialog.cpp index 10adf836b..8c63e321b 100644 --- a/app/dialog/diskcache/diskcachedialog.cpp +++ b/app/dialog/diskcache/diskcachedialog.cpp @@ -28,86 +28,101 @@ #include "config/config.h" #include "core.h" -namespace olive { - -DiskCacheDialog::DiskCacheDialog(DiskCacheFolder *folder, QWidget* parent) : - QDialog(parent), - folder_(folder) +namespace olive { - QGridLayout* layout = new QGridLayout(this); - int row = 0; +DiskCacheDialog::DiskCacheDialog(DiskCacheFolder *folder, QWidget *parent) + : QDialog(parent) + , folder_(folder) +{ + QGridLayout *layout = new QGridLayout(this); - layout->addWidget(new QLabel(tr("Disk Cache: %1").arg(folder->GetPath())), row, 0, 1, 2); - setWindowTitle(tr("Disk Cache Settings")); + int row = 0; - row++; + layout->addWidget(new QLabel(tr("Disk Cache: %1").arg(folder->GetPath())), + row, 0, 1, 2); + setWindowTitle(tr("Disk Cache Settings")); - layout->addWidget(new QLabel(tr("Maximum Disk Cache:")), row, 0); + row++; - maximum_cache_slider_ = new FloatSlider(); - maximum_cache_slider_->SetFormat(tr("%1 GB")); - maximum_cache_slider_->SetMinimum(1.0); - maximum_cache_slider_->SetValue(static_cast(folder->GetLimit()) / static_cast(kBytesInGigabyte)); - layout->addWidget(maximum_cache_slider_, row, 1); + layout->addWidget(new QLabel(tr("Maximum Disk Cache:")), row, 0); - row++; + maximum_cache_slider_ = new FloatSlider(); + maximum_cache_slider_->SetFormat(tr("%1 GB")); + maximum_cache_slider_->SetMinimum(1.0); + maximum_cache_slider_->SetValue(static_cast(folder->GetLimit()) / + static_cast(kBytesInGigabyte)); + layout->addWidget(maximum_cache_slider_, row, 1); - clear_cache_btn_ = new QPushButton(tr("Clear Disk Cache")); - connect(clear_cache_btn_, &QPushButton::clicked, this, static_cast(&DiskCacheDialog::ClearDiskCache)); - layout->addWidget(clear_cache_btn_, row, 1); + row++; - row++; + clear_cache_btn_ = new QPushButton(tr("Clear Disk Cache")); + connect(clear_cache_btn_, &QPushButton::clicked, this, + static_cast( + &DiskCacheDialog::ClearDiskCache)); + layout->addWidget(clear_cache_btn_, row, 1); - clear_disk_cache_ = new QCheckBox(tr("Automatically clear disk cache on close")); - clear_disk_cache_->setChecked(folder->GetClearOnClose()); - layout->addWidget(clear_disk_cache_, row, 1); + row++; - row++; + clear_disk_cache_ = + new QCheckBox(tr("Automatically clear disk cache on close")); + clear_disk_cache_->setChecked(folder->GetClearOnClose()); + layout->addWidget(clear_disk_cache_, row, 1); - QDialogButtonBox* buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); - connect(buttons, &QDialogButtonBox::accepted, this, &DiskCacheDialog::accept); - connect(buttons, &QDialogButtonBox::rejected, this, &DiskCacheDialog::reject); - layout->addWidget(buttons, row, 0, 1, 2); + row++; + + QDialogButtonBox *buttons = + new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); + connect(buttons, &QDialogButtonBox::accepted, this, + &DiskCacheDialog::accept); + connect(buttons, &QDialogButtonBox::rejected, this, + &DiskCacheDialog::reject); + layout->addWidget(buttons, row, 0, 1, 2); } void DiskCacheDialog::accept() { - qint64 new_disk_cache_limit = qRound64(maximum_cache_slider_->GetValue() * kBytesInGigabyte); - if (new_disk_cache_limit != folder_->GetLimit()) { - folder_->SetLimit(new_disk_cache_limit); - } + qint64 new_disk_cache_limit = + qRound64(maximum_cache_slider_->GetValue() * kBytesInGigabyte); + if (new_disk_cache_limit != folder_->GetLimit()) { + folder_->SetLimit(new_disk_cache_limit); + } - if (folder_->GetClearOnClose() != clear_disk_cache_->isChecked()) { - folder_->SetClearOnClose(clear_disk_cache_->isChecked()); - } + if (folder_->GetClearOnClose() != clear_disk_cache_->isChecked()) { + folder_->SetClearOnClose(clear_disk_cache_->isChecked()); + } - QDialog::accept(); + QDialog::accept(); } void DiskCacheDialog::ClearDiskCache() { - ClearDiskCache(folder_->GetPath(), this, clear_cache_btn_); + ClearDiskCache(folder_->GetPath(), this, clear_cache_btn_); } -void DiskCacheDialog::ClearDiskCache(const QString &path, QWidget *parent, QPushButton *clear_btn) +void DiskCacheDialog::ClearDiskCache(const QString &path, QWidget *parent, + QPushButton *clear_btn) { - if (QMessageBox::question(parent, - tr("Clear Disk Cache"), - tr("Are you sure you want to clear the disk cache in '%1'?").arg(path), - QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) { - if (clear_btn) clear_btn->setEnabled(false); + if (QMessageBox::question( + parent, tr("Clear Disk Cache"), + tr("Are you sure you want to clear the disk cache in '%1'?") + .arg(path), + QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) { + if (clear_btn) + clear_btn->setEnabled(false); - if (DiskManager::instance()->ClearDiskCache(path)) { - if (clear_btn) clear_btn->setText(tr("Disk Cache Cleared")); - } else { - QMessageBox::information(parent, - tr("Clear Disk Cache"), - tr("Disk cache failed to fully clear. You may have to delete the cache files manually."), - QMessageBox::Ok); - if (clear_btn) clear_btn->setText(tr("Disk Cache Partially Cleared")); - } - } + if (DiskManager::instance()->ClearDiskCache(path)) { + if (clear_btn) + clear_btn->setText(tr("Disk Cache Cleared")); + } else { + QMessageBox::information( + parent, tr("Clear Disk Cache"), + tr("Disk cache failed to fully clear. You may have to delete the cache files manually."), + QMessageBox::Ok); + if (clear_btn) + clear_btn->setText(tr("Disk Cache Partially Cleared")); + } + } } } diff --git a/app/dialog/diskcache/diskcachedialog.h b/app/dialog/diskcache/diskcachedialog.h index b8aec8236..888f26b5e 100644 --- a/app/dialog/diskcache/diskcachedialog.h +++ b/app/dialog/diskcache/diskcachedialog.h @@ -28,31 +28,31 @@ #include "render/diskmanager.h" #include "widget/slider/floatslider.h" -namespace olive { - -class DiskCacheDialog : public QDialog +namespace olive { - Q_OBJECT -public: - DiskCacheDialog(DiskCacheFolder* folder, QWidget* parent = nullptr); - static void ClearDiskCache(const QString &path, QWidget *parent, QPushButton *clear_btn = nullptr); +class DiskCacheDialog : public QDialog { + Q_OBJECT +public: + DiskCacheDialog(DiskCacheFolder *folder, QWidget *parent = nullptr); + + static void ClearDiskCache(const QString &path, QWidget *parent, + QPushButton *clear_btn = nullptr); public slots: - virtual void accept() override; + virtual void accept() override; private: - DiskCacheFolder* folder_; + DiskCacheFolder *folder_; - FloatSlider* maximum_cache_slider_; + FloatSlider *maximum_cache_slider_; - QCheckBox* clear_disk_cache_; + QCheckBox *clear_disk_cache_; - QPushButton* clear_cache_btn_; + QPushButton *clear_cache_btn_; private slots: - void ClearDiskCache(); - + void ClearDiskCache(); }; } diff --git a/app/dialog/export/codec/av1section.cpp b/app/dialog/export/codec/av1section.cpp index 8c65d1bc6..0a4136f5d 100644 --- a/app/dialog/export/codec/av1section.cpp +++ b/app/dialog/export/codec/av1section.cpp @@ -28,105 +28,111 @@ #include "common/qtutils.h" #include "widget/slider/integerslider.h" -namespace olive { +namespace olive +{ -AV1Section::AV1Section(QWidget *parent) : - AV1Section(AV1CRFSection::kDefaultAV1CRF, parent) +AV1Section::AV1Section(QWidget *parent) + : AV1Section(AV1CRFSection::kDefaultAV1CRF, parent) { } -AV1Section::AV1Section(int default_crf, QWidget *parent) : - CodecSection(parent) +AV1Section::AV1Section(int default_crf, QWidget *parent) + : CodecSection(parent) { - QGridLayout* layout = new QGridLayout(this); - layout->setContentsMargins(0, 0, 0, 0); + QGridLayout *layout = new QGridLayout(this); + layout->setContentsMargins(0, 0, 0, 0); - int row = 0; - layout->addWidget(new QLabel(tr("Preset:")), row, 0); + int row = 0; + layout->addWidget(new QLabel(tr("Preset:")), row, 0); - preset_combobox_ = new QComboBox(); - preset_combobox_->setToolTip(tr("This parameter governs the efficiency/encode-time trade-off.\n" - "Lower presets will result in an output with better quality for a given file size, but will take longer to encode.\n" - "Higher presets can result in a very fast encode, but will make some compromises on visual quality for a given crf value.")); + preset_combobox_ = new QComboBox(); + preset_combobox_->setToolTip(tr( + "This parameter governs the efficiency/encode-time trade-off.\n" + "Lower presets will result in an output with better quality for a given file size, but will take longer to encode.\n" + "Higher presets can result in a very fast encode, but will make some compromises on visual quality for a given crf value.")); - for (int i = 0; i <= 13; i++) - preset_combobox_->addItem(QString::number(i)); + for (int i = 0; i <= 13; i++) + preset_combobox_->addItem(QString::number(i)); - preset_combobox_->setCurrentIndex(8); + preset_combobox_->setCurrentIndex(8); - layout->addWidget(preset_combobox_, row, 1); + layout->addWidget(preset_combobox_, row, 1); - row++; + row++; - layout->addWidget(new QLabel(tr("Compression Method:")), row, 0); + layout->addWidget(new QLabel(tr("Compression Method:")), row, 0); - QComboBox* compression_box = new QComboBox(); - compression_box->setToolTip(tr("This parameter governs the quality/size trade-off.\n" - "Higher CRF values will result in a final output that takes less space, but begins to lose detail.\n" - "Lower CRF values retain more detail at the cost of larger file sizes.\n" - "The possible range of CRF in SVT-AV1 is 1-63.")); + QComboBox *compression_box = new QComboBox(); + compression_box->setToolTip(tr( + "This parameter governs the quality/size trade-off.\n" + "Higher CRF values will result in a final output that takes less space, but begins to lose detail.\n" + "Lower CRF values retain more detail at the cost of larger file sizes.\n" + "The possible range of CRF in SVT-AV1 is 1-63.")); - // These items must correspond to the CompressionMethod enum - compression_box->addItem(tr("Constant Rate Factor")); + // These items must correspond to the CompressionMethod enum + compression_box->addItem(tr("Constant Rate Factor")); - layout->addWidget(compression_box, row, 1); + layout->addWidget(compression_box, row, 1); - row++; + row++; - compression_method_stack_ = new QStackedWidget(); - layout->addWidget(compression_method_stack_, row, 0, 1, 2); + compression_method_stack_ = new QStackedWidget(); + layout->addWidget(compression_method_stack_, row, 0, 1, 2); - crf_section_ = new AV1CRFSection(default_crf); - compression_method_stack_->addWidget(crf_section_); + crf_section_ = new AV1CRFSection(default_crf); + compression_method_stack_->addWidget(crf_section_); - connect(compression_box, - static_cast(&QComboBox::currentIndexChanged), - compression_method_stack_, - &QStackedWidget::setCurrentIndex); + connect( + compression_box, + static_cast(&QComboBox::currentIndexChanged), + compression_method_stack_, &QStackedWidget::setCurrentIndex); } void AV1Section::AddOpts(EncodingParams *params) { + CompressionMethod method = static_cast( + compression_method_stack_->currentIndex()); - CompressionMethod method = static_cast(compression_method_stack_->currentIndex()); + if (method == kConstantRateFactor) { + // Set Quantizer value + params->set_video_option(QStringLiteral("qp"), + QString::number(crf_section_->GetValue())); + } - if (method == kConstantRateFactor) { - - // Set Quantizer value - params->set_video_option(QStringLiteral("qp"), QString::number(crf_section_->GetValue())); - - } - - params->set_video_option(QStringLiteral("preset"), QString::number(preset_combobox_->currentIndex())); + params->set_video_option(QStringLiteral("preset"), + QString::number(preset_combobox_->currentIndex())); } -AV1CRFSection::AV1CRFSection(int default_crf, QWidget *parent) : - QWidget(parent) +AV1CRFSection::AV1CRFSection(int default_crf, QWidget *parent) + : QWidget(parent) { - QHBoxLayout* layout = new QHBoxLayout(this); - layout->setContentsMargins(0, 0, 0, 0); + QHBoxLayout *layout = new QHBoxLayout(this); + layout->setContentsMargins(0, 0, 0, 0); - crf_slider_ = new QSlider(Qt::Horizontal); - crf_slider_->setMinimum(kMinimumCRF); - crf_slider_->setMaximum(kMaximumCRF); - crf_slider_->setValue(default_crf); - layout->addWidget(crf_slider_); + crf_slider_ = new QSlider(Qt::Horizontal); + crf_slider_->setMinimum(kMinimumCRF); + crf_slider_->setMaximum(kMaximumCRF); + crf_slider_->setValue(default_crf); + layout->addWidget(crf_slider_); - IntegerSlider* crf_input = new IntegerSlider(); - crf_input->setMaximumWidth(QtUtils::QFontMetricsWidth(crf_input->fontMetrics(), QStringLiteral("HHHH"))); - crf_input->SetMinimum(kMinimumCRF); - crf_input->SetMaximum(kMaximumCRF); - crf_input->SetValue(default_crf); - crf_input->SetDefaultValue(default_crf); - layout->addWidget(crf_input); + IntegerSlider *crf_input = new IntegerSlider(); + crf_input->setMaximumWidth(QtUtils::QFontMetricsWidth( + crf_input->fontMetrics(), QStringLiteral("HHHH"))); + crf_input->SetMinimum(kMinimumCRF); + crf_input->SetMaximum(kMaximumCRF); + crf_input->SetValue(default_crf); + crf_input->SetDefaultValue(default_crf); + layout->addWidget(crf_input); - connect(crf_slider_, &QSlider::valueChanged, crf_input, &IntegerSlider::SetValue); - connect(crf_input, &IntegerSlider::ValueChanged, crf_slider_, &QSlider::setValue); + connect(crf_slider_, &QSlider::valueChanged, crf_input, + &IntegerSlider::SetValue); + connect(crf_input, &IntegerSlider::ValueChanged, crf_slider_, + &QSlider::setValue); } int AV1CRFSection::GetValue() const { - return crf_slider_->value(); + return crf_slider_->value(); } } diff --git a/app/dialog/export/codec/av1section.h b/app/dialog/export/codec/av1section.h index 065485fbc..bbc8b0a7f 100644 --- a/app/dialog/export/codec/av1section.h +++ b/app/dialog/export/codec/av1section.h @@ -28,45 +28,43 @@ #include "codecsection.h" #include "widget/slider/floatslider.h" -namespace olive { - -class AV1CRFSection : public QWidget +namespace olive { - Q_OBJECT + +class AV1CRFSection : public QWidget { + Q_OBJECT public: - AV1CRFSection(int default_crf, QWidget* parent = nullptr); + AV1CRFSection(int default_crf, QWidget *parent = nullptr); - int GetValue() const; + int GetValue() const; - static const int kDefaultAV1CRF = 30; + static const int kDefaultAV1CRF = 30; private: - static const int kMinimumCRF = 0; - static const int kMaximumCRF = 63; - - QSlider* crf_slider_; + static const int kMinimumCRF = 0; + static const int kMaximumCRF = 63; + QSlider *crf_slider_; }; -class AV1Section : public CodecSection -{ - Q_OBJECT +class AV1Section : public CodecSection { + Q_OBJECT public: - enum CompressionMethod { - kConstantRateFactor, - }; + enum CompressionMethod { + kConstantRateFactor, + }; - AV1Section(QWidget* parent = nullptr); - AV1Section(int default_crf, QWidget* parent); + AV1Section(QWidget *parent = nullptr); + AV1Section(int default_crf, QWidget *parent); - virtual void AddOpts(EncodingParams* params) override; + virtual void AddOpts(EncodingParams *params) override; private: - QStackedWidget* compression_method_stack_; + QStackedWidget *compression_method_stack_; - AV1CRFSection* crf_section_; + AV1CRFSection *crf_section_; - QComboBox *preset_combobox_; + QComboBox *preset_combobox_; }; } diff --git a/app/dialog/export/codec/cineformsection.cpp b/app/dialog/export/codec/cineformsection.cpp index 9cae58409..f102a6501 100644 --- a/app/dialog/export/codec/cineformsection.cpp +++ b/app/dialog/export/codec/cineformsection.cpp @@ -23,22 +23,23 @@ #include #include -namespace olive { - -CineformSection::CineformSection(QWidget *parent) : - CodecSection(parent) +namespace olive { - QGridLayout *layout = new QGridLayout(this); - layout->setContentsMargins(0, 0, 0, 0); +CineformSection::CineformSection(QWidget *parent) + : CodecSection(parent) +{ + QGridLayout *layout = new QGridLayout(this); - int row = 0; + layout->setContentsMargins(0, 0, 0, 0); - layout->addWidget(new QLabel(tr("Quality:")), row, 0); + int row = 0; - quality_combobox_ = new QComboBox(); + layout->addWidget(new QLabel(tr("Quality:")), row, 0); - /* Correspond to the following indexes for FFmpeg + quality_combobox_ = new QComboBox(); + + /* Correspond to the following indexes for FFmpeg * * -quality E..V....... set quality (from 0 to 12) (default film3+) * film3+ 0 E..V....... @@ -57,34 +58,37 @@ CineformSection::CineformSection(QWidget *parent) : * */ - quality_combobox_->addItem(tr("Film Scan 3+")); - quality_combobox_->addItem(tr("Film Scan 3")); - quality_combobox_->addItem(tr("Film Scan 2+")); - quality_combobox_->addItem(tr("Film Scan 2")); - quality_combobox_->addItem(tr("Film Scan 1.5")); - quality_combobox_->addItem(tr("Film Scan 1+")); - quality_combobox_->addItem(tr("Film Scan 1")); - quality_combobox_->addItem(tr("High+")); - quality_combobox_->addItem(tr("High")); - quality_combobox_->addItem(tr("Medium+")); - quality_combobox_->addItem(tr("Medium")); - quality_combobox_->addItem(tr("Low+")); - quality_combobox_->addItem(tr("Low")); + quality_combobox_->addItem(tr("Film Scan 3+")); + quality_combobox_->addItem(tr("Film Scan 3")); + quality_combobox_->addItem(tr("Film Scan 2+")); + quality_combobox_->addItem(tr("Film Scan 2")); + quality_combobox_->addItem(tr("Film Scan 1.5")); + quality_combobox_->addItem(tr("Film Scan 1+")); + quality_combobox_->addItem(tr("Film Scan 1")); + quality_combobox_->addItem(tr("High+")); + quality_combobox_->addItem(tr("High")); + quality_combobox_->addItem(tr("Medium+")); + quality_combobox_->addItem(tr("Medium")); + quality_combobox_->addItem(tr("Low+")); + quality_combobox_->addItem(tr("Low")); - // Default to "medium" - quality_combobox_->setCurrentIndex(10); + // Default to "medium" + quality_combobox_->setCurrentIndex(10); - layout->addWidget(quality_combobox_, row, 1); + layout->addWidget(quality_combobox_, row, 1); } void CineformSection::AddOpts(EncodingParams *params) { - params->set_video_option(QStringLiteral("quality"), QString::number(quality_combobox_->currentIndex())); + params->set_video_option( + QStringLiteral("quality"), + QString::number(quality_combobox_->currentIndex())); } void CineformSection::SetOpts(const EncodingParams *p) { - quality_combobox_->setCurrentIndex(p->video_option(QStringLiteral("quality")).toInt()); + quality_combobox_->setCurrentIndex( + p->video_option(QStringLiteral("quality")).toInt()); } } diff --git a/app/dialog/export/codec/cineformsection.h b/app/dialog/export/codec/cineformsection.h index 8a3a08491..f77822972 100644 --- a/app/dialog/export/codec/cineformsection.h +++ b/app/dialog/export/codec/cineformsection.h @@ -25,21 +25,20 @@ #include "codecsection.h" -namespace olive { - -class CineformSection : public CodecSection +namespace olive { - Q_OBJECT + +class CineformSection : public CodecSection { + Q_OBJECT public: - CineformSection(QWidget *parent = nullptr); + CineformSection(QWidget *parent = nullptr); - virtual void AddOpts(EncodingParams* params) override; + virtual void AddOpts(EncodingParams *params) override; - virtual void SetOpts(const EncodingParams *p) override; + virtual void SetOpts(const EncodingParams *p) override; private: - QComboBox *quality_combobox_; - + QComboBox *quality_combobox_; }; } diff --git a/app/dialog/export/codec/codecsection.cpp b/app/dialog/export/codec/codecsection.cpp index 37ce0e1cd..497f4153a 100644 --- a/app/dialog/export/codec/codecsection.cpp +++ b/app/dialog/export/codec/codecsection.cpp @@ -20,10 +20,11 @@ #include "codecsection.h" -namespace olive { +namespace olive +{ -CodecSection::CodecSection(QWidget *parent) : - QWidget(parent) +CodecSection::CodecSection(QWidget *parent) + : QWidget(parent) { } diff --git a/app/dialog/export/codec/codecsection.h b/app/dialog/export/codec/codecsection.h index 93eebaa1d..5a43594e1 100644 --- a/app/dialog/export/codec/codecsection.h +++ b/app/dialog/export/codec/codecsection.h @@ -25,18 +25,23 @@ #include "codec/encoder.h" -namespace olive { - -class CodecSection : public QWidget +namespace olive { - Q_OBJECT + +class CodecSection : public QWidget { + Q_OBJECT public: - CodecSection(QWidget* parent = nullptr); + CodecSection(QWidget *parent = nullptr); - virtual void AddOpts(EncodingParams* params){Q_UNUSED(params)} - - virtual void SetOpts(const EncodingParams *p){Q_UNUSED(p)} + virtual void AddOpts(EncodingParams *params) + { + Q_UNUSED(params) + } + virtual void SetOpts(const EncodingParams *p) + { + Q_UNUSED(p) + } }; } diff --git a/app/dialog/export/codec/codecstack.cpp b/app/dialog/export/codec/codecstack.cpp index d857536b4..1845f1121 100644 --- a/app/dialog/export/codec/codecstack.cpp +++ b/app/dialog/export/codec/codecstack.cpp @@ -20,34 +20,37 @@ #include "codecstack.h" -namespace olive { +namespace olive +{ #define super QStackedWidget CodecStack::CodecStack(QWidget *parent) - : super{parent} + : super{ parent } { - connect(this, &CodecStack::currentChanged, this, &CodecStack::OnChange); + connect(this, &CodecStack::currentChanged, this, &CodecStack::OnChange); } void CodecStack::addWidget(QWidget *widget) { - super::addWidget(widget); + super::addWidget(widget); - OnChange(currentIndex()); + OnChange(currentIndex()); } void CodecStack::OnChange(int index) { - for (int i=0; isetSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); - } else { - widget(i)->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored); - } - widget(i)->adjustSize(); - } - adjustSize(); + for (int i = 0; i < count(); i++) { + if (i == index) { + widget(i)->setSizePolicy(QSizePolicy::Expanding, + QSizePolicy::Expanding); + } else { + widget(i)->setSizePolicy(QSizePolicy::Ignored, + QSizePolicy::Ignored); + } + widget(i)->adjustSize(); + } + adjustSize(); } } diff --git a/app/dialog/export/codec/codecstack.h b/app/dialog/export/codec/codecstack.h index ebfaf3964..352954d45 100644 --- a/app/dialog/export/codec/codecstack.h +++ b/app/dialog/export/codec/codecstack.h @@ -23,21 +23,20 @@ #include -namespace olive { - -class CodecStack : public QStackedWidget +namespace olive { - Q_OBJECT -public: - explicit CodecStack(QWidget *parent = nullptr); - void addWidget(QWidget *widget); +class CodecStack : public QStackedWidget { + Q_OBJECT +public: + explicit CodecStack(QWidget *parent = nullptr); + + void addWidget(QWidget *widget); signals: private slots: - void OnChange(int index); - + void OnChange(int index); }; } diff --git a/app/dialog/export/codec/h264section.cpp b/app/dialog/export/codec/h264section.cpp index 0d50312e4..7a4cf520b 100644 --- a/app/dialog/export/codec/h264section.cpp +++ b/app/dialog/export/codec/h264section.cpp @@ -28,274 +28,284 @@ #include "common/qtutils.h" #include "widget/slider/integerslider.h" -namespace olive { +namespace olive +{ -H264Section::H264Section(QWidget *parent) : - H264Section(H264CRFSection::kDefaultH264CRF, parent) +H264Section::H264Section(QWidget *parent) + : H264Section(H264CRFSection::kDefaultH264CRF, parent) { } -H264Section::H264Section(int default_crf, QWidget *parent) : - CodecSection(parent) +H264Section::H264Section(int default_crf, QWidget *parent) + : CodecSection(parent) { - QGridLayout* layout = new QGridLayout(this); - layout->setContentsMargins(0, 0, 0, 0); + QGridLayout *layout = new QGridLayout(this); + layout->setContentsMargins(0, 0, 0, 0); - int row = 0; - layout->addWidget(new QLabel(tr("Encode Speed:")), row, 0); + int row = 0; + layout->addWidget(new QLabel(tr("Encode Speed:")), row, 0); + preset_combobox_ = new QComboBox(); + preset_combobox_->setToolTip(tr( + "This setting allows you to tweak the ratio of export speed to compression quality. \n\n" + "If using Constant Rate Factor, slower speeds will result in smaller file sizes for the same quality. \n\n" + "If using Target Bit Rate or Target File Size, slower speeds will result in higher quality for the same bitrate/filesize. \n\n" + "This setting is equivalent to the `preset` setting in libx264.")); - preset_combobox_ = new QComboBox(); - preset_combobox_->setToolTip(tr("This setting allows you to tweak the ratio of export speed to compression quality. \n\n" - "If using Constant Rate Factor, slower speeds will result in smaller file sizes for the same quality. \n\n" - "If using Target Bit Rate or Target File Size, slower speeds will result in higher quality for the same bitrate/filesize. \n\n" - "This setting is equivalent to the `preset` setting in libx264.")); + preset_combobox_->addItem(tr("Ultra Fast")); + preset_combobox_->addItem(tr("Super Fast")); + preset_combobox_->addItem(tr("Very Fast")); + preset_combobox_->addItem(tr("Faster")); + preset_combobox_->addItem(tr("Fast")); + preset_combobox_->addItem(tr("Medium")); + preset_combobox_->addItem(tr("Slow")); + preset_combobox_->addItem(tr("Slower")); + preset_combobox_->addItem(tr("Very Slow")); - preset_combobox_->addItem(tr("Ultra Fast")); - preset_combobox_->addItem(tr("Super Fast")); - preset_combobox_->addItem(tr("Very Fast")); - preset_combobox_->addItem(tr("Faster")); - preset_combobox_->addItem(tr("Fast")); - preset_combobox_->addItem(tr("Medium")); - preset_combobox_->addItem(tr("Slow")); - preset_combobox_->addItem(tr("Slower")); - preset_combobox_->addItem(tr("Very Slow")); + //Default to "medium" + preset_combobox_->setCurrentIndex(5); - //Default to "medium" - preset_combobox_->setCurrentIndex(5); + layout->addWidget(preset_combobox_, row, 1); - layout->addWidget(preset_combobox_, row, 1); + row++; - row++; + layout->addWidget(new QLabel(tr("Compression Method:")), row, 0); - layout->addWidget(new QLabel(tr("Compression Method:")), row, 0); + QComboBox *compression_box = new QComboBox(); - QComboBox* compression_box = new QComboBox(); + // These items must correspond to the CompressionMethod enum + compression_box->addItem(tr("Constant Rate Factor")); + compression_box->addItem(tr("Target Bit Rate")); + compression_box->addItem(tr("Target File Size")); - // These items must correspond to the CompressionMethod enum - compression_box->addItem(tr("Constant Rate Factor")); - compression_box->addItem(tr("Target Bit Rate")); - compression_box->addItem(tr("Target File Size")); + layout->addWidget(compression_box, row, 1); - layout->addWidget(compression_box, row, 1); + row++; - row++; + compression_method_stack_ = new QStackedWidget(); + layout->addWidget(compression_method_stack_, row, 0, 1, 2); - compression_method_stack_ = new QStackedWidget(); - layout->addWidget(compression_method_stack_, row, 0, 1, 2); + crf_section_ = new H264CRFSection(default_crf); + compression_method_stack_->addWidget(crf_section_); - crf_section_ = new H264CRFSection(default_crf); - compression_method_stack_->addWidget(crf_section_); + bitrate_section_ = new H264BitRateSection(); + compression_method_stack_->addWidget(bitrate_section_); - bitrate_section_ = new H264BitRateSection(); - compression_method_stack_->addWidget(bitrate_section_); + filesize_section_ = new H264FileSizeSection(); + compression_method_stack_->addWidget(filesize_section_); - filesize_section_ = new H264FileSizeSection(); - compression_method_stack_->addWidget(filesize_section_); - - connect(compression_box, - static_cast(&QComboBox::currentIndexChanged), - compression_method_stack_, - &QStackedWidget::setCurrentIndex); + connect( + compression_box, + static_cast(&QComboBox::currentIndexChanged), + compression_method_stack_, &QStackedWidget::setCurrentIndex); } void H264Section::AddOpts(EncodingParams *params) { - // FIXME: Implement two-pass + // FIXME: Implement two-pass - CompressionMethod method = static_cast(compression_method_stack_->currentIndex()); + CompressionMethod method = static_cast( + compression_method_stack_->currentIndex()); - // This option is not used by the encoder (nor is anything with the ove_ prefix), it's to help us - // identify which option was chosen when params are restored - params->set_video_option(QStringLiteral("ove_compressionmethod"), QString::number(method)); + // This option is not used by the encoder (nor is anything with the ove_ prefix), it's to help us + // identify which option was chosen when params are restored + params->set_video_option(QStringLiteral("ove_compressionmethod"), + QString::number(method)); - if (method == kConstantRateFactor) { + if (method == kConstantRateFactor) { + // Simply set CRF value + params->set_video_option(QStringLiteral("crf"), + QString::number(crf_section_->GetValue())); - // Simply set CRF value - params->set_video_option(QStringLiteral("crf"), QString::number(crf_section_->GetValue())); + } else { + int64_t target_rate, max_rate, min_rate; - } else { + if (method == kTargetBitRate) { + // Use user-supplied values for the bit rate + target_rate = bitrate_section_->GetTargetBitRate(); + min_rate = 0; + max_rate = bitrate_section_->GetMaximumBitRate(); + } else { + // Calculate the bit rate from the file size divided by the sequence length in seconds (bits per second) + int64_t target_fs = filesize_section_->GetFileSize(); + target_rate = qRound64(static_cast(target_fs) / + params->GetExportLength().toDouble()); + min_rate = target_rate; + max_rate = target_rate; - int64_t target_rate, max_rate, min_rate; + params->set_video_option(QStringLiteral("ove_targetfilesize"), + QString::number(target_fs)); + } - if (method == kTargetBitRate) { - // Use user-supplied values for the bit rate - target_rate = bitrate_section_->GetTargetBitRate(); - min_rate = 0; - max_rate = bitrate_section_->GetMaximumBitRate(); - } else { - // Calculate the bit rate from the file size divided by the sequence length in seconds (bits per second) - int64_t target_fs = filesize_section_->GetFileSize(); - target_rate = qRound64(static_cast(target_fs) / params->GetExportLength().toDouble()); - min_rate = target_rate; - max_rate = target_rate; + // Disable CRF encoding + params->set_video_option(QStringLiteral("crf"), QStringLiteral("-1")); - params->set_video_option(QStringLiteral("ove_targetfilesize"), QString::number(target_fs)); - } + params->set_video_bit_rate(target_rate); + params->set_video_min_bit_rate(min_rate); + params->set_video_max_bit_rate(max_rate); + params->set_video_buffer_size(2000000); + } - // Disable CRF encoding - params->set_video_option(QStringLiteral("crf"), QStringLiteral("-1")); - - params->set_video_bit_rate(target_rate); - params->set_video_min_bit_rate(min_rate); - params->set_video_max_bit_rate(max_rate); - params->set_video_buffer_size(2000000); - - } - - params->set_video_option(QStringLiteral("preset"), QString::number(preset_combobox_->currentIndex())); + params->set_video_option(QStringLiteral("preset"), + QString::number(preset_combobox_->currentIndex())); } void H264Section::SetOpts(const EncodingParams *p) { - CompressionMethod method = static_cast(p->video_option(QStringLiteral("ove_compressionmethod")).toInt()); + CompressionMethod method = static_cast( + p->video_option(QStringLiteral("ove_compressionmethod")).toInt()); - compression_method_stack_->setCurrentIndex(method); + compression_method_stack_->setCurrentIndex(method); - if (method == kConstantRateFactor) { - crf_section_->SetValue(p->video_option(QStringLiteral("crf")).toInt()); - } else { - int64_t target_rate = p->video_bit_rate(); - int64_t max_rate = p->video_max_bit_rate(); + if (method == kConstantRateFactor) { + crf_section_->SetValue(p->video_option(QStringLiteral("crf")).toInt()); + } else { + int64_t target_rate = p->video_bit_rate(); + int64_t max_rate = p->video_max_bit_rate(); - if (method == kTargetBitRate) { - // Use user-supplied values for the bit rate - bitrate_section_->SetTargetBitRate(target_rate); - bitrate_section_->SetMaximumBitRate(max_rate); - } else { - // Calculate the bit rate from the file size divided by the sequence length in seconds (bits per second) - filesize_section_->SetFileSize(p->video_option(QStringLiteral("ove_targetfilesize")).toLongLong()); - } - } + if (method == kTargetBitRate) { + // Use user-supplied values for the bit rate + bitrate_section_->SetTargetBitRate(target_rate); + bitrate_section_->SetMaximumBitRate(max_rate); + } else { + // Calculate the bit rate from the file size divided by the sequence length in seconds (bits per second) + filesize_section_->SetFileSize( + p->video_option(QStringLiteral("ove_targetfilesize")) + .toLongLong()); + } + } } -H264CRFSection::H264CRFSection(int default_crf, QWidget *parent) : - QWidget(parent) +H264CRFSection::H264CRFSection(int default_crf, QWidget *parent) + : QWidget(parent) { - QHBoxLayout* layout = new QHBoxLayout(this); - layout->setContentsMargins(0, 0, 0, 0); + QHBoxLayout *layout = new QHBoxLayout(this); + layout->setContentsMargins(0, 0, 0, 0); - crf_slider_ = new QSlider(Qt::Horizontal); - crf_slider_->setMinimum(kMinimumCRF); - crf_slider_->setMaximum(kMaximumCRF); - crf_slider_->setValue(default_crf); - layout->addWidget(crf_slider_); + crf_slider_ = new QSlider(Qt::Horizontal); + crf_slider_->setMinimum(kMinimumCRF); + crf_slider_->setMaximum(kMaximumCRF); + crf_slider_->setValue(default_crf); + layout->addWidget(crf_slider_); - IntegerSlider* crf_input = new IntegerSlider(); - crf_input->setMaximumWidth(QtUtils::QFontMetricsWidth(crf_input->fontMetrics(), QStringLiteral("HHHH"))); - crf_input->SetMinimum(kMinimumCRF); - crf_input->SetMaximum(kMaximumCRF); - crf_input->SetValue(default_crf); - crf_input->SetDefaultValue(default_crf); - layout->addWidget(crf_input); + IntegerSlider *crf_input = new IntegerSlider(); + crf_input->setMaximumWidth(QtUtils::QFontMetricsWidth( + crf_input->fontMetrics(), QStringLiteral("HHHH"))); + crf_input->SetMinimum(kMinimumCRF); + crf_input->SetMaximum(kMaximumCRF); + crf_input->SetValue(default_crf); + crf_input->SetDefaultValue(default_crf); + layout->addWidget(crf_input); - connect(crf_slider_, &QSlider::valueChanged, crf_input, &IntegerSlider::SetValue); - connect(crf_input, &IntegerSlider::ValueChanged, crf_slider_, &QSlider::setValue); + connect(crf_slider_, &QSlider::valueChanged, crf_input, + &IntegerSlider::SetValue); + connect(crf_input, &IntegerSlider::ValueChanged, crf_slider_, + &QSlider::setValue); } int H264CRFSection::GetValue() const { - return crf_slider_->value(); + return crf_slider_->value(); } void H264CRFSection::SetValue(int c) { - crf_slider_->setValue(c); + crf_slider_->setValue(c); } -H264BitRateSection::H264BitRateSection(QWidget *parent) : - QWidget(parent) +H264BitRateSection::H264BitRateSection(QWidget *parent) + : QWidget(parent) { - QGridLayout* layout = new QGridLayout(this); - layout->setContentsMargins(0, 0, 0, 0); + QGridLayout *layout = new QGridLayout(this); + layout->setContentsMargins(0, 0, 0, 0); - int row = 0; + int row = 0; - layout->addWidget(new QLabel(tr("Target Bit Rate (Mbps):")), row, 0); + layout->addWidget(new QLabel(tr("Target Bit Rate (Mbps):")), row, 0); - target_rate_ = new FloatSlider(); - target_rate_->SetMinimum(0); - layout->addWidget(target_rate_, row, 1); + target_rate_ = new FloatSlider(); + target_rate_->SetMinimum(0); + layout->addWidget(target_rate_, row, 1); - row++; + row++; - layout->addWidget(new QLabel(tr("Maximum Bit Rate (Mbps):")), row, 0); + layout->addWidget(new QLabel(tr("Maximum Bit Rate (Mbps):")), row, 0); - max_rate_ = new FloatSlider(); - max_rate_->SetMinimum(0); - layout->addWidget(max_rate_, row, 1); + max_rate_ = new FloatSlider(); + max_rate_->SetMinimum(0); + layout->addWidget(max_rate_, row, 1); - row++; + row++; - layout->addWidget(new QLabel(tr("Two-Pass")), row, 0); + layout->addWidget(new QLabel(tr("Two-Pass")), row, 0); - QCheckBox* two_pass_box = new QCheckBox(); - layout->addWidget(two_pass_box, row, 1); + QCheckBox *two_pass_box = new QCheckBox(); + layout->addWidget(two_pass_box, row, 1); - // Bit rate defaults - target_rate_->SetValue(16.0); - max_rate_->SetValue(32.0); + // Bit rate defaults + target_rate_->SetValue(16.0); + max_rate_->SetValue(32.0); } int64_t H264BitRateSection::GetTargetBitRate() const { - return qRound64(target_rate_->GetValue() * 1000000.0); + return qRound64(target_rate_->GetValue() * 1000000.0); } void H264BitRateSection::SetTargetBitRate(int64_t b) { - target_rate_->SetValue(double(b) * 0.000001); + target_rate_->SetValue(double(b) * 0.000001); } int64_t H264BitRateSection::GetMaximumBitRate() const { - return qRound64(max_rate_->GetValue() * 1000000.0); + return qRound64(max_rate_->GetValue() * 1000000.0); } void H264BitRateSection::SetMaximumBitRate(int64_t b) { - max_rate_->SetValue(double(b) * 0.000001); + max_rate_->SetValue(double(b) * 0.000001); } -H264FileSizeSection::H264FileSizeSection(QWidget *parent) : - QWidget(parent) +H264FileSizeSection::H264FileSizeSection(QWidget *parent) + : QWidget(parent) { - QGridLayout* layout = new QGridLayout(this); - layout->setContentsMargins(0, 0, 0, 0); + QGridLayout *layout = new QGridLayout(this); + layout->setContentsMargins(0, 0, 0, 0); - int row = 0; + int row = 0; - layout->addWidget(new QLabel(tr("Target File Size (MB):")), row, 0); + layout->addWidget(new QLabel(tr("Target File Size (MB):")), row, 0); - file_size_ = new FloatSlider(); - file_size_->SetMinimum(0); - layout->addWidget(file_size_, row, 1); + file_size_ = new FloatSlider(); + file_size_->SetMinimum(0); + layout->addWidget(file_size_, row, 1); - row++; + row++; - layout->addWidget(new QLabel(tr("Two-Pass")), row, 0); + layout->addWidget(new QLabel(tr("Two-Pass")), row, 0); - QCheckBox* two_pass_box = new QCheckBox(); - layout->addWidget(two_pass_box, row, 1); + QCheckBox *two_pass_box = new QCheckBox(); + layout->addWidget(two_pass_box, row, 1); - // File size defaults - file_size_->SetValue(700.0); + // File size defaults + file_size_->SetValue(700.0); } int64_t H264FileSizeSection::GetFileSize() const { - // Convert megabytes to BITS - return qRound64(file_size_->GetValue() * 1024.0 * 1024.0 * 8.0); + // Convert megabytes to BITS + return qRound64(file_size_->GetValue() * 1024.0 * 1024.0 * 8.0); } void H264FileSizeSection::SetFileSize(int64_t f) { - // Convert bits back to megabytes - file_size_->SetValue(double(f) / 8.0 / 1024.0 / 1024.0); + // Convert bits back to megabytes + file_size_->SetValue(double(f) / 8.0 / 1024.0 / 1024.0); } -H265Section::H265Section(QWidget *parent) : - H264Section(H264CRFSection::kDefaultH265CRF, parent) +H265Section::H265Section(QWidget *parent) + : H264Section(H264CRFSection::kDefaultH265CRF, parent) { } diff --git a/app/dialog/export/codec/h264section.h b/app/dialog/export/codec/h264section.h index 9fd984ae5..d54e793c3 100644 --- a/app/dialog/export/codec/h264section.h +++ b/app/dialog/export/codec/h264section.h @@ -28,104 +28,97 @@ #include "codecsection.h" #include "widget/slider/floatslider.h" -namespace olive { - -class H264CRFSection : public QWidget +namespace olive { - Q_OBJECT + +class H264CRFSection : public QWidget { + Q_OBJECT public: - H264CRFSection(int default_crf, QWidget* parent = nullptr); + H264CRFSection(int default_crf, QWidget *parent = nullptr); - int GetValue() const; - void SetValue(int c); + int GetValue() const; + void SetValue(int c); - static const int kDefaultH264CRF = 18; - static const int kDefaultH265CRF = 23; + static const int kDefaultH264CRF = 18; + static const int kDefaultH265CRF = 23; private: - static const int kMinimumCRF = 0; - static const int kMaximumCRF = 51; - - QSlider* crf_slider_; + static const int kMinimumCRF = 0; + static const int kMaximumCRF = 51; + QSlider *crf_slider_; }; -class H264BitRateSection : public QWidget -{ - Q_OBJECT +class H264BitRateSection : public QWidget { + Q_OBJECT public: - H264BitRateSection(QWidget* parent = nullptr); + H264BitRateSection(QWidget *parent = nullptr); - /** + /** * @brief Get user-selected target bit rate (returns in BITS) */ - int64_t GetTargetBitRate() const; - void SetTargetBitRate(int64_t b); + int64_t GetTargetBitRate() const; + void SetTargetBitRate(int64_t b); - /** + /** * @brief Get user-selected maximum bit rate (returns in BITS) */ - int64_t GetMaximumBitRate() const; - void SetMaximumBitRate(int64_t b); + int64_t GetMaximumBitRate() const; + void SetMaximumBitRate(int64_t b); private: - FloatSlider* target_rate_; - - FloatSlider* max_rate_; + FloatSlider *target_rate_; + FloatSlider *max_rate_; }; -class H264FileSizeSection : public QWidget -{ - Q_OBJECT +class H264FileSizeSection : public QWidget { + Q_OBJECT public: - H264FileSizeSection(QWidget* parent = nullptr); + H264FileSizeSection(QWidget *parent = nullptr); - /** + /** * @brief Returns file size in BITS */ - int64_t GetFileSize() const; - void SetFileSize(int64_t f); + int64_t GetFileSize() const; + void SetFileSize(int64_t f); private: - FloatSlider* file_size_; - + FloatSlider *file_size_; }; -class H264Section : public CodecSection -{ - Q_OBJECT +class H264Section : public CodecSection { + Q_OBJECT public: - enum CompressionMethod { - kConstantRateFactor, - kTargetBitRate, - kTargetFileSize - }; + enum CompressionMethod { + kConstantRateFactor, + kTargetBitRate, + kTargetFileSize + }; - H264Section(QWidget* parent = nullptr); - H264Section(int default_crf, QWidget* parent); + H264Section(QWidget *parent = nullptr); + H264Section(int default_crf, QWidget *parent); - virtual void AddOpts(EncodingParams* params) override; + virtual void AddOpts(EncodingParams *params) override; - virtual void SetOpts(const EncodingParams *p) override; + virtual void SetOpts(const EncodingParams *p) override; private: - QStackedWidget* compression_method_stack_; + QStackedWidget *compression_method_stack_; - H264CRFSection* crf_section_; + H264CRFSection *crf_section_; - H264BitRateSection* bitrate_section_; + H264BitRateSection *bitrate_section_; - H264FileSizeSection* filesize_section_; + H264FileSizeSection *filesize_section_; - QComboBox *preset_combobox_; + QComboBox *preset_combobox_; }; -class H265Section : public H264Section -{ - Q_OBJECT +class H265Section : public H264Section { + Q_OBJECT public: - H265Section(QWidget* parent = nullptr); + H265Section(QWidget *parent = nullptr); }; } diff --git a/app/dialog/export/codec/imagesection.cpp b/app/dialog/export/codec/imagesection.cpp index 50be54175..8ceb307b4 100644 --- a/app/dialog/export/codec/imagesection.cpp +++ b/app/dialog/export/codec/imagesection.cpp @@ -23,37 +23,40 @@ #include #include -namespace olive { - -ImageSection::ImageSection(QWidget* parent) : - CodecSection(parent) +namespace olive { - QGridLayout* layout = new QGridLayout(this); - layout->setContentsMargins(0, 0, 0, 0); - int row = 0; +ImageSection::ImageSection(QWidget *parent) + : CodecSection(parent) +{ + QGridLayout *layout = new QGridLayout(this); + layout->setContentsMargins(0, 0, 0, 0); - layout->addWidget(new QLabel(tr("Image Sequence:")), row, 0); + int row = 0; - image_sequence_checkbox_ = new QCheckBox(); - connect(image_sequence_checkbox_, &QCheckBox::toggled, this, &ImageSection::ImageSequenceCheckBoxToggled); - layout->addWidget(image_sequence_checkbox_, row, 1); + layout->addWidget(new QLabel(tr("Image Sequence:")), row, 0); - row++; + image_sequence_checkbox_ = new QCheckBox(); + connect(image_sequence_checkbox_, &QCheckBox::toggled, this, + &ImageSection::ImageSequenceCheckBoxToggled); + layout->addWidget(image_sequence_checkbox_, row, 1); - layout->addWidget(new QLabel(tr("Frame to Export:")), row, 0); + row++; - frame_slider_ = new RationalSlider(); - frame_slider_->SetMinimum(0); - frame_slider_->SetValue(0); - frame_slider_->SetDisplayType(RationalSlider::kTime); - connect(frame_slider_, &RationalSlider::ValueChanged, this, &ImageSection::TimeChanged); - layout->addWidget(frame_slider_, row, 1); + layout->addWidget(new QLabel(tr("Frame to Export:")), row, 0); + + frame_slider_ = new RationalSlider(); + frame_slider_->SetMinimum(0); + frame_slider_->SetValue(0); + frame_slider_->SetDisplayType(RationalSlider::kTime); + connect(frame_slider_, &RationalSlider::ValueChanged, this, + &ImageSection::TimeChanged); + layout->addWidget(frame_slider_, row, 1); } void ImageSection::ImageSequenceCheckBoxToggled(bool e) { - frame_slider_->setEnabled(!e); + frame_slider_->setEnabled(!e); } } diff --git a/app/dialog/export/codec/imagesection.h b/app/dialog/export/codec/imagesection.h index b1d6cac61..cfe76bbed 100644 --- a/app/dialog/export/codec/imagesection.h +++ b/app/dialog/export/codec/imagesection.h @@ -26,50 +26,49 @@ #include "codecsection.h" #include "widget/slider/rationalslider.h" -namespace olive { - -class ImageSection : public CodecSection +namespace olive { - Q_OBJECT + +class ImageSection : public CodecSection { + Q_OBJECT public: - ImageSection(QWidget* parent = nullptr); + ImageSection(QWidget *parent = nullptr); - bool IsImageSequenceChecked() const - { - return image_sequence_checkbox_->isChecked(); - } + bool IsImageSequenceChecked() const + { + return image_sequence_checkbox_->isChecked(); + } - void SetImageSequenceChecked(bool e) - { - image_sequence_checkbox_->setChecked(e); - } + void SetImageSequenceChecked(bool e) + { + image_sequence_checkbox_->setChecked(e); + } - void SetTimebase(const rational& r) - { - frame_slider_->SetTimebase(r); - } + void SetTimebase(const rational &r) + { + frame_slider_->SetTimebase(r); + } - rational GetTime() const - { - return frame_slider_->GetValue(); - } + rational GetTime() const + { + return frame_slider_->GetValue(); + } - void SetTime(const rational &t) - { - frame_slider_->SetValue(t); - } + void SetTime(const rational &t) + { + frame_slider_->SetValue(t); + } signals: - void TimeChanged(const rational &t); + void TimeChanged(const rational &t); private: - QCheckBox* image_sequence_checkbox_; + QCheckBox *image_sequence_checkbox_; - RationalSlider* frame_slider_; + RationalSlider *frame_slider_; private slots: - void ImageSequenceCheckBoxToggled(bool e); - + void ImageSequenceCheckBoxToggled(bool e); }; } diff --git a/app/dialog/export/export.cpp b/app/dialog/export/export.cpp index c5cfa2a17..22f7b6598 100644 --- a/app/dialog/export/export.cpp +++ b/app/dialog/export/export.cpp @@ -40,792 +40,838 @@ #include "ui/icons/icons.h" #include "widget/timeruler/timeruler.h" -namespace olive { +namespace olive +{ #define super QDialog -ExportDialog::ExportDialog(ViewerOutput *viewer_node, bool stills_only_mode, QWidget *parent) : - super(parent), - viewer_node_(viewer_node), - stills_only_mode_(stills_only_mode), - loading_presets_(false) +ExportDialog::ExportDialog(ViewerOutput *viewer_node, bool stills_only_mode, + QWidget *parent) + : super(parent) + , viewer_node_(viewer_node) + , stills_only_mode_(stills_only_mode) + , loading_presets_(false) { - QHBoxLayout* layout = new QHBoxLayout(this); + QHBoxLayout *layout = new QHBoxLayout(this); - QSplitter* splitter = new QSplitter(Qt::Horizontal); - splitter->setChildrenCollapsible(false); - layout->addWidget(splitter); + QSplitter *splitter = new QSplitter(Qt::Horizontal); + splitter->setChildrenCollapsible(false); + layout->addWidget(splitter); - preferences_area_ = new QWidget(); - QGridLayout* preferences_layout = new QGridLayout(preferences_area_); - preferences_layout->setContentsMargins(0, 0, 0, 0); + preferences_area_ = new QWidget(); + QGridLayout *preferences_layout = new QGridLayout(preferences_area_); + preferences_layout->setContentsMargins(0, 0, 0, 0); - int row = 0; + int row = 0; - QLabel* fn_lbl = new QLabel(tr("Filename:")); - fn_lbl->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum); - preferences_layout->addWidget(fn_lbl, row, 0); + QLabel *fn_lbl = new QLabel(tr("Filename:")); + fn_lbl->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum); + preferences_layout->addWidget(fn_lbl, row, 0); - filename_edit_ = new QLineEdit(); - preferences_layout->addWidget(filename_edit_, row, 1, 1, 2); + filename_edit_ = new QLineEdit(); + preferences_layout->addWidget(filename_edit_, row, 1, 1, 2); - QPushButton* file_browse_btn = new QPushButton(); - file_browse_btn->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum); - file_browse_btn->setIcon(icon::Folder); - file_browse_btn->setToolTip(tr("Browse for exported file filename")); - connect(file_browse_btn, - &QPushButton::clicked, - this, - &ExportDialog::BrowseFilename); - preferences_layout->addWidget(file_browse_btn, row, 3); + QPushButton *file_browse_btn = new QPushButton(); + file_browse_btn->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum); + file_browse_btn->setIcon(icon::Folder); + file_browse_btn->setToolTip(tr("Browse for exported file filename")); + connect(file_browse_btn, &QPushButton::clicked, this, + &ExportDialog::BrowseFilename); + preferences_layout->addWidget(file_browse_btn, row, 3); - row++; + row++; - QLabel* preset_lbl = new QLabel(tr("Preset:")); - preset_lbl->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum); - preferences_layout->addWidget(preset_lbl, row, 0); - preset_combobox_ = new QComboBox(); - LoadPresets(); - connect(preset_combobox_, static_cast(&QComboBox::currentIndexChanged), this, &ExportDialog::PresetComboBoxChanged); - preferences_layout->addWidget(preset_combobox_, row, 1, 1, 2); + QLabel *preset_lbl = new QLabel(tr("Preset:")); + preset_lbl->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum); + preferences_layout->addWidget(preset_lbl, row, 0); + preset_combobox_ = new QComboBox(); + LoadPresets(); + connect( + preset_combobox_, + static_cast(&QComboBox::currentIndexChanged), + this, &ExportDialog::PresetComboBoxChanged); + preferences_layout->addWidget(preset_combobox_, row, 1, 1, 2); - /*QPushButton* preset_load_btn = new QPushButton(); + /*QPushButton* preset_load_btn = new QPushButton(); preset_load_btn->setIcon(icon::Open); preset_load_btn->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum); preferences_layout->addWidget(preset_load_btn, row, 2);*/ - QPushButton* preset_save_btn = new QPushButton(); - preset_save_btn->setIcon(icon::Save); - preset_save_btn->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum); - preferences_layout->addWidget(preset_save_btn, row, 3); - connect(preset_save_btn, &QPushButton::clicked, this, &ExportDialog::SavePreset); + QPushButton *preset_save_btn = new QPushButton(); + preset_save_btn->setIcon(icon::Save); + preset_save_btn->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum); + preferences_layout->addWidget(preset_save_btn, row, 3); + connect(preset_save_btn, &QPushButton::clicked, this, + &ExportDialog::SavePreset); - row++; + row++; - preferences_layout->addWidget(QtUtils::CreateHorizontalLine(), row, 0, 1, 4); + preferences_layout->addWidget(QtUtils::CreateHorizontalLine(), row, 0, 1, + 4); - row++; + row++; - preferences_layout->addWidget(new QLabel(tr("Range:")), row, 0); + preferences_layout->addWidget(new QLabel(tr("Range:")), row, 0); - range_combobox_ = new QComboBox(); - range_combobox_->addItem(tr("Entire Sequence")); - range_combobox_->addItem(tr("In to Out")); - range_combobox_->setEnabled(viewer_node_->GetWorkArea()->enabled()); + range_combobox_ = new QComboBox(); + range_combobox_->addItem(tr("Entire Sequence")); + range_combobox_->addItem(tr("In to Out")); + range_combobox_->setEnabled(viewer_node_->GetWorkArea()->enabled()); - preferences_layout->addWidget(range_combobox_, row, 1, 1, 3); + preferences_layout->addWidget(range_combobox_, row, 1, 1, 3); - row++; + row++; - preferences_layout->addWidget(QtUtils::CreateHorizontalLine(), row, 0, 1, 4); + preferences_layout->addWidget(QtUtils::CreateHorizontalLine(), row, 0, 1, + 4); - row++; + row++; - preferences_layout->addWidget(new QLabel(tr("Format:")), row, 0); - format_combobox_ = new ExportFormatComboBox(); - preferences_layout->addWidget(format_combobox_, row, 1, 1, 3); + preferences_layout->addWidget(new QLabel(tr("Format:")), row, 0); + format_combobox_ = new ExportFormatComboBox(); + preferences_layout->addWidget(format_combobox_, row, 1, 1, 3); - row++; + row++; - QHBoxLayout* av_enabled_layout = new QHBoxLayout(); + QHBoxLayout *av_enabled_layout = new QHBoxLayout(); - video_enabled_ = new QCheckBox(tr("Export Video")); - av_enabled_layout->addWidget(video_enabled_); + video_enabled_ = new QCheckBox(tr("Export Video")); + av_enabled_layout->addWidget(video_enabled_); - audio_enabled_ = new QCheckBox(tr("Export Audio")); - av_enabled_layout->addWidget(audio_enabled_); + audio_enabled_ = new QCheckBox(tr("Export Audio")); + av_enabled_layout->addWidget(audio_enabled_); - subtitles_enabled_ = new QCheckBox(tr("Export Subtitles")); - av_enabled_layout->addWidget(subtitles_enabled_); + subtitles_enabled_ = new QCheckBox(tr("Export Subtitles")); + av_enabled_layout->addWidget(subtitles_enabled_); - preferences_layout->addLayout(av_enabled_layout, row, 0, 1, 4); + preferences_layout->addLayout(av_enabled_layout, row, 0, 1, 4); - row++; + row++; - preferences_tabs_ = new QTabWidget(); + preferences_tabs_ = new QTabWidget(); - color_manager_ = viewer_node_->project()->color_manager(); - video_tab_ = new ExportVideoTab(color_manager_); - AddPreferencesTab(video_tab_, tr("Video")); + color_manager_ = viewer_node_->project()->color_manager(); + video_tab_ = new ExportVideoTab(color_manager_); + AddPreferencesTab(video_tab_, tr("Video")); - // Set video tab time and make connections - connect(viewer_node, &ViewerOutput::PlayheadChanged, video_tab_, &ExportVideoTab::SetTime); - connect(video_tab_, &ExportVideoTab::TimeChanged, viewer_node, &ViewerOutput::SetPlayhead); - video_tab_->SetTime(viewer_node->GetPlayhead()); + // Set video tab time and make connections + connect(viewer_node, &ViewerOutput::PlayheadChanged, video_tab_, + &ExportVideoTab::SetTime); + connect(video_tab_, &ExportVideoTab::TimeChanged, viewer_node, + &ViewerOutput::SetPlayhead); + video_tab_->SetTime(viewer_node->GetPlayhead()); - audio_tab_ = new ExportAudioTab(); - AddPreferencesTab(audio_tab_, tr("Audio")); + audio_tab_ = new ExportAudioTab(); + AddPreferencesTab(audio_tab_, tr("Audio")); - subtitle_tab_ = new ExportSubtitlesTab(); - AddPreferencesTab(subtitle_tab_, tr("Subtitles")); + subtitle_tab_ = new ExportSubtitlesTab(); + AddPreferencesTab(subtitle_tab_, tr("Subtitles")); - preferences_layout->addWidget(preferences_tabs_, row, 0, 1, 4); + preferences_layout->addWidget(preferences_tabs_, row, 0, 1, 4); - row++; + row++; - { - QGroupBox *options_group = new QGroupBox(); - preferences_layout->addWidget(options_group, row, 0, 1, 4); + { + QGroupBox *options_group = new QGroupBox(); + preferences_layout->addWidget(options_group, row, 0, 1, 4); - QGridLayout *options_layout = new QGridLayout(options_group); + QGridLayout *options_layout = new QGridLayout(options_group); - int opt_row = 0; + int opt_row = 0; - export_bkg_box_ = new QCheckBox(tr("Run In Background")); - export_bkg_box_->setToolTip(tr("Exporting in the background allows you to continue using Olive while " - "exporting, but may result in slower export speeds, and may" - "severely impact editing and playback performance.")); - options_layout->addWidget(export_bkg_box_, opt_row, 0); + export_bkg_box_ = new QCheckBox(tr("Run In Background")); + export_bkg_box_->setToolTip(tr( + "Exporting in the background allows you to continue using Olive while " + "exporting, but may result in slower export speeds, and may" + "severely impact editing and playback performance.")); + options_layout->addWidget(export_bkg_box_, opt_row, 0); - import_file_after_export_ = new QCheckBox(tr("Import Result After Export")); - options_layout->addWidget(import_file_after_export_, opt_row, 1); + import_file_after_export_ = + new QCheckBox(tr("Import Result After Export")); + options_layout->addWidget(import_file_after_export_, opt_row, 1); - connect(export_bkg_box_, &QCheckBox::toggled, import_file_after_export_, [this](bool e){ - import_file_after_export_->setEnabled(!e); - }); - } + connect(export_bkg_box_, &QCheckBox::toggled, import_file_after_export_, + [this](bool e) { import_file_after_export_->setEnabled(!e); }); + } - row++; + row++; - QHBoxLayout *btn_layout = new QHBoxLayout(); - btn_layout->setContentsMargins(0, 0, 0, 0); - preferences_layout->addLayout(btn_layout, row, 0, 1, 4); + QHBoxLayout *btn_layout = new QHBoxLayout(); + btn_layout->setContentsMargins(0, 0, 0, 0); + preferences_layout->addLayout(btn_layout, row, 0, 1, 4); - btn_layout->addStretch(); + btn_layout->addStretch(); - QPushButton *export_btn = new QPushButton(tr("Export")); - btn_layout->addWidget(export_btn); - connect(export_btn, &QPushButton::clicked, this, &ExportDialog::StartExport); + QPushButton *export_btn = new QPushButton(tr("Export")); + btn_layout->addWidget(export_btn); + connect(export_btn, &QPushButton::clicked, this, + &ExportDialog::StartExport); - QPushButton *cancel_btn = new QPushButton(tr("Cancel")); - btn_layout->addWidget(cancel_btn); - connect(cancel_btn, &QPushButton::clicked, this, &ExportDialog::reject); + QPushButton *cancel_btn = new QPushButton(tr("Cancel")); + btn_layout->addWidget(cancel_btn); + connect(cancel_btn, &QPushButton::clicked, this, &ExportDialog::reject); - btn_layout->addStretch(); + btn_layout->addStretch(); - splitter->addWidget(preferences_area_); + splitter->addWidget(preferences_area_); - QWidget* preview_area = new QWidget(); - QVBoxLayout* preview_layout = new QVBoxLayout(preview_area); - preview_layout->addWidget(new QLabel(tr("Preview"))); - preview_viewer_ = new ViewerWidget(); - preview_viewer_->ruler()->SetMarkerEditingEnabled(false); - preview_viewer_->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); - preview_layout->addWidget(preview_viewer_); - splitter->addWidget(preview_area); + QWidget *preview_area = new QWidget(); + QVBoxLayout *preview_layout = new QVBoxLayout(preview_area); + preview_layout->addWidget(new QLabel(tr("Preview"))); + preview_viewer_ = new ViewerWidget(); + preview_viewer_->ruler()->SetMarkerEditingEnabled(false); + preview_viewer_->setSizePolicy(QSizePolicy::Expanding, + QSizePolicy::Expanding); + preview_layout->addWidget(preview_viewer_); + splitter->addWidget(preview_area); - // Prioritize preview area - splitter->setSizes({1, 99999}); + // Prioritize preview area + splitter->setSizes({ 1, 99999 }); - // Set default filename - SetDefaultFilename(); + // Set default filename + SetDefaultFilename(); - // Set defaults - previously_selected_format_ = ExportFormat::kFormatMPEG4Video; - connect(format_combobox_, &ExportFormatComboBox::FormatChanged, this, &ExportDialog::FormatChanged); + // Set defaults + previously_selected_format_ = ExportFormat::kFormatMPEG4Video; + connect(format_combobox_, &ExportFormatComboBox::FormatChanged, this, + &ExportDialog::FormatChanged); - VideoParams vp = viewer_node_->GetVideoParams(); - video_aspect_ratio_ = static_cast(vp.width()) / static_cast(vp.height()); + VideoParams vp = viewer_node_->GetVideoParams(); + video_aspect_ratio_ = + static_cast(vp.width()) / static_cast(vp.height()); - connect(video_tab_->width_slider(), - &IntegerSlider::ValueChanged, - this, - &ExportDialog::ResolutionChanged); + connect(video_tab_->width_slider(), &IntegerSlider::ValueChanged, this, + &ExportDialog::ResolutionChanged); - connect(video_tab_->height_slider(), - &IntegerSlider::ValueChanged, - this, - &ExportDialog::ResolutionChanged); + connect(video_tab_->height_slider(), &IntegerSlider::ValueChanged, this, + &ExportDialog::ResolutionChanged); - connect(video_tab_->scaling_method_combobox(), - static_cast(&QComboBox::currentIndexChanged), - this, - &ExportDialog::UpdateViewerDimensions); + connect( + video_tab_->scaling_method_combobox(), + static_cast(&QComboBox::currentIndexChanged), + this, &ExportDialog::UpdateViewerDimensions); - connect(video_tab_->maintain_aspect_checkbox(), - &QCheckBox::toggled, - this, - &ExportDialog::ResolutionChanged); + connect(video_tab_->maintain_aspect_checkbox(), &QCheckBox::toggled, this, + &ExportDialog::ResolutionChanged); - connect(video_tab_, - &ExportVideoTab::ColorSpaceChanged, - preview_viewer_, - static_cast(&ViewerWidget::SetColorTransform)); - connect(video_tab_, - &ExportVideoTab::ImageSequenceCheckBoxChanged, - this, - &ExportDialog::ImageSequenceCheckBoxChanged); + connect(video_tab_, &ExportVideoTab::ColorSpaceChanged, preview_viewer_, + static_cast( + &ViewerWidget::SetColorTransform)); + connect(video_tab_, &ExportVideoTab::ImageSequenceCheckBoxChanged, this, + &ExportDialog::ImageSequenceCheckBoxChanged); - // We don't check if the codec supports subtitles because we can always export to a sidecar file - bool has_subtitle_tracks = SequenceHasSubtitles(); - connect(subtitles_enabled_, &QCheckBox::toggled, subtitle_tab_, &QWidget::setEnabled); - subtitles_enabled_->setEnabled(has_subtitle_tracks); + // We don't check if the codec supports subtitles because we can always export to a sidecar file + bool has_subtitle_tracks = SequenceHasSubtitles(); + connect(subtitles_enabled_, &QCheckBox::toggled, subtitle_tab_, + &QWidget::setEnabled); + subtitles_enabled_->setEnabled(has_subtitle_tracks); - // If the viewer already has cached params, use them - if (!stills_only_mode_ && viewer_node_->GetLastUsedEncodingParams().IsValid()) { - // This will automatically set the param data - QtUtils::SetComboBoxData(preset_combobox_, kPresetLastUsed); - } else { - SetDefaults(); - } + // If the viewer already has cached params, use them + if (!stills_only_mode_ && + viewer_node_->GetLastUsedEncodingParams().IsValid()) { + // This will automatically set the param data + QtUtils::SetComboBoxData(preset_combobox_, kPresetLastUsed); + } else { + SetDefaults(); + } - // Set viewer to view the node and set its colorspace - preview_viewer_->ConnectViewerNode(viewer_node_); - preview_viewer_->SetColorMenuEnabled(false); - preview_viewer_->SetColorTransform(video_tab_->CurrentOCIOColorSpace()); + // Set viewer to view the node and set its colorspace + preview_viewer_->ConnectViewerNode(viewer_node_); + preview_viewer_->SetColorMenuEnabled(false); + preview_viewer_->SetColorTransform(video_tab_->CurrentOCIOColorSpace()); - qApp->installEventFilter(this); + qApp->installEventFilter(this); - connect(video_enabled_, &QCheckBox::toggled, video_tab_, &QWidget::setEnabled); - video_tab_->setEnabled(video_enabled_->isChecked()); - connect(audio_enabled_, &QCheckBox::toggled, audio_tab_, &QWidget::setEnabled); - audio_tab_->setEnabled(audio_enabled_->isChecked()); - connect(subtitles_enabled_, &QCheckBox::toggled, subtitle_tab_, &QWidget::setEnabled); - subtitle_tab_->setEnabled(subtitles_enabled_->isChecked()); + connect(video_enabled_, &QCheckBox::toggled, video_tab_, + &QWidget::setEnabled); + video_tab_->setEnabled(video_enabled_->isChecked()); + connect(audio_enabled_, &QCheckBox::toggled, audio_tab_, + &QWidget::setEnabled); + audio_tab_->setEnabled(audio_enabled_->isChecked()); + connect(subtitles_enabled_, &QCheckBox::toggled, subtitle_tab_, + &QWidget::setEnabled); + subtitle_tab_->setEnabled(subtitles_enabled_->isChecked()); } rational ExportDialog::GetSelectedTimebase() const { - return video_tab_->GetSelectedFrameRate().flipped(); + return video_tab_->GetSelectedFrameRate().flipped(); } void ExportDialog::SetSelectedTimebase(const rational &r) { - video_tab_->SetSelectedFrameRate(r.flipped()); + video_tab_->SetSelectedFrameRate(r.flipped()); } void ExportDialog::StartExport() { - if (!video_enabled_->isChecked() && !audio_enabled_->isChecked() && !subtitles_enabled_->isChecked()) { - QtUtils::MsgBox(this, QMessageBox::Critical, tr("Invalid parameters"), - tr("Video, audio, and subtitles are disabled. There's nothing to export.")); - return; - } + if (!video_enabled_->isChecked() && !audio_enabled_->isChecked() && + !subtitles_enabled_->isChecked()) { + QtUtils::MsgBox( + this, QMessageBox::Critical, tr("Invalid parameters"), + tr("Video, audio, and subtitles are disabled. There's nothing to export.")); + return; + } - // Validate if the entered filename contains the correct extension (the extension is necessary - // for both FFmpeg and OIIO to determine the output format) - QString necessary_ext = QStringLiteral(".%1").arg(ExportFormat::GetExtension(format_combobox_->GetFormat())); - QString proposed_filename = filename_edit_->text().trimmed(); + // Validate if the entered filename contains the correct extension (the extension is necessary + // for both FFmpeg and OIIO to determine the output format) + QString necessary_ext = QStringLiteral(".%1").arg( + ExportFormat::GetExtension(format_combobox_->GetFormat())); + QString proposed_filename = filename_edit_->text().trimmed(); - // If it doesn't, see if the user wants to append it automatically. If not, we don't abort the export. - if (!proposed_filename.endsWith(necessary_ext, Qt::CaseInsensitive)) { - if (QtUtils::MsgBox(this, QMessageBox::Warning, tr("Invalid filename"), - tr("The filename must contain the extension \"%1\". Would you like to append it " - "automatically?").arg(necessary_ext), - QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) { - filename_edit_->setText(proposed_filename.append(necessary_ext)); - } else { - return; - } - } + // If it doesn't, see if the user wants to append it automatically. If not, we don't abort the export. + if (!proposed_filename.endsWith(necessary_ext, Qt::CaseInsensitive)) { + if (QtUtils::MsgBox( + this, QMessageBox::Warning, tr("Invalid filename"), + tr("The filename must contain the extension \"%1\". Would you like to append it " + "automatically?") + .arg(necessary_ext), + QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) { + filename_edit_->setText(proposed_filename.append(necessary_ext)); + } else { + return; + } + } - // Validate the intended path - QFileInfo file_info(proposed_filename); - QFileInfo dir_info(file_info.path()); + // Validate the intended path + QFileInfo file_info(proposed_filename); + QFileInfo dir_info(file_info.path()); - // If the directory does not exist, try to create it - QDir dest_dir(file_info.path()); - if (!FileFunctions::DirectoryIsValid(dest_dir)) { - QtUtils::MsgBox(this, QMessageBox::Critical, tr("Failed to create output directory"), - tr("The intended output directory doesn't exist and Olive couldn't create it. " - "Please choose a different filename.")); - return; - } + // If the directory does not exist, try to create it + QDir dest_dir(file_info.path()); + if (!FileFunctions::DirectoryIsValid(dest_dir)) { + QtUtils::MsgBox( + this, QMessageBox::Critical, + tr("Failed to create output directory"), + tr("The intended output directory doesn't exist and Olive couldn't create it. " + "Please choose a different filename.")); + return; + } - // Validate if this is an image sequence and if the filename contains enough digits - if (video_tab_->IsImageSequenceSet()) { - // Ensure filename contains digits - if (!Encoder::FilenameContainsDigitPlaceholder(proposed_filename)) { - QtUtils::MsgBox(this, QMessageBox::Critical, tr("Invalid filename"), - tr("Export is set to an image sequence, but the filename does not have a section for digits " - "(formatted as [#####] where the amount of # is the amount of digits).")); - return; - } + // Validate if this is an image sequence and if the filename contains enough digits + if (video_tab_->IsImageSequenceSet()) { + // Ensure filename contains digits + if (!Encoder::FilenameContainsDigitPlaceholder(proposed_filename)) { + QtUtils::MsgBox( + this, QMessageBox::Critical, tr("Invalid filename"), + tr("Export is set to an image sequence, but the filename does not have a section for digits " + "(formatted as [#####] where the amount of # is the amount of digits).")); + return; + } - int64_t frame_count = GetExportLengthInTimebaseUnits(); - int64_t needed_digit_count = GetDigitCount(frame_count); - int current_digit_count = Encoder::GetImageSequencePlaceholderDigitCount(proposed_filename); - if (current_digit_count < needed_digit_count) { - QtUtils::MsgBox(this, QMessageBox::Critical, tr("Invalid filename"), - tr("Filename doesn't contain enough digits for the amount of frames " - "this export will need (need %1 for %n frame(s)).", nullptr, frame_count) - .arg(QString::number(needed_digit_count))); - return; - } - } + int64_t frame_count = GetExportLengthInTimebaseUnits(); + int64_t needed_digit_count = GetDigitCount(frame_count); + int current_digit_count = + Encoder::GetImageSequencePlaceholderDigitCount(proposed_filename); + if (current_digit_count < needed_digit_count) { + QtUtils::MsgBox( + this, QMessageBox::Critical, tr("Invalid filename"), + tr("Filename doesn't contain enough digits for the amount of frames " + "this export will need (need %1 for %n frame(s)).", + nullptr, frame_count) + .arg(QString::number(needed_digit_count))); + return; + } + } - // Validate if the file exists and whether the user wishes to overwrite it - if (file_info.exists()) { - if (QtUtils::MsgBox(this, QMessageBox::Warning, tr("Confirm Overwrite"), - tr("The file \"%1\" already exists. Do you want to overwrite it?") - .arg(proposed_filename), - QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) { - return; - } - } + // Validate if the file exists and whether the user wishes to overwrite it + if (file_info.exists()) { + if (QtUtils::MsgBox( + this, QMessageBox::Warning, tr("Confirm Overwrite"), + tr("The file \"%1\" already exists. Do you want to overwrite it?") + .arg(proposed_filename), + QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) { + return; + } + } - // Validate video resolution - if (video_enabled_->isChecked() - && (video_tab_->GetSelectedCodec() == ExportCodec::kCodecH264 || video_tab_->GetSelectedCodec() == ExportCodec::kCodecH265) - && (video_tab_->width_slider()->GetValue()%2 != 0 || video_tab_->height_slider()->GetValue()%2 != 0)) { - QtUtils::MsgBox(this, QMessageBox::Critical, tr("Invalid Parameters"), - tr("Width and height must be multiples of 2.")); - return; - } + // Validate video resolution + if (video_enabled_->isChecked() && + (video_tab_->GetSelectedCodec() == ExportCodec::kCodecH264 || + video_tab_->GetSelectedCodec() == ExportCodec::kCodecH265) && + (video_tab_->width_slider()->GetValue() % 2 != 0 || + video_tab_->height_slider()->GetValue() % 2 != 0)) { + QtUtils::MsgBox(this, QMessageBox::Critical, tr("Invalid Parameters"), + tr("Width and height must be multiples of 2.")); + return; + } - ExportTask* task = new ExportTask(viewer_node_, color_manager_, GenerateParams()); + ExportTask *task = + new ExportTask(viewer_node_, color_manager_, GenerateParams()); - if (export_bkg_box_->isChecked()) { - // Send to TaskManager to export in background - TaskManager::instance()->AddTask(task); - this->accept(); - } else { - // Use modal dialog box - TaskDialog* td = new TaskDialog(task, tr("Export"), this); - connect(td, &TaskDialog::TaskSucceeded, this, &ExportDialog::ExportFinished); - td->open(); - } + if (export_bkg_box_->isChecked()) { + // Send to TaskManager to export in background + TaskManager::instance()->AddTask(task); + this->accept(); + } else { + // Use modal dialog box + TaskDialog *td = new TaskDialog(task, tr("Export"), this); + connect(td, &TaskDialog::TaskSucceeded, this, + &ExportDialog::ExportFinished); + td->open(); + } } void ExportDialog::ExportFinished() { - TaskDialog* td = static_cast(sender()); + TaskDialog *td = static_cast(sender()); - if (td->GetTask()->IsCancelled()) { - // If this task was cancelled, we stay open so the user can potentially queue another export - } else { - // Accept this dialog and close - if (import_file_after_export_->isEnabled() && import_file_after_export_->isChecked()) { - QString filename = filename_edit_->text().trimmed(); - emit RequestImportFile(filename); - } + if (td->GetTask()->IsCancelled()) { + // If this task was cancelled, we stay open so the user can potentially queue another export + } else { + // Accept this dialog and close + if (import_file_after_export_->isEnabled() && + import_file_after_export_->isChecked()) { + QString filename = filename_edit_->text().trimmed(); + emit RequestImportFile(filename); + } - this->accept(); - } + this->accept(); + } } void ExportDialog::ImageSequenceCheckBoxChanged(bool e) { - QFileInfo current_fileinfo(filename_edit_->text()); + QFileInfo current_fileinfo(filename_edit_->text()); - QString basename = current_fileinfo.completeBaseName(); - QString suffix = current_fileinfo.suffix(); + QString basename = current_fileinfo.completeBaseName(); + QString suffix = current_fileinfo.suffix(); - if (e) { - if (!Encoder::FilenameContainsDigitPlaceholder(basename)) { - basename.append(QStringLiteral("_[#####]")); - } - } else { - basename = Encoder::FilenameRemoveDigitPlaceholder(basename); - } + if (e) { + if (!Encoder::FilenameContainsDigitPlaceholder(basename)) { + basename.append(QStringLiteral("_[#####]")); + } + } else { + basename = Encoder::FilenameRemoveDigitPlaceholder(basename); + } - // Set filename - if (!suffix.isEmpty()) { - basename.append('.'); - basename.append(suffix); - } - filename_edit_->setText(current_fileinfo.dir().filePath(basename)); + // Set filename + if (!suffix.isEmpty()) { + basename.append('.'); + basename.append(suffix); + } + filename_edit_->setText(current_fileinfo.dir().filePath(basename)); } void ExportDialog::SavePreset() { - ExportSavePresetDialog d(GenerateParams(), this); - if (d.exec() == QDialog::Accepted) { - LoadPresets(); - preset_combobox_->setCurrentText(d.GetSelectedPresetName()); - } + ExportSavePresetDialog d(GenerateParams(), this); + if (d.exec() == QDialog::Accepted) { + LoadPresets(); + preset_combobox_->setCurrentText(d.GetSelectedPresetName()); + } } void ExportDialog::PresetComboBoxChanged() { - if (loading_presets_) { - return; - } + if (loading_presets_) { + return; + } - QComboBox *c = static_cast(sender()); + QComboBox *c = static_cast(sender()); - int preset_number = c->currentData().toInt(); - if (preset_number == kPresetDefault) { - SetDefaults(); - } else if (preset_number == kPresetLastUsed) { - SetParams(viewer_node_->GetLastUsedEncodingParams()); - } else { - SetParams(presets_.at(preset_number)); - } + int preset_number = c->currentData().toInt(); + if (preset_number == kPresetDefault) { + SetDefaults(); + } else if (preset_number == kPresetLastUsed) { + SetParams(viewer_node_->GetLastUsedEncodingParams()); + } else { + SetParams(presets_.at(preset_number)); + } } -void ExportDialog::AddPreferencesTab(QWidget *inner_widget, const QString &title) +void ExportDialog::AddPreferencesTab(QWidget *inner_widget, + const QString &title) { - QScrollArea* scroll_area = new QScrollArea(); - scroll_area->setWidgetResizable(true); - scroll_area->setWidget(inner_widget); - preferences_tabs_->addTab(scroll_area, title); + QScrollArea *scroll_area = new QScrollArea(); + scroll_area->setWidgetResizable(true); + scroll_area->setWidget(inner_widget); + preferences_tabs_->addTab(scroll_area, title); } void ExportDialog::BrowseFilename() { - ExportFormat::Format f = format_combobox_->GetFormat(); + ExportFormat::Format f = format_combobox_->GetFormat(); - QString browsed_fn = QFileDialog::getSaveFileName(this, - "", - filename_edit_->text().trimmed(), - QStringLiteral("%1 (*.%2)").arg(ExportFormat::GetName(f), ExportFormat::GetExtension(f)), - nullptr, + QString browsed_fn = QFileDialog::getSaveFileName( + this, "", filename_edit_->text().trimmed(), + QStringLiteral("%1 (*.%2)") + .arg(ExportFormat::GetName(f), ExportFormat::GetExtension(f)), + nullptr, - // We don't confirm overwrite here because we do it later - QFileDialog::DontConfirmOverwrite); + // We don't confirm overwrite here because we do it later + QFileDialog::DontConfirmOverwrite); - if (!browsed_fn.isEmpty()) { - filename_edit_->setText(browsed_fn); - } + if (!browsed_fn.isEmpty()) { + filename_edit_->setText(browsed_fn); + } } void ExportDialog::FormatChanged(ExportFormat::Format current_format) { - QString current_filename = filename_edit_->text().trimmed(); - QString previously_selected_ext = ExportFormat::GetExtension(previously_selected_format_); - QString currently_selected_ext = ExportFormat::GetExtension(current_format); + QString current_filename = filename_edit_->text().trimmed(); + QString previously_selected_ext = + ExportFormat::GetExtension(previously_selected_format_); + QString currently_selected_ext = ExportFormat::GetExtension(current_format); - // If the previous extension was added, remove it - if (current_filename.endsWith(previously_selected_ext, Qt::CaseInsensitive)) { - current_filename.resize(current_filename.size() - previously_selected_ext.size() - 1); - } + // If the previous extension was added, remove it + if (current_filename.endsWith(previously_selected_ext, + Qt::CaseInsensitive)) { + current_filename.resize(current_filename.size() - + previously_selected_ext.size() - 1); + } - // Add the extension and set it - current_filename.append('.'); - current_filename.append(currently_selected_ext); - filename_edit_->setText(current_filename); + // Add the extension and set it + current_filename.append('.'); + current_filename.append(currently_selected_ext); + filename_edit_->setText(current_filename); - previously_selected_format_ = current_format; + previously_selected_format_ = current_format; - // Update video and audio comboboxes - bool has_video_codecs = video_tab_->SetFormat(current_format); - video_enabled_->setChecked(has_video_codecs); - video_enabled_->setEnabled(has_video_codecs); + // Update video and audio comboboxes + bool has_video_codecs = video_tab_->SetFormat(current_format); + video_enabled_->setChecked(has_video_codecs); + video_enabled_->setEnabled(has_video_codecs); - bool has_audio_codecs = audio_tab_->SetFormat(current_format); - audio_enabled_->setChecked(has_audio_codecs); - audio_enabled_->setEnabled(has_audio_codecs); + bool has_audio_codecs = audio_tab_->SetFormat(current_format); + audio_enabled_->setChecked(has_audio_codecs); + audio_enabled_->setEnabled(has_audio_codecs); - if (subtitles_enabled_->isEnabled()) { - subtitle_tab_->SetFormat(current_format); - } + if (subtitles_enabled_->isEnabled()) { + subtitle_tab_->SetFormat(current_format); + } } void ExportDialog::ResolutionChanged() { - if (video_tab_->maintain_aspect_checkbox()->isChecked()) { - // Keep aspect ratio maintained - if (sender() == video_tab_->height_slider()) { + if (video_tab_->maintain_aspect_checkbox()->isChecked()) { + // Keep aspect ratio maintained + if (sender() == video_tab_->height_slider()) { + // Convert height to float + double new_width = video_tab_->height_slider()->GetValue(); - // Convert height to float - double new_width = video_tab_->height_slider()->GetValue(); + // Generate width from aspect ratio + new_width *= video_aspect_ratio_; - // Generate width from aspect ratio - new_width *= video_aspect_ratio_; + // Align to even number and set + video_tab_->width_slider()->SetValue(new_width); - // Align to even number and set - video_tab_->width_slider()->SetValue(new_width); + } else { + // Convert width to float + double new_height = video_tab_->width_slider()->GetValue(); - } else { + // Generate height from aspect ratio + new_height /= video_aspect_ratio_; - // Convert width to float - double new_height = video_tab_->width_slider()->GetValue(); + // Align to even number and set + video_tab_->height_slider()->SetValue(new_height); + } + } - // Generate height from aspect ratio - new_height /= video_aspect_ratio_; - - // Align to even number and set - video_tab_->height_slider()->SetValue(new_height); - - } - } - - UpdateViewerDimensions(); + UpdateViewerDimensions(); } void ExportDialog::LoadPresets() { - loading_presets_ = true; + loading_presets_ = true; - preset_combobox_->clear(); - presets_.clear(); + preset_combobox_->clear(); + presets_.clear(); - preset_combobox_->addItem(tr("Default"), kPresetDefault); + preset_combobox_->addItem(tr("Default"), kPresetDefault); - if (viewer_node_->GetLastUsedEncodingParams().IsValid()) { - preset_combobox_->addItem(tr("Last Used"), kPresetLastUsed); - } + if (viewer_node_->GetLastUsedEncodingParams().IsValid()) { + preset_combobox_->addItem(tr("Last Used"), kPresetLastUsed); + } - preset_combobox_->insertSeparator(preset_combobox_->count()); + preset_combobox_->insertSeparator(preset_combobox_->count()); - QStringList l = EncodingParams::GetListOfPresets(); - presets_.reserve(l.size()); + QStringList l = EncodingParams::GetListOfPresets(); + presets_.reserve(l.size()); - for (const QString &preset : l) { - EncodingParams p; + for (const QString &preset : l) { + EncodingParams p; - QFile f(EncodingParams::GetPresetPath().filePath(preset)); - if (f.open(QFile::ReadOnly)) { - if (p.Load(&f)) { - preset_combobox_->addItem(preset, int(presets_.size())); - presets_.push_back(p); - } - f.close(); - } - } + QFile f(EncodingParams::GetPresetPath().filePath(preset)); + if (f.open(QFile::ReadOnly)) { + if (p.Load(&f)) { + preset_combobox_->addItem(preset, int(presets_.size())); + presets_.push_back(p); + } + f.close(); + } + } - loading_presets_ = false; + loading_presets_ = false; } void ExportDialog::SetDefaultFilename() { - Project* p = viewer_node_->project(); + Project *p = viewer_node_->project(); - QDir doc_location; + QDir doc_location; - if (p->filename().isEmpty()) { - doc_location.setPath(QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation)); - } else { - doc_location = QFileInfo(p->filename()).dir(); - } + if (p->filename().isEmpty()) { + doc_location.setPath(QStandardPaths::writableLocation( + QStandardPaths::DocumentsLocation)); + } else { + doc_location = QFileInfo(p->filename()).dir(); + } - QString file_location = doc_location.filePath(viewer_node_->GetLabel()); - filename_edit_->setText(file_location); + QString file_location = doc_location.filePath(viewer_node_->GetLabel()); + filename_edit_->setText(file_location); } bool ExportDialog::SequenceHasSubtitles() const { - if (Sequence *s = dynamic_cast(viewer_node_)) { - TrackList *tl = s->track_list(Track::kSubtitle); - for (Track *t : tl->GetTracks()) { - if (!t->IsMuted() && !t->Blocks().empty()) { - return true; - } - } - } + if (Sequence *s = dynamic_cast(viewer_node_)) { + TrackList *tl = s->track_list(Track::kSubtitle); + for (Track *t : tl->GetTracks()) { + if (!t->IsMuted() && !t->Blocks().empty()) { + return true; + } + } + } - return false; + return false; } void ExportDialog::SetDefaults() { - if (!stills_only_mode_) { - format_combobox_->SetFormat(ExportFormat::kFormatMPEG4Video); - } else { - format_combobox_->SetFormat(ExportFormat::kFormatPNG); - } - FormatChanged(format_combobox_->GetFormat()); + if (!stills_only_mode_) { + format_combobox_->SetFormat(ExportFormat::kFormatMPEG4Video); + } else { + format_combobox_->SetFormat(ExportFormat::kFormatPNG); + } + FormatChanged(format_combobox_->GetFormat()); - VideoParams vp = viewer_node_->GetVideoParams(); - AudioParams ap = viewer_node_->GetAudioParams(); + VideoParams vp = viewer_node_->GetVideoParams(); + AudioParams ap = viewer_node_->GetAudioParams(); - video_tab_->width_slider()->SetValue(vp.width()); - video_tab_->width_slider()->SetDefaultValue(vp.width()); - video_tab_->height_slider()->SetValue(vp.height()); - video_tab_->height_slider()->SetDefaultValue(vp.height()); - video_tab_->SetSelectedFrameRate(vp.frame_rate()); - video_tab_->pixel_aspect_combobox()->SetPixelAspectRatio(vp.pixel_aspect_ratio()); - video_tab_->pixel_format_field()->SetPixelFormat(static_cast(OLIVE_CONFIG("OnlinePixelFormat").toInt())); - video_tab_->interlaced_combobox()->SetInterlaceMode(vp.interlacing()); - audio_tab_->sample_rate_combobox()->SetSampleRate(ap.sample_rate()); - audio_tab_->sample_format_combobox()->SetAttemptToRestoreFormat(false); - audio_tab_->channel_layout_combobox()->SetChannelLayout(ap.channel_layout()); - subtitles_enabled_->setChecked(SequenceHasSubtitles()); - subtitle_tab_->SetSidecarFormat(ExportFormat::kFormatSRT); + video_tab_->width_slider()->SetValue(vp.width()); + video_tab_->width_slider()->SetDefaultValue(vp.width()); + video_tab_->height_slider()->SetValue(vp.height()); + video_tab_->height_slider()->SetDefaultValue(vp.height()); + video_tab_->SetSelectedFrameRate(vp.frame_rate()); + video_tab_->pixel_aspect_combobox()->SetPixelAspectRatio( + vp.pixel_aspect_ratio()); + video_tab_->pixel_format_field()->SetPixelFormat( + static_cast( + OLIVE_CONFIG("OnlinePixelFormat").toInt())); + video_tab_->interlaced_combobox()->SetInterlaceMode(vp.interlacing()); + audio_tab_->sample_rate_combobox()->SetSampleRate(ap.sample_rate()); + audio_tab_->sample_format_combobox()->SetAttemptToRestoreFormat(false); + audio_tab_->channel_layout_combobox()->SetChannelLayout( + ap.channel_layout()); + subtitles_enabled_->setChecked(SequenceHasSubtitles()); + subtitle_tab_->SetSidecarFormat(ExportFormat::kFormatSRT); } EncodingParams ExportDialog::GenerateParams() const { - VideoParams video_render_params(static_cast(video_tab_->width_slider()->GetValue()), - static_cast(video_tab_->height_slider()->GetValue()), - GetSelectedTimebase(), - video_tab_->pixel_format_field()->GetPixelFormat(), - VideoParams::kInternalChannelCount, - video_tab_->pixel_aspect_combobox()->GetPixelAspectRatio(), - video_tab_->interlaced_combobox()->GetInterlaceMode(), - 1); + VideoParams video_render_params( + static_cast(video_tab_->width_slider()->GetValue()), + static_cast(video_tab_->height_slider()->GetValue()), + GetSelectedTimebase(), + video_tab_->pixel_format_field()->GetPixelFormat(), + VideoParams::kInternalChannelCount, + video_tab_->pixel_aspect_combobox()->GetPixelAspectRatio(), + video_tab_->interlaced_combobox()->GetInterlaceMode(), 1); - AudioParams audio_render_params(audio_tab_->sample_rate_combobox()->GetSampleRate(), - audio_tab_->channel_layout_combobox()->GetChannelLayout(), - audio_tab_->sample_format_combobox()->GetSampleFormat()); + AudioParams audio_render_params( + audio_tab_->sample_rate_combobox()->GetSampleRate(), + audio_tab_->channel_layout_combobox()->GetChannelLayout(), + audio_tab_->sample_format_combobox()->GetSampleFormat()); - EncodingParams params; - params.set_format(format_combobox_->GetFormat()); - params.SetFilename(filename_edit_->text().trimmed()); - params.SetExportLength(viewer_node_->GetLength()); + EncodingParams params; + params.set_format(format_combobox_->GetFormat()); + params.SetFilename(filename_edit_->text().trimmed()); + params.SetExportLength(viewer_node_->GetLength()); - if (ExportCodec::IsCodecAStillImage(video_tab_->GetSelectedCodec()) && !video_tab_->IsImageSequenceSet()) { - // Exporting as image without exporting image sequence, only export one frame - rational export_time = video_tab_->GetStillImageTime(); - params.set_custom_range(TimeRange(export_time, export_time + GetSelectedTimebase())); - } else if (range_combobox_->currentIndex() == kRangeInToOut) { - // Assume if this combobox is enabled, workarea is enabled - a check that we make in this dialog's constructor - params.set_custom_range(viewer_node_->GetWorkArea()->range()); - } + if (ExportCodec::IsCodecAStillImage(video_tab_->GetSelectedCodec()) && + !video_tab_->IsImageSequenceSet()) { + // Exporting as image without exporting image sequence, only export one frame + rational export_time = video_tab_->GetStillImageTime(); + params.set_custom_range( + TimeRange(export_time, export_time + GetSelectedTimebase())); + } else if (range_combobox_->currentIndex() == kRangeInToOut) { + // Assume if this combobox is enabled, workarea is enabled - a check that we make in this dialog's constructor + params.set_custom_range(viewer_node_->GetWorkArea()->range()); + } - if (video_tab_->scaling_method_combobox()->isEnabled()) { - params.set_video_scaling_method(static_cast(video_tab_->scaling_method_combobox()->currentData().toInt())); - } + if (video_tab_->scaling_method_combobox()->isEnabled()) { + params.set_video_scaling_method( + static_cast( + video_tab_->scaling_method_combobox()->currentData().toInt())); + } - if (video_enabled_->isChecked()) { - ExportCodec::Codec video_codec = video_tab_->GetSelectedCodec(); + if (video_enabled_->isChecked()) { + ExportCodec::Codec video_codec = video_tab_->GetSelectedCodec(); - video_render_params.set_color_range(video_tab_->color_range()); + video_render_params.set_color_range(video_tab_->color_range()); - params.EnableVideo(video_render_params, video_codec); + params.EnableVideo(video_render_params, video_codec); - params.set_video_threads(video_tab_->threads()); + params.set_video_threads(video_tab_->threads()); - if (video_tab_->isVisible()) { - video_tab_->GetCodecSection()->AddOpts(¶ms); - } + if (video_tab_->isVisible()) { + video_tab_->GetCodecSection()->AddOpts(¶ms); + } - params.set_color_transform(video_tab_->CurrentOCIOColorSpace()); + params.set_color_transform(video_tab_->CurrentOCIOColorSpace()); - params.set_video_pix_fmt(video_tab_->pix_fmt()); + params.set_video_pix_fmt(video_tab_->pix_fmt()); - params.set_video_is_image_sequence(video_tab_->IsImageSequenceSet()); - } + params.set_video_is_image_sequence(video_tab_->IsImageSequenceSet()); + } - if (audio_enabled_->isChecked()) { - ExportCodec::Codec audio_codec = audio_tab_->GetCodec(); - params.EnableAudio(audio_render_params, audio_codec); + if (audio_enabled_->isChecked()) { + ExportCodec::Codec audio_codec = audio_tab_->GetCodec(); + params.EnableAudio(audio_render_params, audio_codec); - params.set_audio_bit_rate(audio_tab_->bit_rate_slider()->GetValue() * 1000); - } + params.set_audio_bit_rate(audio_tab_->bit_rate_slider()->GetValue() * + 1000); + } - if (subtitles_enabled_->isEnabled() - && subtitles_enabled_->isChecked()) { - if (!subtitle_tab_->GetSidecarEnabled()) { - // Export subtitles embedded in container - params.EnableSubtitles(subtitle_tab_->GetSubtitleCodec()); - } else { - // Export subtitles to a sidecar file - params.EnableSidecarSubtitles(subtitle_tab_->GetSidecarFormat(), subtitle_tab_->GetSubtitleCodec()); - } - } + if (subtitles_enabled_->isEnabled() && subtitles_enabled_->isChecked()) { + if (!subtitle_tab_->GetSidecarEnabled()) { + // Export subtitles embedded in container + params.EnableSubtitles(subtitle_tab_->GetSubtitleCodec()); + } else { + // Export subtitles to a sidecar file + params.EnableSidecarSubtitles(subtitle_tab_->GetSidecarFormat(), + subtitle_tab_->GetSubtitleCodec()); + } + } - return params; + return params; } void ExportDialog::SetParams(const EncodingParams &e) { - format_combobox_->SetFormat(e.format()); - FormatChanged(format_combobox_->GetFormat()); + format_combobox_->SetFormat(e.format()); + FormatChanged(format_combobox_->GetFormat()); - if (e.has_custom_range() && viewer_node_->GetWorkArea()->enabled()) { - range_combobox_->setCurrentIndex(kRangeInToOut); - } + if (e.has_custom_range() && viewer_node_->GetWorkArea()->enabled()) { + range_combobox_->setCurrentIndex(kRangeInToOut); + } - QtUtils::SetComboBoxData(video_tab_->scaling_method_combobox(), e.video_scaling_method()); + QtUtils::SetComboBoxData(video_tab_->scaling_method_combobox(), + e.video_scaling_method()); - video_enabled_->setChecked(e.video_enabled()); - if (e.video_enabled()) { - video_tab_->width_slider()->SetValue(e.video_params().width()); - video_tab_->height_slider()->SetValue(e.video_params().height()); - SetSelectedTimebase(e.video_params().time_base()); - video_tab_->pixel_format_field()->SetPixelFormat(e.video_params().format()); - video_tab_->pixel_aspect_combobox()->SetPixelAspectRatio(e.video_params().pixel_aspect_ratio()); - video_tab_->interlaced_combobox()->SetInterlaceMode(e.video_params().interlacing()); + video_enabled_->setChecked(e.video_enabled()); + if (e.video_enabled()) { + video_tab_->width_slider()->SetValue(e.video_params().width()); + video_tab_->height_slider()->SetValue(e.video_params().height()); + SetSelectedTimebase(e.video_params().time_base()); + video_tab_->pixel_format_field()->SetPixelFormat( + e.video_params().format()); + video_tab_->pixel_aspect_combobox()->SetPixelAspectRatio( + e.video_params().pixel_aspect_ratio()); + video_tab_->interlaced_combobox()->SetInterlaceMode( + e.video_params().interlacing()); - video_tab_->SetSelectedCodec(e.video_codec()); + video_tab_->SetSelectedCodec(e.video_codec()); - video_tab_->SetColorRange(e.video_params().color_range()); + video_tab_->SetColorRange(e.video_params().color_range()); - video_tab_->SetThreads(e.video_threads()); + video_tab_->SetThreads(e.video_threads()); - if (video_tab_->isVisible()) { - video_tab_->GetCodecSection()->SetOpts(&e); - } + if (video_tab_->isVisible()) { + video_tab_->GetCodecSection()->SetOpts(&e); + } - video_tab_->SetOCIOColorSpace(e.color_transform().output()); + video_tab_->SetOCIOColorSpace(e.color_transform().output()); - video_tab_->SetPixFmt(e.video_pix_fmt()); + video_tab_->SetPixFmt(e.video_pix_fmt()); - video_tab_->SetImageSequence(e.video_is_image_sequence()); - } + video_tab_->SetImageSequence(e.video_is_image_sequence()); + } - audio_enabled_->setChecked(e.audio_enabled()); - if (e.audio_enabled()) { - audio_tab_->sample_rate_combobox()->SetSampleRate(e.audio_params().sample_rate()); - audio_tab_->channel_layout_combobox()->SetChannelLayout(e.audio_params().channel_layout()); - audio_tab_->sample_format_combobox()->SetSampleFormat(e.audio_params().format()); + audio_enabled_->setChecked(e.audio_enabled()); + if (e.audio_enabled()) { + audio_tab_->sample_rate_combobox()->SetSampleRate( + e.audio_params().sample_rate()); + audio_tab_->channel_layout_combobox()->SetChannelLayout( + e.audio_params().channel_layout()); + audio_tab_->sample_format_combobox()->SetSampleFormat( + e.audio_params().format()); - audio_tab_->SetCodec(e.audio_codec()); + audio_tab_->SetCodec(e.audio_codec()); - audio_tab_->bit_rate_slider()->SetValue(e.audio_bit_rate() / 1000); - } + audio_tab_->bit_rate_slider()->SetValue(e.audio_bit_rate() / 1000); + } - if (subtitles_enabled_->isEnabled()) { - subtitles_enabled_->setChecked(e.subtitles_enabled()); - subtitle_tab_->SetSidecarEnabled(e.subtitles_are_sidecar()); - if (e.subtitles_enabled()) { - subtitle_tab_->SetSubtitleCodec(e.subtitles_codec()); - if (e.subtitles_are_sidecar()) { - subtitle_tab_->SetSidecarFormat(e.subtitle_sidecar_fmt()); - } - } - } + if (subtitles_enabled_->isEnabled()) { + subtitles_enabled_->setChecked(e.subtitles_enabled()); + subtitle_tab_->SetSidecarEnabled(e.subtitles_are_sidecar()); + if (e.subtitles_enabled()) { + subtitle_tab_->SetSubtitleCodec(e.subtitles_codec()); + if (e.subtitles_are_sidecar()) { + subtitle_tab_->SetSidecarFormat(e.subtitle_sidecar_fmt()); + } + } + } } bool ExportDialog::eventFilter(QObject *o, QEvent *e) { - // Any parameters in scrollable areas, ignore wheel events so the user doesn't unwittingly change - // them while trying to scroll through the pages - if (e->type() == QEvent::Wheel) { - while ((o = o->parent())) { - if (o == video_tab_ || o == audio_tab_ || o == subtitle_tab_) { - e->ignore(); - return true; - } - } - } + // Any parameters in scrollable areas, ignore wheel events so the user doesn't unwittingly change + // them while trying to scroll through the pages + if (e->type() == QEvent::Wheel) { + while ((o = o->parent())) { + if (o == video_tab_ || o == audio_tab_ || o == subtitle_tab_) { + e->ignore(); + return true; + } + } + } - return super::eventFilter(o, e); + return super::eventFilter(o, e); } void ExportDialog::done(int r) { - preview_viewer_->ConnectViewerNode(nullptr); + preview_viewer_->ConnectViewerNode(nullptr); - if (!stills_only_mode_) { - viewer_node_->SetLastUsedEncodingParams(GenerateParams()); - } + if (!stills_only_mode_) { + viewer_node_->SetLastUsedEncodingParams(GenerateParams()); + } - super::done(r); + super::done(r); } rational ExportDialog::GetExportLength() const { - if (range_combobox_->currentIndex() == kRangeInToOut) { - return viewer_node_->GetWorkArea()->range().length(); - } else { - return viewer_node_->GetLength(); - } + if (range_combobox_->currentIndex() == kRangeInToOut) { + return viewer_node_->GetWorkArea()->range().length(); + } else { + return viewer_node_->GetLength(); + } } int64_t ExportDialog::GetExportLengthInTimebaseUnits() const { - return Timecode::time_to_timestamp(GetExportLength(), GetSelectedTimebase()); + return Timecode::time_to_timestamp(GetExportLength(), + GetSelectedTimebase()); } void ExportDialog::UpdateViewerDimensions() { - preview_viewer_->SetViewerResolution(static_cast(video_tab_->width_slider()->GetValue()), - static_cast(video_tab_->height_slider()->GetValue())); + preview_viewer_->SetViewerResolution( + static_cast(video_tab_->width_slider()->GetValue()), + static_cast(video_tab_->height_slider()->GetValue())); - VideoParams vp = viewer_node_->GetVideoParams(); + VideoParams vp = viewer_node_->GetVideoParams(); - QMatrix4x4 transform = EncodingParams::GenerateMatrix( - static_cast(video_tab_->scaling_method_combobox()->currentData().toInt()), - vp.width(), - vp.height(), - static_cast(video_tab_->width_slider()->GetValue()), - static_cast(video_tab_->height_slider()->GetValue()) - ); + QMatrix4x4 transform = EncodingParams::GenerateMatrix( + static_cast( + video_tab_->scaling_method_combobox()->currentData().toInt()), + vp.width(), vp.height(), + static_cast(video_tab_->width_slider()->GetValue()), + static_cast(video_tab_->height_slider()->GetValue())); - preview_viewer_->SetMatrix(transform); + preview_viewer_->SetMatrix(transform); } } diff --git a/app/dialog/export/export.h b/app/dialog/export/export.h index b0afc83ac..90b0f3478 100644 --- a/app/dialog/export/export.h +++ b/app/dialog/export/export.h @@ -37,107 +37,105 @@ #include "widget/nodeparamview/nodeparamviewwidgetbridge.h" #include "widget/viewer/viewer.h" -namespace olive { - -class ExportDialog : public QDialog +namespace olive { - Q_OBJECT + +class ExportDialog : public QDialog { + Q_OBJECT public: - ExportDialog(ViewerOutput* viewer_node, bool stills_only_mode, QWidget* parent = nullptr); - ExportDialog(ViewerOutput* viewer_node, QWidget* parent = nullptr) : - ExportDialog(viewer_node, false, parent) - {} + ExportDialog(ViewerOutput *viewer_node, bool stills_only_mode, + QWidget *parent = nullptr); + ExportDialog(ViewerOutput *viewer_node, QWidget *parent = nullptr) + : ExportDialog(viewer_node, false, parent) + { + } - rational GetSelectedTimebase() const; - void SetSelectedTimebase(const rational &r); + rational GetSelectedTimebase() const; + void SetSelectedTimebase(const rational &r); - EncodingParams GenerateParams() const; - void SetParams(const EncodingParams &e); + EncodingParams GenerateParams() const; + void SetParams(const EncodingParams &e); - virtual bool eventFilter(QObject *o, QEvent *e) override; + virtual bool eventFilter(QObject *o, QEvent *e) override; public slots: - virtual void done(int r) override; + virtual void done(int r) override; signals: - void RequestImportFile(const QString &s); + void RequestImportFile(const QString &s); private: - void AddPreferencesTab(QWidget *inner_widget, const QString &title); + void AddPreferencesTab(QWidget *inner_widget, const QString &title); - void LoadPresets(); - void SetDefaultFilename(); + void LoadPresets(); + void SetDefaultFilename(); - bool SequenceHasSubtitles() const; + bool SequenceHasSubtitles() const; - void SetDefaults(); + void SetDefaults(); - ViewerOutput* viewer_node_; + ViewerOutput *viewer_node_; - ExportFormat::Format previously_selected_format_; + ExportFormat::Format previously_selected_format_; - rational GetExportLength() const; - int64_t GetExportLengthInTimebaseUnits() const; + rational GetExportLength() const; + int64_t GetExportLengthInTimebaseUnits() const; - enum RangeSelection { - kRangeEntireSequence, - kRangeInToOut - }; + enum RangeSelection { kRangeEntireSequence, kRangeInToOut }; - enum AutoPreset { - kPresetDefault = -1, - kPresetLastUsed = -2, - }; + enum AutoPreset { + kPresetDefault = -1, + kPresetLastUsed = -2, + }; - QTabWidget* preferences_tabs_; + QTabWidget *preferences_tabs_; - QComboBox* preset_combobox_; - QComboBox* range_combobox_; - std::vector presets_; + QComboBox *preset_combobox_; + QComboBox *range_combobox_; + std::vector presets_; - QCheckBox* video_enabled_; - QCheckBox* audio_enabled_; - QCheckBox* subtitles_enabled_; + QCheckBox *video_enabled_; + QCheckBox *audio_enabled_; + QCheckBox *subtitles_enabled_; - ViewerWidget* preview_viewer_; - QLineEdit* filename_edit_; - ExportFormatComboBox* format_combobox_; + ViewerWidget *preview_viewer_; + QLineEdit *filename_edit_; + ExportFormatComboBox *format_combobox_; - ExportVideoTab* video_tab_; - ExportAudioTab* audio_tab_; - ExportSubtitlesTab* subtitle_tab_; + ExportVideoTab *video_tab_; + ExportAudioTab *audio_tab_; + ExportSubtitlesTab *subtitle_tab_; - double video_aspect_ratio_; + double video_aspect_ratio_; - ColorManager* color_manager_; + ColorManager *color_manager_; - QWidget* preferences_area_; - QCheckBox *export_bkg_box_; - QCheckBox *import_file_after_export_; + QWidget *preferences_area_; + QCheckBox *export_bkg_box_; + QCheckBox *import_file_after_export_; - bool stills_only_mode_; + bool stills_only_mode_; - bool loading_presets_; + bool loading_presets_; private slots: - void BrowseFilename(); + void BrowseFilename(); - void FormatChanged(ExportFormat::Format current_format); + void FormatChanged(ExportFormat::Format current_format); - void ResolutionChanged(); + void ResolutionChanged(); - void UpdateViewerDimensions(); + void UpdateViewerDimensions(); - void StartExport(); + void StartExport(); - void ExportFinished(); + void ExportFinished(); - void ImageSequenceCheckBoxChanged(bool e); + void ImageSequenceCheckBoxChanged(bool e); - void SavePreset(); - - void PresetComboBoxChanged(); + void SavePreset(); + void PresetComboBoxChanged(); }; } diff --git a/app/dialog/export/exportadvancedvideodialog.cpp b/app/dialog/export/exportadvancedvideodialog.cpp index 2d08ceacd..4932778b9 100644 --- a/app/dialog/export/exportadvancedvideodialog.cpp +++ b/app/dialog/export/exportadvancedvideodialog.cpp @@ -5,65 +5,71 @@ #include #include -namespace olive { - -ExportAdvancedVideoDialog::ExportAdvancedVideoDialog(const QList &pix_fmts, QWidget *parent) : - QDialog(parent) +namespace olive { - setWindowTitle(tr("Advanced")); - QVBoxLayout* layout = new QVBoxLayout(this); +ExportAdvancedVideoDialog::ExportAdvancedVideoDialog( + const QList &pix_fmts, QWidget *parent) + : QDialog(parent) +{ + setWindowTitle(tr("Advanced")); - { - // Pixel Settings - QGroupBox* pixel_group = new QGroupBox(); - layout->addWidget(pixel_group); - pixel_group->setTitle(tr("Pixel")); + QVBoxLayout *layout = new QVBoxLayout(this); - QGridLayout* pixel_layout = new QGridLayout(pixel_group); + { + // Pixel Settings + QGroupBox *pixel_group = new QGroupBox(); + layout->addWidget(pixel_group); + pixel_group->setTitle(tr("Pixel")); - int row = 0; + QGridLayout *pixel_layout = new QGridLayout(pixel_group); - pixel_layout->addWidget(new QLabel(tr("Pixel Format:")), row, 0); + int row = 0; - pixel_format_combobox_ = new QComboBox(); - pixel_format_combobox_->addItems(pix_fmts); - pixel_layout->addWidget(pixel_format_combobox_, row, 1); + pixel_layout->addWidget(new QLabel(tr("Pixel Format:")), row, 0); - row++; + pixel_format_combobox_ = new QComboBox(); + pixel_format_combobox_->addItems(pix_fmts); + pixel_layout->addWidget(pixel_format_combobox_, row, 1); - pixel_layout->addWidget(new QLabel(tr("YUV Color Range:")), row, 0); + row++; - yuv_color_range_combobox_ = new QComboBox(); - yuv_color_range_combobox_->addItems({tr("Limited (16-235)"), tr("Full (0-255)")}); - pixel_layout->addWidget(yuv_color_range_combobox_, row, 1); - } + pixel_layout->addWidget(new QLabel(tr("YUV Color Range:")), row, 0); - { - // Performance Settings - QGroupBox* performance_group = new QGroupBox(); - layout->addWidget(performance_group); - performance_group->setTitle(tr("Performance")); + yuv_color_range_combobox_ = new QComboBox(); + yuv_color_range_combobox_->addItems( + { tr("Limited (16-235)"), tr("Full (0-255)") }); + pixel_layout->addWidget(yuv_color_range_combobox_, row, 1); + } - QGridLayout* performance_layout = new QGridLayout(performance_group); + { + // Performance Settings + QGroupBox *performance_group = new QGroupBox(); + layout->addWidget(performance_group); + performance_group->setTitle(tr("Performance")); - int row = 0; + QGridLayout *performance_layout = new QGridLayout(performance_group); - performance_layout->addWidget(new QLabel(tr("Threads:")), row, 0); + int row = 0; - thread_slider_ = new IntegerSlider(); - thread_slider_->SetMinimum(0); - thread_slider_->SetDefaultValue(0); - thread_slider_->InsertLabelSubstitution(0, tr("Auto")); - performance_layout->addWidget(thread_slider_, row, 1); + performance_layout->addWidget(new QLabel(tr("Threads:")), row, 0); - row++; - } + thread_slider_ = new IntegerSlider(); + thread_slider_->SetMinimum(0); + thread_slider_->SetDefaultValue(0); + thread_slider_->InsertLabelSubstitution(0, tr("Auto")); + performance_layout->addWidget(thread_slider_, row, 1); - QDialogButtonBox* buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); - connect(buttons, &QDialogButtonBox::accepted, this, &ExportAdvancedVideoDialog::accept); - connect(buttons, &QDialogButtonBox::rejected, this, &ExportAdvancedVideoDialog::reject); - layout->addWidget(buttons); + row++; + } + + QDialogButtonBox *buttons = + new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); + connect(buttons, &QDialogButtonBox::accepted, this, + &ExportAdvancedVideoDialog::accept); + connect(buttons, &QDialogButtonBox::rejected, this, + &ExportAdvancedVideoDialog::reject); + layout->addWidget(buttons); } } diff --git a/app/dialog/export/exportadvancedvideodialog.h b/app/dialog/export/exportadvancedvideodialog.h index f001a476d..13a34d733 100644 --- a/app/dialog/export/exportadvancedvideodialog.h +++ b/app/dialog/export/exportadvancedvideodialog.h @@ -7,52 +7,52 @@ #include "codec/encoder.h" #include "widget/slider/integerslider.h" -namespace olive { - -class ExportAdvancedVideoDialog : public QDialog +namespace olive { - Q_OBJECT + +class ExportAdvancedVideoDialog : public QDialog { + Q_OBJECT public: - ExportAdvancedVideoDialog(const QList& pix_fmts, - QWidget* parent = nullptr); + ExportAdvancedVideoDialog(const QList &pix_fmts, + QWidget *parent = nullptr); - int threads() const - { - return static_cast(thread_slider_->GetValue()); - } + int threads() const + { + return static_cast(thread_slider_->GetValue()); + } - void set_threads(int t) - { - thread_slider_->SetValue(t); - } + void set_threads(int t) + { + thread_slider_->SetValue(t); + } - QString pix_fmt() const - { - return pixel_format_combobox_->currentText(); - } + QString pix_fmt() const + { + return pixel_format_combobox_->currentText(); + } - void set_pix_fmt(const QString& s) - { - pixel_format_combobox_->setCurrentText(s); - } + void set_pix_fmt(const QString &s) + { + pixel_format_combobox_->setCurrentText(s); + } - VideoParams::ColorRange yuv_range() const - { - return static_cast(yuv_color_range_combobox_->currentIndex()); - } + VideoParams::ColorRange yuv_range() const + { + return static_cast( + yuv_color_range_combobox_->currentIndex()); + } - void set_yuv_range(VideoParams::ColorRange i) - { - yuv_color_range_combobox_->setCurrentIndex(i); - } + void set_yuv_range(VideoParams::ColorRange i) + { + yuv_color_range_combobox_->setCurrentIndex(i); + } private: - IntegerSlider* thread_slider_; + IntegerSlider *thread_slider_; - QComboBox* pixel_format_combobox_; - - QComboBox* yuv_color_range_combobox_; + QComboBox *pixel_format_combobox_; + QComboBox *yuv_color_range_combobox_; }; } diff --git a/app/dialog/export/exportaudiotab.cpp b/app/dialog/export/exportaudiotab.cpp index 45ee90a7a..2f0194a1e 100644 --- a/app/dialog/export/exportaudiotab.cpp +++ b/app/dialog/export/exportaudiotab.cpp @@ -25,96 +25,103 @@ #include "core.h" -namespace olive { +namespace olive +{ const int ExportAudioTab::kDefaultBitRate = 320; -ExportAudioTab::ExportAudioTab(QWidget* parent) : - QWidget(parent) +ExportAudioTab::ExportAudioTab(QWidget *parent) + : QWidget(parent) { - QVBoxLayout* outer_layout = new QVBoxLayout(this); + QVBoxLayout *outer_layout = new QVBoxLayout(this); - QGridLayout* layout = new QGridLayout(); - outer_layout->addLayout(layout); + QGridLayout *layout = new QGridLayout(); + outer_layout->addLayout(layout); - int row = 0; + int row = 0; - layout->addWidget(new QLabel(tr("Codec:")), row, 0); + layout->addWidget(new QLabel(tr("Codec:")), row, 0); - codec_combobox_ = new QComboBox(); - connect(codec_combobox_, static_cast(&QComboBox::currentIndexChanged), this, &ExportAudioTab::UpdateSampleFormats); - connect(codec_combobox_, static_cast(&QComboBox::currentIndexChanged), this, &ExportAudioTab::UpdateBitRateEnabled); - layout->addWidget(codec_combobox_, row, 1); + codec_combobox_ = new QComboBox(); + connect( + codec_combobox_, + static_cast(&QComboBox::currentIndexChanged), + this, &ExportAudioTab::UpdateSampleFormats); + connect( + codec_combobox_, + static_cast(&QComboBox::currentIndexChanged), + this, &ExportAudioTab::UpdateBitRateEnabled); + layout->addWidget(codec_combobox_, row, 1); - row++; + row++; - layout->addWidget(new QLabel(tr("Sample Rate:")), row, 0); + layout->addWidget(new QLabel(tr("Sample Rate:")), row, 0); - sample_rate_combobox_ = new SampleRateComboBox(); - layout->addWidget(sample_rate_combobox_, row, 1); + sample_rate_combobox_ = new SampleRateComboBox(); + layout->addWidget(sample_rate_combobox_, row, 1); - row++; + row++; - layout->addWidget(new QLabel(tr("Channel Layout:")), row, 0); + layout->addWidget(new QLabel(tr("Channel Layout:")), row, 0); - channel_layout_combobox_ = new ChannelLayoutComboBox(); - layout->addWidget(channel_layout_combobox_, row, 1); + channel_layout_combobox_ = new ChannelLayoutComboBox(); + layout->addWidget(channel_layout_combobox_, row, 1); - row++; + row++; - layout->addWidget(new QLabel(tr("Format:")), row, 0); + layout->addWidget(new QLabel(tr("Format:")), row, 0); - sample_format_combobox_ = new SampleFormatComboBox(); - layout->addWidget(sample_format_combobox_, row, 1); + sample_format_combobox_ = new SampleFormatComboBox(); + layout->addWidget(sample_format_combobox_, row, 1); - row++; + row++; - layout->addWidget(new QLabel(tr("Bit Rate:")), row, 0); + layout->addWidget(new QLabel(tr("Bit Rate:")), row, 0); - bit_rate_slider_ = new IntegerSlider(); - bit_rate_slider_->SetMinimum(32); - bit_rate_slider_->SetMaximum(320); - bit_rate_slider_->SetValue(kDefaultBitRate); - bit_rate_slider_->SetFormat(tr("%1 kbps")); - layout->addWidget(bit_rate_slider_, row, 1); + bit_rate_slider_ = new IntegerSlider(); + bit_rate_slider_->SetMinimum(32); + bit_rate_slider_->SetMaximum(320); + bit_rate_slider_->SetValue(kDefaultBitRate); + bit_rate_slider_->SetFormat(tr("%1 kbps")); + layout->addWidget(bit_rate_slider_, row, 1); - outer_layout->addStretch(); + outer_layout->addStretch(); } int ExportAudioTab::SetFormat(ExportFormat::Format format) { - QList acodecs = ExportFormat::GetAudioCodecs(format); - setEnabled(!acodecs.isEmpty()); - codec_combobox_->blockSignals(true); - codec_combobox_->clear(); - foreach (ExportCodec::Codec acodec, acodecs) { - codec_combobox_->addItem(ExportCodec::GetCodecName(acodec), acodec); - } - codec_combobox_->blockSignals(false); - fmt_ = format; + QList acodecs = ExportFormat::GetAudioCodecs(format); + setEnabled(!acodecs.isEmpty()); + codec_combobox_->blockSignals(true); + codec_combobox_->clear(); + foreach (ExportCodec::Codec acodec, acodecs) { + codec_combobox_->addItem(ExportCodec::GetCodecName(acodec), acodec); + } + codec_combobox_->blockSignals(false); + fmt_ = format; - UpdateSampleFormats(); - UpdateBitRateEnabled(); + UpdateSampleFormats(); + UpdateBitRateEnabled(); - return acodecs.size(); + return acodecs.size(); } void ExportAudioTab::UpdateSampleFormats() { - auto fmts = ExportFormat::GetSampleFormatsForCodec(fmt_, GetCodec()); - sample_format_combobox_->SetAvailableFormats(fmts); + auto fmts = ExportFormat::GetSampleFormatsForCodec(fmt_, GetCodec()); + sample_format_combobox_->SetAvailableFormats(fmts); } void ExportAudioTab::UpdateBitRateEnabled() { - bool uses_bitrate = !ExportCodec::IsCodecLossless(GetCodec()); - bit_rate_slider_->setEnabled(uses_bitrate); + bool uses_bitrate = !ExportCodec::IsCodecLossless(GetCodec()); + bit_rate_slider_->setEnabled(uses_bitrate); - if (!uses_bitrate) { - bit_rate_slider_->SetTristate(); - } else { - bit_rate_slider_->SetValue(kDefaultBitRate ); - } + if (!uses_bitrate) { + bit_rate_slider_->SetTristate(); + } else { + bit_rate_slider_->SetValue(kDefaultBitRate); + } } } diff --git a/app/dialog/export/exportaudiotab.h b/app/dialog/export/exportaudiotab.h index e7463364a..f8325e3c0 100644 --- a/app/dialog/export/exportaudiotab.h +++ b/app/dialog/export/exportaudiotab.h @@ -29,67 +29,67 @@ #include "widget/slider/integerslider.h" #include "widget/standardcombos/standardcombos.h" -namespace olive { - -class ExportAudioTab : public QWidget +namespace olive { - Q_OBJECT + +class ExportAudioTab : public QWidget { + Q_OBJECT public: - ExportAudioTab(QWidget* parent = nullptr); + ExportAudioTab(QWidget *parent = nullptr); - ExportCodec::Codec GetCodec() const - { - return static_cast(codec_combobox_->currentData().toInt()); - } + ExportCodec::Codec GetCodec() const + { + return static_cast( + codec_combobox_->currentData().toInt()); + } - void SetCodec(ExportCodec::Codec c) - { - for (int i=0; icount(); i++) { - if (codec_combobox_->itemData(i) == c) { - codec_combobox_->setCurrentIndex(i); - break; - } - } - } + void SetCodec(ExportCodec::Codec c) + { + for (int i = 0; i < codec_combobox_->count(); i++) { + if (codec_combobox_->itemData(i) == c) { + codec_combobox_->setCurrentIndex(i); + break; + } + } + } - SampleRateComboBox* sample_rate_combobox() const - { - return sample_rate_combobox_; - } + SampleRateComboBox *sample_rate_combobox() const + { + return sample_rate_combobox_; + } - SampleFormatComboBox* sample_format_combobox() const - { - return sample_format_combobox_; - } + SampleFormatComboBox *sample_format_combobox() const + { + return sample_format_combobox_; + } - ChannelLayoutComboBox* channel_layout_combobox() const - { - return channel_layout_combobox_; - } + ChannelLayoutComboBox *channel_layout_combobox() const + { + return channel_layout_combobox_; + } - IntegerSlider* bit_rate_slider() const - { - return bit_rate_slider_; - } + IntegerSlider *bit_rate_slider() const + { + return bit_rate_slider_; + } public slots: - int SetFormat(ExportFormat::Format format); + int SetFormat(ExportFormat::Format format); private: - ExportFormat::Format fmt_; - QComboBox* codec_combobox_; - SampleRateComboBox* sample_rate_combobox_; - ChannelLayoutComboBox* channel_layout_combobox_; - SampleFormatComboBox *sample_format_combobox_; - IntegerSlider* bit_rate_slider_; + ExportFormat::Format fmt_; + QComboBox *codec_combobox_; + SampleRateComboBox *sample_rate_combobox_; + ChannelLayoutComboBox *channel_layout_combobox_; + SampleFormatComboBox *sample_format_combobox_; + IntegerSlider *bit_rate_slider_; - static const int kDefaultBitRate; + static const int kDefaultBitRate; private slots: - void UpdateSampleFormats(); - - void UpdateBitRateEnabled(); + void UpdateSampleFormats(); + void UpdateBitRateEnabled(); }; } diff --git a/app/dialog/export/exportformatcombobox.cpp b/app/dialog/export/exportformatcombobox.cpp index 2c60cb1a2..658429783 100644 --- a/app/dialog/export/exportformatcombobox.cpp +++ b/app/dialog/export/exportformatcombobox.cpp @@ -25,115 +25,119 @@ #include "ui/icons/icons.h" -namespace olive { - -ExportFormatComboBox::ExportFormatComboBox(Mode mode, QWidget *parent) : - QComboBox(parent) +namespace olive { - custom_menu_ = new Menu(this); - // Populate combobox formats - switch (mode) { - case kShowAllFormats: - custom_menu_->addAction(CreateHeader(icon::Video, tr("Video"))); - PopulateType(Track::kVideo); - custom_menu_->addSeparator(); +ExportFormatComboBox::ExportFormatComboBox(Mode mode, QWidget *parent) + : QComboBox(parent) +{ + custom_menu_ = new Menu(this); - custom_menu_->addAction(CreateHeader(icon::Audio, tr("Audio"))); - PopulateType(Track::kAudio); - custom_menu_->addSeparator(); + // Populate combobox formats + switch (mode) { + case kShowAllFormats: + custom_menu_->addAction(CreateHeader(icon::Video, tr("Video"))); + PopulateType(Track::kVideo); + custom_menu_->addSeparator(); - custom_menu_->addAction(CreateHeader(icon::Subtitles, tr("Subtitle"))); - PopulateType(Track::kSubtitle); - break; - case kShowAudioOnly: - PopulateType(Track::kAudio); - break; - case kShowVideoOnly: - PopulateType(Track::kVideo); - break; - case kShowSubtitlesOnly: - PopulateType(Track::kSubtitle); - break; - } + custom_menu_->addAction(CreateHeader(icon::Audio, tr("Audio"))); + PopulateType(Track::kAudio); + custom_menu_->addSeparator(); - connect(custom_menu_, &Menu::triggered, this, &ExportFormatComboBox::HandleIndexChange); + custom_menu_->addAction(CreateHeader(icon::Subtitles, tr("Subtitle"))); + PopulateType(Track::kSubtitle); + break; + case kShowAudioOnly: + PopulateType(Track::kAudio); + break; + case kShowVideoOnly: + PopulateType(Track::kVideo); + break; + case kShowSubtitlesOnly: + PopulateType(Track::kSubtitle); + break; + } + + connect(custom_menu_, &Menu::triggered, this, + &ExportFormatComboBox::HandleIndexChange); } void ExportFormatComboBox::showPopup() { - custom_menu_->setMinimumWidth(this->width()); - custom_menu_->exec(mapToGlobal(QPoint(0, 0))); + custom_menu_->setMinimumWidth(this->width()); + custom_menu_->exec(mapToGlobal(QPoint(0, 0))); } void ExportFormatComboBox::SetFormat(ExportFormat::Format fmt) { - current_ = fmt; - clear(); - addItem(ExportFormat::GetName(current_)); + current_ = fmt; + clear(); + addItem(ExportFormat::GetName(current_)); } void ExportFormatComboBox::HandleIndexChange(QAction *a) { - ExportFormat::Format f = static_cast(a->data().toInt()); - SetFormat(f); - emit FormatChanged(f); + ExportFormat::Format f = + static_cast(a->data().toInt()); + SetFormat(f); + emit FormatChanged(f); } void ExportFormatComboBox::PopulateType(Track::Type type) { - for (int i=0; i(i); + for (int i = 0; i < ExportFormat::kFormatCount; i++) { + ExportFormat::Format f = static_cast(i); - if (type == Track::kVideo - && !ExportFormat::GetVideoCodecs(f).isEmpty()) { - // Do nothing - } else if (type == Track::kAudio - && ExportFormat::GetVideoCodecs(f).isEmpty() - && !ExportFormat::GetAudioCodecs(f).isEmpty()) { - // Do nothing - } else if (type == Track::kSubtitle - && ExportFormat::GetVideoCodecs(f).isEmpty() - && ExportFormat::GetAudioCodecs(f).isEmpty() - && !ExportFormat::GetSubtitleCodecs(f).isEmpty()) { - // Do nothing - } else { - continue; - } + if (type == Track::kVideo && + !ExportFormat::GetVideoCodecs(f).isEmpty()) { + // Do nothing + } else if (type == Track::kAudio && + ExportFormat::GetVideoCodecs(f).isEmpty() && + !ExportFormat::GetAudioCodecs(f).isEmpty()) { + // Do nothing + } else if (type == Track::kSubtitle && + ExportFormat::GetVideoCodecs(f).isEmpty() && + ExportFormat::GetAudioCodecs(f).isEmpty() && + !ExportFormat::GetSubtitleCodecs(f).isEmpty()) { + // Do nothing + } else { + continue; + } - QString format_name = ExportFormat::GetName(f); + QString format_name = ExportFormat::GetName(f); - QAction *a = custom_menu_->addAction(format_name); - a->setData(i); - a->setIconVisibleInMenu(false); - } + QAction *a = custom_menu_->addAction(format_name); + a->setData(i); + a->setIconVisibleInMenu(false); + } } -QWidgetAction *ExportFormatComboBox::CreateHeader(const QIcon &icon, const QString &title) +QWidgetAction *ExportFormatComboBox::CreateHeader(const QIcon &icon, + const QString &title) { - QWidgetAction *a = new QWidgetAction(this); + QWidgetAction *a = new QWidgetAction(this); - QWidget *w = new QWidget(); - QHBoxLayout *layout = new QHBoxLayout(w); + QWidget *w = new QWidget(); + QHBoxLayout *layout = new QHBoxLayout(w); - QLabel *icon_lbl = new QLabel(); + QLabel *icon_lbl = new QLabel(); - QLabel *text_lbl = new QLabel(title); - text_lbl->setAlignment(Qt::AlignCenter); - QFont f = text_lbl->font(); - f.setWeight(QFont::Bold); - text_lbl->setFont(f); + QLabel *text_lbl = new QLabel(title); + text_lbl->setAlignment(Qt::AlignCenter); + QFont f = text_lbl->font(); + f.setWeight(QFont::Bold); + text_lbl->setFont(f); - icon_lbl->setPixmap(icon.pixmap(text_lbl->sizeHint())); + icon_lbl->setPixmap(icon.pixmap(text_lbl->sizeHint())); - layout->addStretch(); - layout->addWidget(icon_lbl); - layout->addWidget(text_lbl); - layout->addStretch(); + layout->addStretch(); + layout->addWidget(icon_lbl); + layout->addWidget(text_lbl); + layout->addStretch(); - a->setDefaultWidget(w); - a->setEnabled(false); - return a; + a->setDefaultWidget(w); + a->setEnabled(false); + return a; } } diff --git a/app/dialog/export/exportformatcombobox.h b/app/dialog/export/exportformatcombobox.h index 8cff5beec..32be322ec 100644 --- a/app/dialog/export/exportformatcombobox.h +++ b/app/dialog/export/exportformatcombobox.h @@ -28,49 +28,49 @@ #include "node/output/track/track.h" #include "widget/menu/menu.h" -namespace olive { - -class ExportFormatComboBox : public QComboBox +namespace olive { - Q_OBJECT + +class ExportFormatComboBox : public QComboBox { + Q_OBJECT public: - enum Mode { - kShowAllFormats, - kShowAudioOnly, - kShowVideoOnly, - kShowSubtitlesOnly - }; + enum Mode { + kShowAllFormats, + kShowAudioOnly, + kShowVideoOnly, + kShowSubtitlesOnly + }; - ExportFormatComboBox(Mode mode, QWidget *parent = nullptr); - ExportFormatComboBox(QWidget *parent = nullptr) : - ExportFormatComboBox(kShowAllFormats, parent) - {} + ExportFormatComboBox(Mode mode, QWidget *parent = nullptr); + ExportFormatComboBox(QWidget *parent = nullptr) + : ExportFormatComboBox(kShowAllFormats, parent) + { + } - ExportFormat::Format GetFormat() const - { - return current_; - } + ExportFormat::Format GetFormat() const + { + return current_; + } - void showPopup(); + void showPopup(); signals: - void FormatChanged(ExportFormat::Format fmt); + void FormatChanged(ExportFormat::Format fmt); public slots: - void SetFormat(ExportFormat::Format fmt); + void SetFormat(ExportFormat::Format fmt); private slots: - void HandleIndexChange(QAction *a); + void HandleIndexChange(QAction *a); private: - void PopulateType(Track::Type type); + void PopulateType(Track::Type type); - QWidgetAction *CreateHeader(const QIcon &icon, const QString &title); + QWidgetAction *CreateHeader(const QIcon &icon, const QString &title); - Menu *custom_menu_; - - ExportFormat::Format current_; + Menu *custom_menu_; + ExportFormat::Format current_; }; } diff --git a/app/dialog/export/exportsavepresetdialog.cpp b/app/dialog/export/exportsavepresetdialog.cpp index 03052c4ec..aadd2712a 100644 --- a/app/dialog/export/exportsavepresetdialog.cpp +++ b/app/dialog/export/exportsavepresetdialog.cpp @@ -25,73 +25,86 @@ #include #include -namespace olive { - -ExportSavePresetDialog::ExportSavePresetDialog(const EncodingParams &p, QWidget *parent) : - QDialog(parent), - params_(p) +namespace olive { - auto layout = new QVBoxLayout(this); - name_edit_ = new QLineEdit(); +ExportSavePresetDialog::ExportSavePresetDialog(const EncodingParams &p, + QWidget *parent) + : QDialog(parent) + , params_(p) +{ + auto layout = new QVBoxLayout(this); - // Populate existing list - QStringList l = EncodingParams::GetListOfPresets(); - if (!l.empty()) { - auto list_widget_ = new QListWidget(); - for (const QString &f : l) { - list_widget_->addItem(f); - } - connect(list_widget_, &QListWidget::currentTextChanged, name_edit_, &QLineEdit::setText); - layout->addWidget(list_widget_); - } + name_edit_ = new QLineEdit(); - auto name_layout = new QHBoxLayout(); - layout->addLayout(name_layout); + // Populate existing list + QStringList l = EncodingParams::GetListOfPresets(); + if (!l.empty()) { + auto list_widget_ = new QListWidget(); + for (const QString &f : l) { + list_widget_->addItem(f); + } + connect(list_widget_, &QListWidget::currentTextChanged, name_edit_, + &QLineEdit::setText); + layout->addWidget(list_widget_); + } - name_layout->addWidget(new QLabel(tr("Name:"))); + auto name_layout = new QHBoxLayout(); + layout->addLayout(name_layout); - name_edit_->setFocus(); - name_layout->addWidget(name_edit_); + name_layout->addWidget(new QLabel(tr("Name:"))); - auto btns = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); - connect(btns, &QDialogButtonBox::accepted, this, &ExportSavePresetDialog::accept); - connect(btns, &QDialogButtonBox::rejected, this, &ExportSavePresetDialog::reject); - layout->addWidget(btns); + name_edit_->setFocus(); + name_layout->addWidget(name_edit_); - setWindowTitle(tr("Save Export Preset")); + auto btns = + new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); + connect(btns, &QDialogButtonBox::accepted, this, + &ExportSavePresetDialog::accept); + connect(btns, &QDialogButtonBox::rejected, this, + &ExportSavePresetDialog::reject); + layout->addWidget(btns); + + setWindowTitle(tr("Save Export Preset")); } void ExportSavePresetDialog::accept() { - if (name_edit_->text().isEmpty()) { - QMessageBox::critical(this, tr("Invalid Name"), tr("You must enter a name to save an export preset.")); - return; - } + if (name_edit_->text().isEmpty()) { + QMessageBox::critical( + this, tr("Invalid Name"), + tr("You must enter a name to save an export preset.")); + return; + } - QDir d(EncodingParams::GetPresetPath()); - if (!d.exists()) { - d.mkpath(QStringLiteral(".")); - } + QDir d(EncodingParams::GetPresetPath()); + if (!d.exists()) { + d.mkpath(QStringLiteral(".")); + } - QFile f(d.filePath(name_edit_->text())); - if (f.exists()) { - if (QMessageBox::question(this, tr("Overwrite Preset"), tr("A preset with the name \"%1\" already exists. Do you wish to overwrite it?").arg(name_edit_->text()), - QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) { - return; - } - } + QFile f(d.filePath(name_edit_->text())); + if (f.exists()) { + if (QMessageBox::question( + this, tr("Overwrite Preset"), + tr("A preset with the name \"%1\" already exists. Do you wish to overwrite it?") + .arg(name_edit_->text()), + QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) { + return; + } + } - if (!f.open(QFile::WriteOnly)) { - QMessageBox::critical(this, tr("Write Error"), tr("Failed to open file \"%1\" for writing.").arg(f.fileName())); - return; - } + if (!f.open(QFile::WriteOnly)) { + QMessageBox::critical( + this, tr("Write Error"), + tr("Failed to open file \"%1\" for writing.").arg(f.fileName())); + return; + } - params_.Save(&f); + params_.Save(&f); - f.close(); + f.close(); - QDialog::accept(); + QDialog::accept(); } } diff --git a/app/dialog/export/exportsavepresetdialog.h b/app/dialog/export/exportsavepresetdialog.h index 1f8ca09b9..3791bea20 100644 --- a/app/dialog/export/exportsavepresetdialog.h +++ b/app/dialog/export/exportsavepresetdialog.h @@ -27,27 +27,26 @@ #include "codec/encoder.h" -namespace olive { - -class ExportSavePresetDialog : public QDialog +namespace olive { - Q_OBJECT -public: - ExportSavePresetDialog(const EncodingParams &p, QWidget *parent = nullptr); - QString GetSelectedPresetName() const - { - return name_edit_->text(); - } +class ExportSavePresetDialog : public QDialog { + Q_OBJECT +public: + ExportSavePresetDialog(const EncodingParams &p, QWidget *parent = nullptr); + + QString GetSelectedPresetName() const + { + return name_edit_->text(); + } public slots: - virtual void accept() override; + virtual void accept() override; private: - QLineEdit *name_edit_; - - EncodingParams params_; + QLineEdit *name_edit_; + EncodingParams params_; }; } diff --git a/app/dialog/export/exportsubtitlestab.cpp b/app/dialog/export/exportsubtitlestab.cpp index 5817e9958..6550d3408 100644 --- a/app/dialog/export/exportsubtitlestab.cpp +++ b/app/dialog/export/exportsubtitlestab.cpp @@ -2,69 +2,74 @@ #include -namespace olive { - -ExportSubtitlesTab::ExportSubtitlesTab(QWidget *parent) : - QWidget(parent) +namespace olive { - QVBoxLayout* outer_layout = new QVBoxLayout(this); - QGridLayout* layout = new QGridLayout(); - outer_layout->addLayout(layout); +ExportSubtitlesTab::ExportSubtitlesTab(QWidget *parent) + : QWidget(parent) +{ + QVBoxLayout *outer_layout = new QVBoxLayout(this); - int row = 0; + QGridLayout *layout = new QGridLayout(); + outer_layout->addLayout(layout); - sidecar_checkbox_ = new QCheckBox(tr("Export to sidecar file")); - layout->addWidget(sidecar_checkbox_, row, 0, 1, 2); + int row = 0; - row++; + sidecar_checkbox_ = new QCheckBox(tr("Export to sidecar file")); + layout->addWidget(sidecar_checkbox_, row, 0, 1, 2); - sidecar_format_label_ = new QLabel(tr("Sidecar Format:")); - sidecar_format_label_->setVisible(false); - layout->addWidget(sidecar_format_label_, row, 0); + row++; - sidecar_format_combobox_ = new ExportFormatComboBox(ExportFormatComboBox::kShowSubtitlesOnly); - sidecar_format_combobox_->setVisible(true); - layout->addWidget(sidecar_format_combobox_, row, 1); + sidecar_format_label_ = new QLabel(tr("Sidecar Format:")); + sidecar_format_label_->setVisible(false); + layout->addWidget(sidecar_format_label_, row, 0); - row++; + sidecar_format_combobox_ = + new ExportFormatComboBox(ExportFormatComboBox::kShowSubtitlesOnly); + sidecar_format_combobox_->setVisible(true); + layout->addWidget(sidecar_format_combobox_, row, 1); - layout->addWidget(new QLabel(tr("Codec:")), row, 0); + row++; - codec_combobox_ = new QComboBox(); - layout->addWidget(codec_combobox_, row, 1); + layout->addWidget(new QLabel(tr("Codec:")), row, 0); - outer_layout->addStretch(); + codec_combobox_ = new QComboBox(); + layout->addWidget(codec_combobox_, row, 1); - connect(sidecar_checkbox_, &QCheckBox::toggled, sidecar_format_label_, &QWidget::setVisible); - connect(sidecar_checkbox_, &QCheckBox::toggled, sidecar_format_combobox_, &QWidget::setVisible); + outer_layout->addStretch(); + + connect(sidecar_checkbox_, &QCheckBox::toggled, sidecar_format_label_, + &QWidget::setVisible); + connect(sidecar_checkbox_, &QCheckBox::toggled, sidecar_format_combobox_, + &QWidget::setVisible); } int ExportSubtitlesTab::SetFormat(ExportFormat::Format format) { - auto vcodecs = ExportFormat::GetVideoCodecs(format); - auto acodecs = ExportFormat::GetAudioCodecs(format); + auto vcodecs = ExportFormat::GetVideoCodecs(format); + auto acodecs = ExportFormat::GetAudioCodecs(format); - auto scodecs = ExportFormat::GetSubtitleCodecs(format); + auto scodecs = ExportFormat::GetSubtitleCodecs(format); - if (!scodecs.empty() && vcodecs.empty() && acodecs.empty()) { - // If format supports ONLY scodecs, default this to off and disable it - sidecar_checkbox_->setChecked(false); - sidecar_checkbox_->setEnabled(false); - } else { - // If format does not support scodecs, default this to checked and disable it - sidecar_checkbox_->setChecked(scodecs.empty()); - sidecar_checkbox_->setEnabled(!scodecs.empty()); - } + if (!scodecs.empty() && vcodecs.empty() && acodecs.empty()) { + // If format supports ONLY scodecs, default this to off and disable it + sidecar_checkbox_->setChecked(false); + sidecar_checkbox_->setEnabled(false); + } else { + // If format does not support scodecs, default this to checked and disable it + sidecar_checkbox_->setChecked(scodecs.empty()); + sidecar_checkbox_->setEnabled(!scodecs.empty()); + } - scodecs = ExportFormat::GetSubtitleCodecs(sidecar_format_combobox_->GetFormat()); + scodecs = + ExportFormat::GetSubtitleCodecs(sidecar_format_combobox_->GetFormat()); - codec_combobox_->clear(); - foreach (ExportCodec::Codec scodec, scodecs) { - codec_combobox_->addItem(ExportCodec::GetCodecName(scodec), scodec); - } + codec_combobox_->clear(); + foreach (ExportCodec::Codec scodec, scodecs) { + codec_combobox_->addItem(ExportCodec::GetCodecName(scodec), scodec); + } - return scodecs.size(); + return scodecs.size(); } } diff --git a/app/dialog/export/exportsubtitlestab.h b/app/dialog/export/exportsubtitlestab.h index dee62f93e..3f440be6c 100644 --- a/app/dialog/export/exportsubtitlestab.h +++ b/app/dialog/export/exportsubtitlestab.h @@ -29,40 +29,52 @@ #include "common/qtutils.h" #include "dialog/export/exportformatcombobox.h" -namespace olive { - -class ExportSubtitlesTab : public QWidget +namespace olive { - Q_OBJECT + +class ExportSubtitlesTab : public QWidget { + Q_OBJECT public: - ExportSubtitlesTab(QWidget *parent = nullptr); + ExportSubtitlesTab(QWidget *parent = nullptr); - bool GetSidecarEnabled() const { return sidecar_checkbox_->isChecked(); } - void SetSidecarEnabled(bool e) { sidecar_checkbox_->setEnabled(e); } + bool GetSidecarEnabled() const + { + return sidecar_checkbox_->isChecked(); + } + void SetSidecarEnabled(bool e) + { + sidecar_checkbox_->setEnabled(e); + } - ExportFormat::Format GetSidecarFormat() const { return sidecar_format_combobox_->GetFormat(); } - void SetSidecarFormat(ExportFormat::Format f) { sidecar_format_combobox_->SetFormat(f); } + ExportFormat::Format GetSidecarFormat() const + { + return sidecar_format_combobox_->GetFormat(); + } + void SetSidecarFormat(ExportFormat::Format f) + { + sidecar_format_combobox_->SetFormat(f); + } - int SetFormat(ExportFormat::Format format); + int SetFormat(ExportFormat::Format format); - ExportCodec::Codec GetSubtitleCodec() - { - return static_cast(codec_combobox_->currentData().toInt()); - } + ExportCodec::Codec GetSubtitleCodec() + { + return static_cast( + codec_combobox_->currentData().toInt()); + } - void SetSubtitleCodec(ExportCodec::Codec c) - { - QtUtils::SetComboBoxData(codec_combobox_, c); - } + void SetSubtitleCodec(ExportCodec::Codec c) + { + QtUtils::SetComboBoxData(codec_combobox_, c); + } private: - QCheckBox *sidecar_checkbox_; + QCheckBox *sidecar_checkbox_; - QLabel *sidecar_format_label_; - ExportFormatComboBox *sidecar_format_combobox_; - - QComboBox *codec_combobox_; + QLabel *sidecar_format_label_; + ExportFormatComboBox *sidecar_format_combobox_; + QComboBox *codec_combobox_; }; } diff --git a/app/dialog/export/exportvideotab.cpp b/app/dialog/export/exportvideotab.cpp index f0c130d02..271edf6e8 100644 --- a/app/dialog/export/exportvideotab.cpp +++ b/app/dialog/export/exportvideotab.cpp @@ -30,259 +30,272 @@ #include "exportadvancedvideodialog.h" #include "node/color/colormanager/colormanager.h" -namespace olive { - -ExportVideoTab::ExportVideoTab(ColorManager* color_manager, QWidget *parent) : - QWidget(parent), - color_manager_(color_manager), - threads_(0), - color_range_(VideoParams::kColorRangeDefault) +namespace olive { - QVBoxLayout* outer_layout = new QVBoxLayout(this); - outer_layout->addWidget(SetupResolutionSection()); +ExportVideoTab::ExportVideoTab(ColorManager *color_manager, QWidget *parent) + : QWidget(parent) + , color_manager_(color_manager) + , threads_(0) + , color_range_(VideoParams::kColorRangeDefault) +{ + QVBoxLayout *outer_layout = new QVBoxLayout(this); - outer_layout->addWidget(SetupCodecSection()); + outer_layout->addWidget(SetupResolutionSection()); - outer_layout->addWidget(SetupColorSection()); + outer_layout->addWidget(SetupCodecSection()); - outer_layout->addStretch(); + outer_layout->addWidget(SetupColorSection()); + + outer_layout->addStretch(); } int ExportVideoTab::SetFormat(ExportFormat::Format format) { - format_ = format; + format_ = format; - QList vcodecs = ExportFormat::GetVideoCodecs(format); - setEnabled(!vcodecs.isEmpty()); - codec_combobox()->clear(); - foreach (ExportCodec::Codec vcodec, vcodecs) { - codec_combobox()->addItem(ExportCodec::GetCodecName(vcodec), vcodec); - } - return vcodecs.size(); + QList vcodecs = ExportFormat::GetVideoCodecs(format); + setEnabled(!vcodecs.isEmpty()); + codec_combobox()->clear(); + foreach (ExportCodec::Codec vcodec, vcodecs) { + codec_combobox()->addItem(ExportCodec::GetCodecName(vcodec), vcodec); + } + return vcodecs.size(); } bool ExportVideoTab::IsImageSequenceSet() const { - ImageSection* img_section = dynamic_cast(codec_stack_->currentWidget()); + ImageSection *img_section = + dynamic_cast(codec_stack_->currentWidget()); - return (img_section && img_section->IsImageSequenceChecked()); + return (img_section && img_section->IsImageSequenceChecked()); } void ExportVideoTab::SetImageSequence(bool e) const { - if (ImageSection* img_section = dynamic_cast(codec_stack_->currentWidget())) { - img_section->SetImageSequenceChecked(e); - } + if (ImageSection *img_section = + dynamic_cast(codec_stack_->currentWidget())) { + img_section->SetImageSequenceChecked(e); + } } -QWidget* ExportVideoTab::SetupResolutionSection() +QWidget *ExportVideoTab::SetupResolutionSection() { - int row = 0; + int row = 0; - QGroupBox* resolution_group = new QGroupBox(); - resolution_group->setTitle(tr("General")); + QGroupBox *resolution_group = new QGroupBox(); + resolution_group->setTitle(tr("General")); - QGridLayout* layout = new QGridLayout(resolution_group); + QGridLayout *layout = new QGridLayout(resolution_group); - layout->addWidget(new QLabel(tr("Width:")), row, 0); + layout->addWidget(new QLabel(tr("Width:")), row, 0); - width_slider_ = new IntegerSlider(); - width_slider_->SetMinimum(1); - layout->addWidget(width_slider_, row, 1); + width_slider_ = new IntegerSlider(); + width_slider_->SetMinimum(1); + layout->addWidget(width_slider_, row, 1); - row++; + row++; - layout->addWidget(new QLabel(tr("Height:")), row, 0); + layout->addWidget(new QLabel(tr("Height:")), row, 0); - height_slider_ = new IntegerSlider(); - height_slider_->SetMinimum(1); - layout->addWidget(height_slider_, row, 1); + height_slider_ = new IntegerSlider(); + height_slider_->SetMinimum(1); + layout->addWidget(height_slider_, row, 1); - row++; + row++; - layout->addWidget(new QLabel(tr("Maintain Aspect Ratio:")), row, 0); + layout->addWidget(new QLabel(tr("Maintain Aspect Ratio:")), row, 0); - maintain_aspect_checkbox_ = new QCheckBox(); - maintain_aspect_checkbox_->setChecked(true); - layout->addWidget(maintain_aspect_checkbox_, row, 1); + maintain_aspect_checkbox_ = new QCheckBox(); + maintain_aspect_checkbox_->setChecked(true); + layout->addWidget(maintain_aspect_checkbox_, row, 1); - row++; + row++; - layout->addWidget(new QLabel(tr("Scaling Method:")), row, 0); + layout->addWidget(new QLabel(tr("Scaling Method:")), row, 0); - scaling_method_combobox_ = new QComboBox(); - scaling_method_combobox_->setEnabled(false); - scaling_method_combobox_->addItem(tr("Fit"), EncodingParams::kFit); - scaling_method_combobox_->addItem(tr("Stretch"), EncodingParams::kStretch); - scaling_method_combobox_->addItem(tr("Crop"), EncodingParams::kCrop); - layout->addWidget(scaling_method_combobox_, row, 1); + scaling_method_combobox_ = new QComboBox(); + scaling_method_combobox_->setEnabled(false); + scaling_method_combobox_->addItem(tr("Fit"), EncodingParams::kFit); + scaling_method_combobox_->addItem(tr("Stretch"), EncodingParams::kStretch); + scaling_method_combobox_->addItem(tr("Crop"), EncodingParams::kCrop); + layout->addWidget(scaling_method_combobox_, row, 1); - // Automatically enable/disable the scaling method depending on maintain aspect ratio - connect(maintain_aspect_checkbox_, &QCheckBox::toggled, this, &ExportVideoTab::MaintainAspectRatioChanged); + // Automatically enable/disable the scaling method depending on maintain aspect ratio + connect(maintain_aspect_checkbox_, &QCheckBox::toggled, this, + &ExportVideoTab::MaintainAspectRatioChanged); - row++; + row++; - layout->addWidget(new QLabel(tr("Frame Rate:")), row, 0); + layout->addWidget(new QLabel(tr("Frame Rate:")), row, 0); - frame_rate_combobox_ = new FrameRateComboBox(); - connect(frame_rate_combobox_, &FrameRateComboBox::FrameRateChanged, this, &ExportVideoTab::UpdateFrameRate); - layout->addWidget(frame_rate_combobox_, row, 1); + frame_rate_combobox_ = new FrameRateComboBox(); + connect(frame_rate_combobox_, &FrameRateComboBox::FrameRateChanged, this, + &ExportVideoTab::UpdateFrameRate); + layout->addWidget(frame_rate_combobox_, row, 1); - row++; + row++; - layout->addWidget(new QLabel(tr("Pixel Aspect Ratio:")), row, 0); + layout->addWidget(new QLabel(tr("Pixel Aspect Ratio:")), row, 0); - pixel_aspect_combobox_ = new PixelAspectRatioComboBox(); - layout->addWidget(pixel_aspect_combobox_, row, 1); + pixel_aspect_combobox_ = new PixelAspectRatioComboBox(); + layout->addWidget(pixel_aspect_combobox_, row, 1); - row++; + row++; - layout->addWidget(new QLabel(tr("Interlacing:")), row, 0); + layout->addWidget(new QLabel(tr("Interlacing:")), row, 0); - interlaced_combobox_ = new InterlacedComboBox(); - layout->addWidget(interlaced_combobox_, row, 1); + interlaced_combobox_ = new InterlacedComboBox(); + layout->addWidget(interlaced_combobox_, row, 1); - row++; + row++; - layout->addWidget(new QLabel(tr("Quality:")), row, 0); + layout->addWidget(new QLabel(tr("Quality:")), row, 0); - pixel_format_field_ = new PixelFormatComboBox(false); - layout->addWidget(pixel_format_field_, row, 1); + pixel_format_field_ = new PixelFormatComboBox(false); + layout->addWidget(pixel_format_field_, row, 1); - return resolution_group; + return resolution_group; } -QWidget* ExportVideoTab::SetupColorSection() +QWidget *ExportVideoTab::SetupColorSection() { - color_space_chooser_ = new ColorSpaceChooser(color_manager_, true, false); - connect(color_space_chooser_, &ColorSpaceChooser::InputColorSpaceChanged, this, &ExportVideoTab::ColorSpaceChanged); - return color_space_chooser_; + color_space_chooser_ = new ColorSpaceChooser(color_manager_, true, false); + connect(color_space_chooser_, &ColorSpaceChooser::InputColorSpaceChanged, + this, &ExportVideoTab::ColorSpaceChanged); + return color_space_chooser_; } QWidget *ExportVideoTab::SetupCodecSection() { - int row = 0; + int row = 0; - QGroupBox* codec_group = new QGroupBox(); - codec_group->setTitle(tr("Codec")); + QGroupBox *codec_group = new QGroupBox(); + codec_group->setTitle(tr("Codec")); - QGridLayout* codec_layout = new QGridLayout(codec_group); + QGridLayout *codec_layout = new QGridLayout(codec_group); - codec_layout->addWidget(new QLabel(tr("Codec:")), row, 0); + codec_layout->addWidget(new QLabel(tr("Codec:")), row, 0); - codec_combobox_ = new QComboBox(); - codec_layout->addWidget(codec_combobox_, row, 1); - connect(codec_combobox_, - static_cast(&QComboBox::currentIndexChanged), - this, - &ExportVideoTab::VideoCodecChanged); + codec_combobox_ = new QComboBox(); + codec_layout->addWidget(codec_combobox_, row, 1); + connect( + codec_combobox_, + static_cast(&QComboBox::currentIndexChanged), + this, &ExportVideoTab::VideoCodecChanged); - row++; + row++; - codec_stack_ = new CodecStack(); - codec_layout->addWidget(codec_stack_, row, 0, 1, 2); + codec_stack_ = new CodecStack(); + codec_layout->addWidget(codec_stack_, row, 0, 1, 2); - image_section_ = new ImageSection(); - connect(image_section_, &ImageSection::TimeChanged, this, &ExportVideoTab::TimeChanged); - codec_stack_->addWidget(image_section_); + image_section_ = new ImageSection(); + connect(image_section_, &ImageSection::TimeChanged, this, + &ExportVideoTab::TimeChanged); + codec_stack_->addWidget(image_section_); - h264_section_ = new H264Section(); - codec_stack_->addWidget(h264_section_); + h264_section_ = new H264Section(); + codec_stack_->addWidget(h264_section_); - h265_section_ = new H265Section(); - codec_stack_->addWidget(h265_section_); + h265_section_ = new H265Section(); + codec_stack_->addWidget(h265_section_); - av1_section_ = new AV1Section(); - codec_stack_->addWidget(av1_section_); + av1_section_ = new AV1Section(); + codec_stack_->addWidget(av1_section_); - cineform_section_ = new CineformSection(); - codec_stack_->addWidget(cineform_section_); + cineform_section_ = new CineformSection(); + codec_stack_->addWidget(cineform_section_); - row++; + row++; - QPushButton* advanced_btn = new QPushButton(tr("Advanced")); - connect(advanced_btn, &QPushButton::clicked, this, &ExportVideoTab::OpenAdvancedDialog); - codec_layout->addWidget(advanced_btn, row, 1); + QPushButton *advanced_btn = new QPushButton(tr("Advanced")); + connect(advanced_btn, &QPushButton::clicked, this, + &ExportVideoTab::OpenAdvancedDialog); + codec_layout->addWidget(advanced_btn, row, 1); - return codec_group; + return codec_group; } void ExportVideoTab::MaintainAspectRatioChanged(bool val) { - scaling_method_combobox_->setEnabled(!val); + scaling_method_combobox_->setEnabled(!val); } void ExportVideoTab::OpenAdvancedDialog() { - // Find export formats compatible with this encoder - QStringList pixel_formats = ExportFormat::GetPixelFormatsForCodec(format_, GetSelectedCodec()); + // Find export formats compatible with this encoder + QStringList pixel_formats = + ExportFormat::GetPixelFormatsForCodec(format_, GetSelectedCodec()); - ExportAdvancedVideoDialog d(pixel_formats, this); + ExportAdvancedVideoDialog d(pixel_formats, this); - d.set_threads(threads_); - d.set_pix_fmt(pix_fmt_); - d.set_yuv_range(color_range_); + d.set_threads(threads_); + d.set_pix_fmt(pix_fmt_); + d.set_yuv_range(color_range_); - if (d.exec() == QDialog::Accepted) { - threads_ = d.threads(); - pix_fmt_ = d.pix_fmt(); - color_range_ = d.yuv_range(); - } + if (d.exec() == QDialog::Accepted) { + threads_ = d.threads(); + pix_fmt_ = d.pix_fmt(); + color_range_ = d.yuv_range(); + } } void ExportVideoTab::UpdateFrameRate(rational r) { - // Convert frame rate to timebase - r.flip(); + // Convert frame rate to timebase + r.flip(); - for (int i=0; icount(); i++) { - ImageSection* img = dynamic_cast(codec_stack_->widget(i)); - if (img) { - img->SetTimebase(r); - } - } + for (int i = 0; i < codec_stack_->count(); i++) { + ImageSection *img = + dynamic_cast(codec_stack_->widget(i)); + if (img) { + img->SetTimebase(r); + } + } } void ExportVideoTab::VideoCodecChanged() { - ExportCodec::Codec codec = GetSelectedCodec(); + ExportCodec::Codec codec = GetSelectedCodec(); - switch (codec) { - case ExportCodec::kCodecH264: - case ExportCodec::kCodecH264rgb: - SetCodecSection(h264_section_); - break; - case ExportCodec::kCodecH265: - SetCodecSection(h265_section_); - break; - case ExportCodec::kCodecAV1: - SetCodecSection(av1_section_); - break; - case ExportCodec::kCodecCineform: - SetCodecSection(cineform_section_); - break; - default: - SetCodecSection(ExportCodec::IsCodecAStillImage(codec) ? image_section_ : nullptr); - } + switch (codec) { + case ExportCodec::kCodecH264: + case ExportCodec::kCodecH264rgb: + SetCodecSection(h264_section_); + break; + case ExportCodec::kCodecH265: + SetCodecSection(h265_section_); + break; + case ExportCodec::kCodecAV1: + SetCodecSection(av1_section_); + break; + case ExportCodec::kCodecCineform: + SetCodecSection(cineform_section_); + break; + default: + SetCodecSection( + ExportCodec::IsCodecAStillImage(codec) ? image_section_ : nullptr); + } - // Set default pixel format - QStringList pix_fmts = ExportFormat::GetPixelFormatsForCodec(format_, codec); - if (!pix_fmts.isEmpty()) { - pix_fmt_ = pix_fmts.first(); - } else { - pix_fmt_.clear(); - } + // Set default pixel format + QStringList pix_fmts = + ExportFormat::GetPixelFormatsForCodec(format_, codec); + if (!pix_fmts.isEmpty()) { + pix_fmt_ = pix_fmts.first(); + } else { + pix_fmt_.clear(); + } } void ExportVideoTab::SetTime(const rational &time) { - for (int i=0; icount(); i++) { - ImageSection* img = dynamic_cast(codec_stack_->widget(i)); - if (img) { - img->SetTime(time); - } - } + for (int i = 0; i < codec_stack_->count(); i++) { + ImageSection *img = + dynamic_cast(codec_stack_->widget(i)); + if (img) { + img->SetTime(time); + } + } } } diff --git a/app/dialog/export/exportvideotab.h b/app/dialog/export/exportvideotab.h index 4e59714be..d283f8e83 100644 --- a/app/dialog/export/exportvideotab.h +++ b/app/dialog/export/exportvideotab.h @@ -36,180 +36,192 @@ #include "widget/slider/integerslider.h" #include "widget/standardcombos/standardcombos.h" -namespace olive { - -class ExportVideoTab : public QWidget +namespace olive { - Q_OBJECT + +class ExportVideoTab : public QWidget { + Q_OBJECT public: - ExportVideoTab(ColorManager* color_manager, QWidget* parent = nullptr); + ExportVideoTab(ColorManager *color_manager, QWidget *parent = nullptr); - int SetFormat(ExportFormat::Format format); + int SetFormat(ExportFormat::Format format); - bool IsImageSequenceSet() const; - void SetImageSequence(bool e) const; + bool IsImageSequenceSet() const; + void SetImageSequence(bool e) const; - rational GetStillImageTime() const - { - return image_section_->GetTime(); - } + rational GetStillImageTime() const + { + return image_section_->GetTime(); + } - ExportCodec::Codec GetSelectedCodec() const - { - return static_cast(codec_combobox()->currentData().toInt()); - } + ExportCodec::Codec GetSelectedCodec() const + { + return static_cast( + codec_combobox()->currentData().toInt()); + } - void SetSelectedCodec(ExportCodec::Codec c) - { - QtUtils::SetComboBoxData(codec_combobox(), c); - } + void SetSelectedCodec(ExportCodec::Codec c) + { + QtUtils::SetComboBoxData(codec_combobox(), c); + } - QComboBox* codec_combobox() const - { - return codec_combobox_; - } + QComboBox *codec_combobox() const + { + return codec_combobox_; + } - IntegerSlider* width_slider() const - { - return width_slider_; - } + IntegerSlider *width_slider() const + { + return width_slider_; + } - IntegerSlider* height_slider() const - { - return height_slider_; - } + IntegerSlider *height_slider() const + { + return height_slider_; + } - QCheckBox* maintain_aspect_checkbox() const - { - return maintain_aspect_checkbox_; - } + QCheckBox *maintain_aspect_checkbox() const + { + return maintain_aspect_checkbox_; + } - QComboBox* scaling_method_combobox() const - { - return scaling_method_combobox_; - } + QComboBox *scaling_method_combobox() const + { + return scaling_method_combobox_; + } - rational GetSelectedFrameRate() const - { - return frame_rate_combobox_->GetFrameRate(); - } + rational GetSelectedFrameRate() const + { + return frame_rate_combobox_->GetFrameRate(); + } - void SetSelectedFrameRate(const rational& fr) - { - frame_rate_combobox_->SetFrameRate(fr); - UpdateFrameRate(fr); - } + void SetSelectedFrameRate(const rational &fr) + { + frame_rate_combobox_->SetFrameRate(fr); + UpdateFrameRate(fr); + } - QString CurrentOCIOColorSpace() - { - return color_space_chooser_->input(); - } + QString CurrentOCIOColorSpace() + { + return color_space_chooser_->input(); + } - void SetOCIOColorSpace(const QString &s) - { - color_space_chooser_->set_input(s); - } + void SetOCIOColorSpace(const QString &s) + { + color_space_chooser_->set_input(s); + } - CodecSection* GetCodecSection() const - { - return static_cast(codec_stack_->currentWidget()); - } + CodecSection *GetCodecSection() const + { + return static_cast(codec_stack_->currentWidget()); + } - void SetCodecSection(CodecSection* section) - { - if (section) { - codec_stack_->setVisible(true); - codec_stack_->setCurrentWidget(section); - } else { - codec_stack_->setVisible(false); - } - } + void SetCodecSection(CodecSection *section) + { + if (section) { + codec_stack_->setVisible(true); + codec_stack_->setCurrentWidget(section); + } else { + codec_stack_->setVisible(false); + } + } - InterlacedComboBox* interlaced_combobox() const - { - return interlaced_combobox_; - } + InterlacedComboBox *interlaced_combobox() const + { + return interlaced_combobox_; + } - PixelAspectRatioComboBox* pixel_aspect_combobox() const - { - return pixel_aspect_combobox_; - } + PixelAspectRatioComboBox *pixel_aspect_combobox() const + { + return pixel_aspect_combobox_; + } - PixelFormatComboBox* pixel_format_field() const - { - return pixel_format_field_; - } + PixelFormatComboBox *pixel_format_field() const + { + return pixel_format_field_; + } - const int& threads() const - { - return threads_; - } + const int &threads() const + { + return threads_; + } - void SetThreads(int t) - { - threads_ = t; - } + void SetThreads(int t) + { + threads_ = t; + } - const QString& pix_fmt() const { return pix_fmt_; } - void SetPixFmt(const QString &s) { pix_fmt_ = s; } + const QString &pix_fmt() const + { + return pix_fmt_; + } + void SetPixFmt(const QString &s) + { + pix_fmt_ = s; + } - VideoParams::ColorRange color_range() const { return color_range_; } - void SetColorRange(VideoParams::ColorRange c) { color_range_ = c; } + VideoParams::ColorRange color_range() const + { + return color_range_; + } + void SetColorRange(VideoParams::ColorRange c) + { + color_range_ = c; + } public slots: - void VideoCodecChanged(); + void VideoCodecChanged(); - void SetTime(const rational &time); + void SetTime(const rational &time); signals: - void ColorSpaceChanged(const QString& colorspace); + void ColorSpaceChanged(const QString &colorspace); - void ImageSequenceCheckBoxChanged(bool e); + void ImageSequenceCheckBoxChanged(bool e); - void TimeChanged(const rational &time); + void TimeChanged(const rational &time); private: - QWidget* SetupResolutionSection(); - QWidget* SetupColorSection(); - QWidget* SetupCodecSection(); + QWidget *SetupResolutionSection(); + QWidget *SetupColorSection(); + QWidget *SetupCodecSection(); - QComboBox* codec_combobox_; - FrameRateComboBox* frame_rate_combobox_; - QCheckBox* maintain_aspect_checkbox_; - QComboBox* scaling_method_combobox_; + QComboBox *codec_combobox_; + FrameRateComboBox *frame_rate_combobox_; + QCheckBox *maintain_aspect_checkbox_; + QComboBox *scaling_method_combobox_; - CodecStack* codec_stack_; - ImageSection* image_section_; - H264Section* h264_section_; - H264Section* h265_section_; - AV1Section* av1_section_; - CineformSection *cineform_section_; + CodecStack *codec_stack_; + ImageSection *image_section_; + H264Section *h264_section_; + H264Section *h265_section_; + AV1Section *av1_section_; + CineformSection *cineform_section_; - ColorSpaceChooser* color_space_chooser_; + ColorSpaceChooser *color_space_chooser_; - IntegerSlider* width_slider_; - IntegerSlider* height_slider_; + IntegerSlider *width_slider_; + IntegerSlider *height_slider_; - ColorManager* color_manager_; + ColorManager *color_manager_; - InterlacedComboBox* interlaced_combobox_; - PixelAspectRatioComboBox* pixel_aspect_combobox_; - PixelFormatComboBox* pixel_format_field_; + InterlacedComboBox *interlaced_combobox_; + PixelAspectRatioComboBox *pixel_aspect_combobox_; + PixelFormatComboBox *pixel_format_field_; - int threads_; + int threads_; - QString pix_fmt_; - VideoParams::ColorRange color_range_; + QString pix_fmt_; + VideoParams::ColorRange color_range_; - ExportFormat::Format format_; + ExportFormat::Format format_; private slots: - void MaintainAspectRatioChanged(bool val); + void MaintainAspectRatioChanged(bool val); - void OpenAdvancedDialog(); - - void UpdateFrameRate(rational r); + void OpenAdvancedDialog(); + void UpdateFrameRate(rational r); }; } diff --git a/app/dialog/footageproperties/footageproperties.cpp b/app/dialog/footageproperties/footageproperties.cpp index a243671d8..25cd73d56 100644 --- a/app/dialog/footageproperties/footageproperties.cpp +++ b/app/dialog/footageproperties/footageproperties.cpp @@ -36,241 +36,246 @@ #include "streamproperties/audiostreamproperties.h" #include "streamproperties/videostreamproperties.h" -namespace olive { - -FootagePropertiesDialog::FootagePropertiesDialog(QWidget *parent, Footage *footage) : - QDialog(parent), - footage_(footage) +namespace olive { - QGridLayout* layout = new QGridLayout(this); - setWindowTitle(tr("\"%1\" Properties").arg(footage_->GetLabelOrName())); - setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); +FootagePropertiesDialog::FootagePropertiesDialog(QWidget *parent, + Footage *footage) + : QDialog(parent) + , footage_(footage) +{ + QGridLayout *layout = new QGridLayout(this); - int row = 0; + setWindowTitle(tr("\"%1\" Properties").arg(footage_->GetLabelOrName())); + setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); - layout->addWidget(new QLabel(tr("Name:")), row, 0); + int row = 0; - footage_name_field_ = new QLineEdit(footage_->GetLabel()); - layout->addWidget(footage_name_field_, row, 1); - row++; + layout->addWidget(new QLabel(tr("Name:")), row, 0); - layout->addWidget(new QLabel(tr("Tracks:")), row, 0, 1, 2); - row++; + footage_name_field_ = new QLineEdit(footage_->GetLabel()); + layout->addWidget(footage_name_field_, row, 1); + row++; - track_list = new QListWidget(); - layout->addWidget(track_list, row, 0, 1, 2); + layout->addWidget(new QLabel(tr("Tracks:")), row, 0, 1, 2); + row++; - row++; + track_list = new QListWidget(); + layout->addWidget(track_list, row, 0, 1, 2); - stacked_widget_ = new QStackedWidget(); - layout->addWidget(stacked_widget_, row, 0, 1, 2); + row++; - int first_usable_stream = -1; + stacked_widget_ = new QStackedWidget(); + layout->addWidget(stacked_widget_, row, 0, 1, 2); - for (int i=0; iGetTotalStreamCount(); i++) { - Track::Reference reference = footage_->GetReferenceFromRealIndex(i); + int first_usable_stream = -1; - QString description; - bool is_enabled = false; + for (int i = 0; i < footage_->GetTotalStreamCount(); i++) { + Track::Reference reference = footage_->GetReferenceFromRealIndex(i); - switch (reference.type()) { - case Track::kVideo: - { - stacked_widget_->addWidget(new VideoStreamProperties(footage_, reference.index())); + QString description; + bool is_enabled = false; - VideoParams vp = footage_->GetVideoParams(reference.index()); - is_enabled = vp.enabled(); - description = Footage::DescribeVideoStream(vp); - break; - } - case Track::kAudio: - { - stacked_widget_->addWidget(new AudioStreamProperties(footage_, reference.index())); + switch (reference.type()) { + case Track::kVideo: { + stacked_widget_->addWidget( + new VideoStreamProperties(footage_, reference.index())); - AudioParams ap = footage_->GetAudioParams(reference.index()); - is_enabled = ap.enabled(); - description = Footage::DescribeAudioStream(ap); - break; - } - case Track::kSubtitle: - { - SubtitleParams sp = footage_->GetSubtitleParams(reference.index()); - is_enabled = sp.enabled(); + VideoParams vp = footage_->GetVideoParams(reference.index()); + is_enabled = vp.enabled(); + description = Footage::DescribeVideoStream(vp); + break; + } + case Track::kAudio: { + stacked_widget_->addWidget( + new AudioStreamProperties(footage_, reference.index())); - // FIXME: Language? - description = tr("Subtitles"); - break; - } - default: - stacked_widget_->addWidget(new StreamProperties()); - description = tr("Unknown"); - break; - } + AudioParams ap = footage_->GetAudioParams(reference.index()); + is_enabled = ap.enabled(); + description = Footage::DescribeAudioStream(ap); + break; + } + case Track::kSubtitle: { + SubtitleParams sp = footage_->GetSubtitleParams(reference.index()); + is_enabled = sp.enabled(); - QListWidgetItem* item = new QListWidgetItem(description, track_list); - item->setFlags(item->flags() | Qt::ItemIsUserCheckable); - item->setCheckState(is_enabled ? Qt::Checked : Qt::Unchecked); - track_list->addItem(item); + // FIXME: Language? + description = tr("Subtitles"); + break; + } + default: + stacked_widget_->addWidget(new StreamProperties()); + description = tr("Unknown"); + break; + } - if (first_usable_stream == -1 - && (reference.type() == Track::kVideo - || reference.type() == Track::kAudio - || reference.type() == Track::kSubtitle)) { - first_usable_stream = i; - } - } + QListWidgetItem *item = new QListWidgetItem(description, track_list); + item->setFlags(item->flags() | Qt::ItemIsUserCheckable); + item->setCheckState(is_enabled ? Qt::Checked : Qt::Unchecked); + track_list->addItem(item); - row++; + if (first_usable_stream == -1 && + (reference.type() == Track::kVideo || + reference.type() == Track::kAudio || + reference.type() == Track::kSubtitle)) { + first_usable_stream = i; + } + } - QDialogButtonBox* buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); - buttons->setCenterButtons(true); - layout->addWidget(buttons, row, 0, 1, 2); + row++; - connect(buttons, &QDialogButtonBox::accepted, this, &QDialog::accept); - connect(buttons, &QDialogButtonBox::rejected, this, &QDialog::reject); + QDialogButtonBox *buttons = + new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); + buttons->setCenterButtons(true); + layout->addWidget(buttons, row, 0, 1, 2); - connect(track_list, &QListWidget::currentRowChanged, stacked_widget_, &QStackedWidget::setCurrentIndex); + connect(buttons, &QDialogButtonBox::accepted, this, &QDialog::accept); + connect(buttons, &QDialogButtonBox::rejected, this, &QDialog::reject); - // Auto-select first item that actually has properties - if (first_usable_stream >= 0) { - track_list->setCurrentRow(first_usable_stream); - } - track_list->setFocus(); + connect(track_list, &QListWidget::currentRowChanged, stacked_widget_, + &QStackedWidget::setCurrentIndex); + + // Auto-select first item that actually has properties + if (first_usable_stream >= 0) { + track_list->setCurrentRow(first_usable_stream); + } + track_list->setFocus(); } void FootagePropertiesDialog::accept() { - // Perform sanity check on all pages - for (int i=0;icount();i++) { - if (!static_cast(stacked_widget_->widget(i))->SanityCheck()) { - // Switch to the failed panel in question - stacked_widget_->setCurrentIndex(i); + // Perform sanity check on all pages + for (int i = 0; i < stacked_widget_->count(); i++) { + if (!static_cast(stacked_widget_->widget(i)) + ->SanityCheck()) { + // Switch to the failed panel in question + stacked_widget_->setCurrentIndex(i); - // Do nothing (it's up to the property panel itself to throw the error message) - return; - } - } + // Do nothing (it's up to the property panel itself to throw the error message) + return; + } + } - MultiUndoCommand* command = new MultiUndoCommand(); + MultiUndoCommand *command = new MultiUndoCommand(); - if (footage_->GetLabel() != footage_name_field_->text()) { - NodeRenameCommand *nrc = new NodeRenameCommand(); - nrc->AddNode(footage_, footage_name_field_->text()); - command->add_child(nrc); - } + if (footage_->GetLabel() != footage_name_field_->text()) { + NodeRenameCommand *nrc = new NodeRenameCommand(); + nrc->AddNode(footage_, footage_name_field_->text()); + command->add_child(nrc); + } - for (int i=0; iGetTotalStreamCount(); i++) { - Track::Reference reference = footage_->GetReferenceFromRealIndex(i); - bool new_stream_enabled = (track_list->item(i)->checkState() == Qt::Checked); - bool old_stream_enabled = new_stream_enabled; + for (int i = 0; i < footage_->GetTotalStreamCount(); i++) { + Track::Reference reference = footage_->GetReferenceFromRealIndex(i); + bool new_stream_enabled = + (track_list->item(i)->checkState() == Qt::Checked); + bool old_stream_enabled = new_stream_enabled; - switch (reference.type()) { - case Track::kVideo: - old_stream_enabled = footage_->GetVideoParams(reference.index()).enabled(); - break; - case Track::kAudio: - old_stream_enabled = footage_->GetAudioParams(reference.index()).enabled(); - break; - case Track::kSubtitle: - old_stream_enabled = footage_->GetSubtitleParams(reference.index()).enabled(); - break; - case Track::kNone: - case Track::kCount: - break; - } + switch (reference.type()) { + case Track::kVideo: + old_stream_enabled = + footage_->GetVideoParams(reference.index()).enabled(); + break; + case Track::kAudio: + old_stream_enabled = + footage_->GetAudioParams(reference.index()).enabled(); + break; + case Track::kSubtitle: + old_stream_enabled = + footage_->GetSubtitleParams(reference.index()).enabled(); + break; + case Track::kNone: + case Track::kCount: + break; + } - if (old_stream_enabled != new_stream_enabled) { - command->add_child(new StreamEnableChangeCommand(footage_, - reference.type(), - reference.index(), - new_stream_enabled)); - } - } + if (old_stream_enabled != new_stream_enabled) { + command->add_child(new StreamEnableChangeCommand( + footage_, reference.type(), reference.index(), + new_stream_enabled)); + } + } - for (int i=0;icount();i++) { - static_cast(stacked_widget_->widget(i))->Accept(command); - } + for (int i = 0; i < stacked_widget_->count(); i++) { + static_cast(stacked_widget_->widget(i)) + ->Accept(command); + } - Core::instance()->undo_stack()->push(command, tr("Set Footage \"%1\" Properties").arg(footage_->GetLabel())); + Core::instance()->undo_stack()->push( + command, tr("Set Footage \"%1\" Properties").arg(footage_->GetLabel())); - QDialog::accept(); + QDialog::accept(); } -FootagePropertiesDialog::StreamEnableChangeCommand::StreamEnableChangeCommand(Footage *footage, Track::Type type, int index_in_type, bool enabled) : - footage_(footage), - type_(type), - index_(index_in_type), - new_enabled_(enabled) +FootagePropertiesDialog::StreamEnableChangeCommand::StreamEnableChangeCommand( + Footage *footage, Track::Type type, int index_in_type, bool enabled) + : footage_(footage) + , type_(type) + , index_(index_in_type) + , new_enabled_(enabled) { } -Project *FootagePropertiesDialog::StreamEnableChangeCommand::GetRelevantProject() const +Project * +FootagePropertiesDialog::StreamEnableChangeCommand::GetRelevantProject() const { - return footage_->project(); + return footage_->project(); } void FootagePropertiesDialog::StreamEnableChangeCommand::redo() { - switch (type_) { - case Track::kVideo: - { - VideoParams vp = footage_->GetVideoParams(index_); - old_enabled_ = vp.enabled(); - vp.set_enabled(new_enabled_); - footage_->SetVideoParams(vp, index_); - break; - } - case Track::kAudio: - { - AudioParams ap = footage_->GetAudioParams(index_); - old_enabled_ = ap.enabled(); - ap.set_enabled(new_enabled_); - footage_->SetAudioParams(ap, index_); - break; - } - case Track::kSubtitle: - { - SubtitleParams sp = footage_->GetSubtitleParams(index_); - old_enabled_ = sp.enabled(); - sp.set_enabled(new_enabled_); - footage_->SetSubtitleParams(sp, index_); - break; - } - case Track::kNone: - case Track::kCount: - break; - } + switch (type_) { + case Track::kVideo: { + VideoParams vp = footage_->GetVideoParams(index_); + old_enabled_ = vp.enabled(); + vp.set_enabled(new_enabled_); + footage_->SetVideoParams(vp, index_); + break; + } + case Track::kAudio: { + AudioParams ap = footage_->GetAudioParams(index_); + old_enabled_ = ap.enabled(); + ap.set_enabled(new_enabled_); + footage_->SetAudioParams(ap, index_); + break; + } + case Track::kSubtitle: { + SubtitleParams sp = footage_->GetSubtitleParams(index_); + old_enabled_ = sp.enabled(); + sp.set_enabled(new_enabled_); + footage_->SetSubtitleParams(sp, index_); + break; + } + case Track::kNone: + case Track::kCount: + break; + } } void FootagePropertiesDialog::StreamEnableChangeCommand::undo() { - switch (type_) { - case Track::kVideo: - { - VideoParams vp = footage_->GetVideoParams(index_); - vp.set_enabled(old_enabled_); - footage_->SetVideoParams(vp, index_); - break; - } - case Track::kAudio: - { - AudioParams ap = footage_->GetAudioParams(index_); - ap.set_enabled(old_enabled_); - footage_->SetAudioParams(ap, index_); - break; - } - case Track::kSubtitle: - { - SubtitleParams sp = footage_->GetSubtitleParams(index_); - sp.set_enabled(old_enabled_); - footage_->SetSubtitleParams(sp, index_); - break; - } - case Track::kNone: - case Track::kCount: - break; - } + switch (type_) { + case Track::kVideo: { + VideoParams vp = footage_->GetVideoParams(index_); + vp.set_enabled(old_enabled_); + footage_->SetVideoParams(vp, index_); + break; + } + case Track::kAudio: { + AudioParams ap = footage_->GetAudioParams(index_); + ap.set_enabled(old_enabled_); + footage_->SetAudioParams(ap, index_); + break; + } + case Track::kSubtitle: { + SubtitleParams sp = footage_->GetSubtitleParams(index_); + sp.set_enabled(old_enabled_); + footage_->SetSubtitleParams(sp, index_); + break; + } + case Track::kNone: + case Track::kCount: + break; + } } } diff --git a/app/dialog/footageproperties/footageproperties.h b/app/dialog/footageproperties/footageproperties.h index e25898381..66a693d18 100644 --- a/app/dialog/footageproperties/footageproperties.h +++ b/app/dialog/footageproperties/footageproperties.h @@ -32,7 +32,8 @@ #include "node/project/footage/footage.h" #include "undo/undocommand.h" -namespace olive { +namespace olive +{ /** * @brief The MediaPropertiesDialog class @@ -41,9 +42,9 @@ namespace olive { * a valid Media object. */ class FootagePropertiesDialog : public QDialog { - Q_OBJECT + Q_OBJECT public: - /** + /** * @brief MediaPropertiesDialog Constructor * * @param parent @@ -54,61 +55,59 @@ public: * * Media object to set properties for. */ - FootagePropertiesDialog(QWidget *parent, Footage* footage); + FootagePropertiesDialog(QWidget *parent, Footage *footage); + private: - class StreamEnableChangeCommand : public UndoCommand { - public: - StreamEnableChangeCommand(Footage *footage, - Track::Type type, - int index_in_type, - bool enabled); + class StreamEnableChangeCommand : public UndoCommand { + public: + StreamEnableChangeCommand(Footage *footage, Track::Type type, + int index_in_type, bool enabled); - virtual Project* GetRelevantProject() const override; + virtual Project *GetRelevantProject() const override; - protected: - virtual void redo() override; - virtual void undo() override; + protected: + virtual void redo() override; + virtual void undo() override; - private: - Footage *footage_; - Track::Type type_; - int index_; + private: + Footage *footage_; + Track::Type type_; + int index_; - bool old_enabled_; - bool new_enabled_; - }; + bool old_enabled_; + bool new_enabled_; + }; - /** + /** * @brief Stack of widgets that changes based on whether the stream is a video or audio stream */ - QStackedWidget* stacked_widget_; + QStackedWidget *stacked_widget_; - /** + /** * @brief Media name text field */ - QLineEdit* footage_name_field_; + QLineEdit *footage_name_field_; - /** + /** * @brief Internal pointer to Media object (set in constructor) */ - Footage* footage_; + Footage *footage_; - /** + /** * @brief A list widget for listing the tracks in Media */ - QListWidget* track_list; + QListWidget *track_list; - /** + /** * @brief Frame rate to conform to */ - QDoubleSpinBox* conform_fr; + QDoubleSpinBox *conform_fr; private slots: - /** + /** * @brief Overridden accept function for saving the properties back to the Media class */ - void accept(); - + void accept(); }; } diff --git a/app/dialog/footageproperties/streamproperties/audiostreamproperties.cpp b/app/dialog/footageproperties/streamproperties/audiostreamproperties.cpp index 0359e7577..946f2f673 100644 --- a/app/dialog/footageproperties/streamproperties/audiostreamproperties.cpp +++ b/app/dialog/footageproperties/streamproperties/audiostreamproperties.cpp @@ -20,18 +20,19 @@ #include "audiostreamproperties.h" -namespace olive { +namespace olive +{ -AudioStreamProperties::AudioStreamProperties(Footage *footage, int audio_index) : - footage_(footage), - audio_index_(audio_index) +AudioStreamProperties::AudioStreamProperties(Footage *footage, int audio_index) + : footage_(footage) + , audio_index_(audio_index) { } -void AudioStreamProperties::Accept(MultiUndoCommand*) +void AudioStreamProperties::Accept(MultiUndoCommand *) { - Q_UNUSED(footage_) - Q_UNUSED(audio_index_) + Q_UNUSED(footage_) + Q_UNUSED(audio_index_) } } diff --git a/app/dialog/footageproperties/streamproperties/audiostreamproperties.h b/app/dialog/footageproperties/streamproperties/audiostreamproperties.h index 058ff2bfc..8abf5f1bb 100644 --- a/app/dialog/footageproperties/streamproperties/audiostreamproperties.h +++ b/app/dialog/footageproperties/streamproperties/audiostreamproperties.h @@ -24,20 +24,19 @@ #include "node/project/footage/footage.h" #include "streamproperties.h" -namespace olive { - -class AudioStreamProperties : public StreamProperties +namespace olive { -public: - AudioStreamProperties(Footage *footage, int audio_index); - virtual void Accept(MultiUndoCommand* parent) override; +class AudioStreamProperties : public StreamProperties { +public: + AudioStreamProperties(Footage *footage, int audio_index); + + virtual void Accept(MultiUndoCommand *parent) override; private: - Footage *footage_; - - int audio_index_; + Footage *footage_; + int audio_index_; }; } diff --git a/app/dialog/footageproperties/streamproperties/streamproperties.cpp b/app/dialog/footageproperties/streamproperties/streamproperties.cpp index 96f3bbd5a..6c7b2bc31 100644 --- a/app/dialog/footageproperties/streamproperties/streamproperties.cpp +++ b/app/dialog/footageproperties/streamproperties/streamproperties.cpp @@ -20,10 +20,11 @@ #include "streamproperties.h" -namespace olive { +namespace olive +{ -StreamProperties::StreamProperties(QWidget *parent) : - QWidget(parent) +StreamProperties::StreamProperties(QWidget *parent) + : QWidget(parent) { } diff --git a/app/dialog/footageproperties/streamproperties/streamproperties.h b/app/dialog/footageproperties/streamproperties/streamproperties.h index c8457216b..6bc350318 100644 --- a/app/dialog/footageproperties/streamproperties/streamproperties.h +++ b/app/dialog/footageproperties/streamproperties/streamproperties.h @@ -26,17 +26,21 @@ #include "common/define.h" #include "undo/undocommand.h" -namespace olive { - -class StreamProperties : public QWidget +namespace olive { + +class StreamProperties : public QWidget { public: - StreamProperties(QWidget* parent = nullptr); + StreamProperties(QWidget *parent = nullptr); - virtual void Accept(MultiUndoCommand*){} - - virtual bool SanityCheck(){return true;} + virtual void Accept(MultiUndoCommand *) + { + } + virtual bool SanityCheck() + { + return true; + } }; } diff --git a/app/dialog/footageproperties/streamproperties/videostreamproperties.cpp b/app/dialog/footageproperties/streamproperties/videostreamproperties.cpp index e2b223621..785d5d30c 100644 --- a/app/dialog/footageproperties/streamproperties/videostreamproperties.cpp +++ b/app/dialog/footageproperties/streamproperties/videostreamproperties.cpp @@ -30,259 +30,272 @@ #include "core.h" #include "undo/undostack.h" -namespace olive { - -VideoStreamProperties::VideoStreamProperties(Footage *footage, int video_index) : - footage_(footage), - video_index_(video_index), - video_premultiply_alpha_(nullptr) +namespace olive { - QGridLayout* video_layout = new QGridLayout(this); - video_layout->setContentsMargins(0, 0, 0, 0); - int row = 0; +VideoStreamProperties::VideoStreamProperties(Footage *footage, int video_index) + : footage_(footage) + , video_index_(video_index) + , video_premultiply_alpha_(nullptr) +{ + QGridLayout *video_layout = new QGridLayout(this); + video_layout->setContentsMargins(0, 0, 0, 0); - video_layout->addWidget(new QLabel(tr("Pixel Aspect:")), row, 0); + int row = 0; - VideoParams vp = footage_->GetVideoParams(video_index_); + video_layout->addWidget(new QLabel(tr("Pixel Aspect:")), row, 0); - pixel_aspect_combo_ = new PixelAspectRatioComboBox(); - pixel_aspect_combo_->SetPixelAspectRatio(vp.pixel_aspect_ratio()); - video_layout->addWidget(pixel_aspect_combo_, row, 1); + VideoParams vp = footage_->GetVideoParams(video_index_); - row++; + pixel_aspect_combo_ = new PixelAspectRatioComboBox(); + pixel_aspect_combo_->SetPixelAspectRatio(vp.pixel_aspect_ratio()); + video_layout->addWidget(pixel_aspect_combo_, row, 1); - video_layout->addWidget(new QLabel(tr("Interlacing:")), row, 0); + row++; - video_interlace_combo_ = new InterlacedComboBox(); - video_interlace_combo_->SetInterlaceMode(vp.interlacing()); + video_layout->addWidget(new QLabel(tr("Interlacing:")), row, 0); - video_layout->addWidget(video_interlace_combo_, row, 1); + video_interlace_combo_ = new InterlacedComboBox(); + video_interlace_combo_->SetInterlaceMode(vp.interlacing()); - row++; + video_layout->addWidget(video_interlace_combo_, row, 1); - video_layout->addWidget(new QLabel(tr("Color Space:")), row, 0); + row++; - video_color_space_ = new QComboBox(); - OCIO::ConstConfigRcPtr config = footage_->project()->color_manager()->GetConfig(); - int number_of_colorspaces = config->getNumColorSpaces(); + video_layout->addWidget(new QLabel(tr("Color Space:")), row, 0); - video_color_space_->addItem(tr("Default (%1)").arg(footage_->project()->color_manager()->GetDefaultInputColorSpace())); + video_color_space_ = new QComboBox(); + OCIO::ConstConfigRcPtr config = + footage_->project()->color_manager()->GetConfig(); + int number_of_colorspaces = config->getNumColorSpaces(); - for (int i=0;igetColorSpaceNameByIndex(i); + video_color_space_->addItem(tr("Default (%1)") + .arg(footage_->project() + ->color_manager() + ->GetDefaultInputColorSpace())); - video_color_space_->addItem(colorspace); - } + for (int i = 0; i < number_of_colorspaces; i++) { + QString colorspace = config->getColorSpaceNameByIndex(i); - video_color_space_->setCurrentText(vp.colorspace()); + video_color_space_->addItem(colorspace); + } - video_layout->addWidget(video_color_space_, row, 1); + video_color_space_->setCurrentText(vp.colorspace()); - row++; + video_layout->addWidget(video_color_space_, row, 1); - video_layout->addWidget(new QLabel(tr("Color Range:")), row, 0); + row++; - color_range_combo_ = new QComboBox(); - color_range_combo_->addItem(tr("Limited (16-235)"), VideoParams::kColorRangeLimited); - color_range_combo_->addItem(tr("Full (0-255)"), VideoParams::kColorRangeFull); - color_range_combo_->setCurrentIndex(vp.color_range()); + video_layout->addWidget(new QLabel(tr("Color Range:")), row, 0); - video_layout->addWidget(color_range_combo_, row, 1); + color_range_combo_ = new QComboBox(); + color_range_combo_->addItem(tr("Limited (16-235)"), + VideoParams::kColorRangeLimited); + color_range_combo_->addItem(tr("Full (0-255)"), + VideoParams::kColorRangeFull); + color_range_combo_->setCurrentIndex(vp.color_range()); - if (vp.channel_count() == VideoParams::kRGBAChannelCount) { - row++; + video_layout->addWidget(color_range_combo_, row, 1); - video_premultiply_alpha_ = new QCheckBox(tr("Premultiplied Alpha")); - video_premultiply_alpha_->setChecked(vp.premultiplied_alpha()); - video_layout->addWidget(video_premultiply_alpha_, row, 0, 1, 2); - } + if (vp.channel_count() == VideoParams::kRGBAChannelCount) { + row++; - row++; + video_premultiply_alpha_ = new QCheckBox(tr("Premultiplied Alpha")); + video_premultiply_alpha_->setChecked(vp.premultiplied_alpha()); + video_layout->addWidget(video_premultiply_alpha_, row, 0, 1, 2); + } - if (vp.video_type() == VideoParams::kVideoTypeImageSequence) { - QGroupBox* imgseq_group = new QGroupBox(tr("Image Sequence")); - QGridLayout* imgseq_layout = new QGridLayout(imgseq_group); + row++; - int imgseq_row = 0; + if (vp.video_type() == VideoParams::kVideoTypeImageSequence) { + QGroupBox *imgseq_group = new QGroupBox(tr("Image Sequence")); + QGridLayout *imgseq_layout = new QGridLayout(imgseq_group); - imgseq_layout->addWidget(new QLabel(tr("Start Index:")), imgseq_row, 0); + int imgseq_row = 0; - imgseq_start_time_ = new IntegerSlider(); - imgseq_start_time_->SetMinimum(0); - imgseq_start_time_->SetValue(vp.start_time()); - imgseq_layout->addWidget(imgseq_start_time_, imgseq_row, 1); + imgseq_layout->addWidget(new QLabel(tr("Start Index:")), imgseq_row, 0); - imgseq_row++; + imgseq_start_time_ = new IntegerSlider(); + imgseq_start_time_->SetMinimum(0); + imgseq_start_time_->SetValue(vp.start_time()); + imgseq_layout->addWidget(imgseq_start_time_, imgseq_row, 1); - imgseq_layout->addWidget(new QLabel(tr("End Index:")), imgseq_row, 0); + imgseq_row++; - imgseq_end_time_ = new IntegerSlider(); - imgseq_end_time_->SetMinimum(0); - imgseq_end_time_->SetValue(vp.start_time() + vp.duration() - 1); - imgseq_layout->addWidget(imgseq_end_time_, imgseq_row, 1); + imgseq_layout->addWidget(new QLabel(tr("End Index:")), imgseq_row, 0); - imgseq_row++; + imgseq_end_time_ = new IntegerSlider(); + imgseq_end_time_->SetMinimum(0); + imgseq_end_time_->SetValue(vp.start_time() + vp.duration() - 1); + imgseq_layout->addWidget(imgseq_end_time_, imgseq_row, 1); - imgseq_layout->addWidget(new QLabel(tr("Frame Rate:")), imgseq_row, 0); + imgseq_row++; - imgseq_frame_rate_ = new FrameRateComboBox(); - imgseq_frame_rate_->SetFrameRate(vp.frame_rate()); - imgseq_layout->addWidget(imgseq_frame_rate_, imgseq_row, 1); + imgseq_layout->addWidget(new QLabel(tr("Frame Rate:")), imgseq_row, 0); - video_layout->addWidget(imgseq_group, row, 0, 1, 2); - } + imgseq_frame_rate_ = new FrameRateComboBox(); + imgseq_frame_rate_->SetFrameRate(vp.frame_rate()); + imgseq_layout->addWidget(imgseq_frame_rate_, imgseq_row, 1); + + video_layout->addWidget(imgseq_group, row, 0, 1, 2); + } } void VideoStreamProperties::Accept(MultiUndoCommand *parent) { - QString set_colorspace; + QString set_colorspace; - if (video_color_space_->currentIndex() > 0) { - set_colorspace = video_color_space_->currentText(); - } + if (video_color_space_->currentIndex() > 0) { + set_colorspace = video_color_space_->currentText(); + } - VideoParams vp = footage_->GetVideoParams(video_index_); + VideoParams vp = footage_->GetVideoParams(video_index_); - if ((video_premultiply_alpha_ && video_premultiply_alpha_->isChecked() != vp.premultiplied_alpha()) - || set_colorspace != vp.colorspace() - || static_cast(video_interlace_combo_->currentIndex()) != vp.interlacing() - || pixel_aspect_combo_->GetPixelAspectRatio() != vp.pixel_aspect_ratio() - || color_range_combo_->currentData().toInt() != vp.color_range()) { + if ((video_premultiply_alpha_ && + video_premultiply_alpha_->isChecked() != vp.premultiplied_alpha()) || + set_colorspace != vp.colorspace() || + static_cast( + video_interlace_combo_->currentIndex()) != vp.interlacing() || + pixel_aspect_combo_->GetPixelAspectRatio() != vp.pixel_aspect_ratio() || + color_range_combo_->currentData().toInt() != vp.color_range()) { + parent->add_child(new VideoStreamChangeCommand( + footage_, video_index_, + video_premultiply_alpha_ ? video_premultiply_alpha_->isChecked() : + vp.premultiplied_alpha(), + set_colorspace, + static_cast( + video_interlace_combo_->currentIndex()), + pixel_aspect_combo_->GetPixelAspectRatio(), + static_cast( + color_range_combo_->currentData().toInt()))); + } - parent->add_child(new VideoStreamChangeCommand(footage_, - video_index_, - video_premultiply_alpha_ ? video_premultiply_alpha_->isChecked() : vp.premultiplied_alpha(), - set_colorspace, - static_cast(video_interlace_combo_->currentIndex()), - pixel_aspect_combo_->GetPixelAspectRatio(), - static_cast(color_range_combo_->currentData().toInt()))); - } + if (vp.video_type() == VideoParams::kVideoTypeImageSequence) { + int64_t new_dur = + imgseq_end_time_->GetValue() - imgseq_start_time_->GetValue() + 1; - if (vp.video_type() == VideoParams::kVideoTypeImageSequence) { - int64_t new_dur = imgseq_end_time_->GetValue() - imgseq_start_time_->GetValue() + 1; - - if (vp.start_time() != imgseq_start_time_->GetValue() - || vp.duration() != new_dur - || vp.frame_rate() != imgseq_frame_rate_->GetFrameRate()) { - parent->add_child(new ImageSequenceChangeCommand(footage_, - video_index_, - imgseq_start_time_->GetValue(), - new_dur, - imgseq_frame_rate_->GetFrameRate())); - } - } + if (vp.start_time() != imgseq_start_time_->GetValue() || + vp.duration() != new_dur || + vp.frame_rate() != imgseq_frame_rate_->GetFrameRate()) { + parent->add_child(new ImageSequenceChangeCommand( + footage_, video_index_, imgseq_start_time_->GetValue(), new_dur, + imgseq_frame_rate_->GetFrameRate())); + } + } } bool VideoStreamProperties::SanityCheck() { - if (footage_->GetVideoParams(video_index_).video_type() == VideoParams::kVideoTypeImageSequence) { - if (imgseq_start_time_->GetValue() >= imgseq_end_time_->GetValue()) { - QMessageBox::critical(this, - tr("Invalid Configuration"), - tr("Image sequence end index must be a value higher than the start index."), - QMessageBox::Ok); - return false; - } - } + if (footage_->GetVideoParams(video_index_).video_type() == + VideoParams::kVideoTypeImageSequence) { + if (imgseq_start_time_->GetValue() >= imgseq_end_time_->GetValue()) { + QMessageBox::critical( + this, tr("Invalid Configuration"), + tr("Image sequence end index must be a value higher than the start index."), + QMessageBox::Ok); + return false; + } + } - return true; + return true; } -VideoStreamProperties::VideoStreamChangeCommand::VideoStreamChangeCommand(Footage *footage, - int video_index, - bool premultiplied, - QString colorspace, - VideoParams::Interlacing interlacing, - const rational &pixel_ar, VideoParams::ColorRange range) : - footage_(footage), - video_index_(video_index), - new_premultiplied_(premultiplied), - new_colorspace_(colorspace), - new_interlacing_(interlacing), - new_pixel_ar_(pixel_ar), - new_range_(range) +VideoStreamProperties::VideoStreamChangeCommand::VideoStreamChangeCommand( + Footage *footage, int video_index, bool premultiplied, QString colorspace, + VideoParams::Interlacing interlacing, const rational &pixel_ar, + VideoParams::ColorRange range) + : footage_(footage) + , video_index_(video_index) + , new_premultiplied_(premultiplied) + , new_colorspace_(colorspace) + , new_interlacing_(interlacing) + , new_pixel_ar_(pixel_ar) + , new_range_(range) { } -Project *VideoStreamProperties::VideoStreamChangeCommand::GetRelevantProject() const +Project * +VideoStreamProperties::VideoStreamChangeCommand::GetRelevantProject() const { - return footage_->project(); + return footage_->project(); } void VideoStreamProperties::VideoStreamChangeCommand::redo() { - VideoParams vp = footage_->GetVideoParams(video_index_); + VideoParams vp = footage_->GetVideoParams(video_index_); - old_premultiplied_ = vp.premultiplied_alpha(); - old_colorspace_ = vp.colorspace(); - old_interlacing_ = vp.interlacing(); - old_pixel_ar_ = vp.pixel_aspect_ratio(); - old_range_ = vp.color_range(); + old_premultiplied_ = vp.premultiplied_alpha(); + old_colorspace_ = vp.colorspace(); + old_interlacing_ = vp.interlacing(); + old_pixel_ar_ = vp.pixel_aspect_ratio(); + old_range_ = vp.color_range(); - vp.set_premultiplied_alpha(new_premultiplied_); - vp.set_colorspace(new_colorspace_); - vp.set_interlacing(new_interlacing_); - vp.set_pixel_aspect_ratio(new_pixel_ar_); - vp.set_color_range(new_range_); + vp.set_premultiplied_alpha(new_premultiplied_); + vp.set_colorspace(new_colorspace_); + vp.set_interlacing(new_interlacing_); + vp.set_pixel_aspect_ratio(new_pixel_ar_); + vp.set_color_range(new_range_); - footage_->SetVideoParams(vp, video_index_); + footage_->SetVideoParams(vp, video_index_); } void VideoStreamProperties::VideoStreamChangeCommand::undo() { - VideoParams vp = footage_->GetVideoParams(video_index_); + VideoParams vp = footage_->GetVideoParams(video_index_); - vp.set_premultiplied_alpha(old_premultiplied_); - vp.set_colorspace(old_colorspace_); - vp.set_interlacing(old_interlacing_); - vp.set_pixel_aspect_ratio(old_pixel_ar_); - vp.set_color_range(old_range_); + vp.set_premultiplied_alpha(old_premultiplied_); + vp.set_colorspace(old_colorspace_); + vp.set_interlacing(old_interlacing_); + vp.set_pixel_aspect_ratio(old_pixel_ar_); + vp.set_color_range(old_range_); - footage_->SetVideoParams(vp, video_index_); + footage_->SetVideoParams(vp, video_index_); } -VideoStreamProperties::ImageSequenceChangeCommand::ImageSequenceChangeCommand(Footage *footage, int video_index, int64_t start_index, int64_t duration, const rational &frame_rate) : - footage_(footage), - video_index_(video_index), - new_start_index_(start_index), - new_duration_(duration), - new_frame_rate_(frame_rate) +VideoStreamProperties::ImageSequenceChangeCommand::ImageSequenceChangeCommand( + Footage *footage, int video_index, int64_t start_index, int64_t duration, + const rational &frame_rate) + : footage_(footage) + , video_index_(video_index) + , new_start_index_(start_index) + , new_duration_(duration) + , new_frame_rate_(frame_rate) { } -Project *VideoStreamProperties::ImageSequenceChangeCommand::GetRelevantProject() const +Project * +VideoStreamProperties::ImageSequenceChangeCommand::GetRelevantProject() const { - return footage_->project(); + return footage_->project(); } void VideoStreamProperties::ImageSequenceChangeCommand::redo() { - VideoParams vp = footage_->GetVideoParams(video_index_); + VideoParams vp = footage_->GetVideoParams(video_index_); - old_start_index_ = vp.start_time(); - vp.set_start_time(new_start_index_); + old_start_index_ = vp.start_time(); + vp.set_start_time(new_start_index_); - old_duration_ = vp.duration(); - vp.set_duration(new_duration_); + old_duration_ = vp.duration(); + vp.set_duration(new_duration_); - old_frame_rate_ = vp.frame_rate(); - vp.set_frame_rate(new_frame_rate_); - vp.set_time_base(new_frame_rate_.flipped()); + old_frame_rate_ = vp.frame_rate(); + vp.set_frame_rate(new_frame_rate_); + vp.set_time_base(new_frame_rate_.flipped()); - footage_->SetVideoParams(vp, video_index_); + footage_->SetVideoParams(vp, video_index_); } void VideoStreamProperties::ImageSequenceChangeCommand::undo() { - VideoParams vp = footage_->GetVideoParams(video_index_); + VideoParams vp = footage_->GetVideoParams(video_index_); - vp.set_start_time(old_start_index_); - vp.set_duration(old_duration_); - vp.set_frame_rate(old_frame_rate_); - vp.set_time_base(old_frame_rate_.flipped()); + vp.set_start_time(old_start_index_); + vp.set_duration(old_duration_); + vp.set_frame_rate(old_frame_rate_); + vp.set_time_base(old_frame_rate_.flipped()); - footage_->SetVideoParams(vp, video_index_); + footage_->SetVideoParams(vp, video_index_); } } diff --git a/app/dialog/footageproperties/streamproperties/videostreamproperties.h b/app/dialog/footageproperties/streamproperties/videostreamproperties.h index dec410c97..c8c153b08 100644 --- a/app/dialog/footageproperties/streamproperties/videostreamproperties.h +++ b/app/dialog/footageproperties/streamproperties/videostreamproperties.h @@ -29,126 +29,119 @@ #include "widget/slider/integerslider.h" #include "widget/standardcombos/standardcombos.h" -namespace olive { - -class VideoStreamProperties : public StreamProperties +namespace olive { - Q_OBJECT + +class VideoStreamProperties : public StreamProperties { + Q_OBJECT public: - VideoStreamProperties(Footage *footage, int video_index); + VideoStreamProperties(Footage *footage, int video_index); - virtual void Accept(MultiUndoCommand *parent) override; + virtual void Accept(MultiUndoCommand *parent) override; - virtual bool SanityCheck() override; + virtual bool SanityCheck() override; private: - Footage *footage_; + Footage *footage_; - int video_index_; + int video_index_; - /** + /** * @brief Setting for associated/premultiplied alpha */ - QCheckBox* video_premultiply_alpha_; + QCheckBox *video_premultiply_alpha_; - /** + /** * @brief Setting for this media's color space */ - QComboBox* video_color_space_; + QComboBox *video_color_space_; - /** + /** * @brief Setting for this streams's color range */ - QComboBox *color_range_combo_; + QComboBox *color_range_combo_; - /** + /** * @brief Setting for video interlacing */ - InterlacedComboBox* video_interlace_combo_; + InterlacedComboBox *video_interlace_combo_; - /** + /** * @brief Sets the start index for image sequences */ - IntegerSlider* imgseq_start_time_; + IntegerSlider *imgseq_start_time_; - /** + /** * @brief Sets the end index for image sequences */ - IntegerSlider* imgseq_end_time_; + IntegerSlider *imgseq_end_time_; - /** + /** * @brief Sets the frame rate for image sequences */ - FrameRateComboBox* imgseq_frame_rate_; + FrameRateComboBox *imgseq_frame_rate_; - /** + /** * @brief Sets the pixel aspect ratio of the stream */ - PixelAspectRatioComboBox* pixel_aspect_combo_; + PixelAspectRatioComboBox *pixel_aspect_combo_; - class VideoStreamChangeCommand : public UndoCommand { - public: - VideoStreamChangeCommand(Footage *footage, - int video_index, - bool premultiplied, - QString colorspace, - VideoParams::Interlacing interlacing, - const rational& pixel_ar, - VideoParams::ColorRange range); + class VideoStreamChangeCommand : public UndoCommand { + public: + VideoStreamChangeCommand(Footage *footage, int video_index, + bool premultiplied, QString colorspace, + VideoParams::Interlacing interlacing, + const rational &pixel_ar, + VideoParams::ColorRange range); - virtual Project* GetRelevantProject() const override; + virtual Project *GetRelevantProject() const override; - protected: - virtual void redo() override; - virtual void undo() override; + protected: + virtual void redo() override; + virtual void undo() override; - private: - Footage *footage_; - int video_index_; + private: + Footage *footage_; + int video_index_; - bool new_premultiplied_; - QString new_colorspace_; - VideoParams::Interlacing new_interlacing_; - rational new_pixel_ar_; - VideoParams::ColorRange new_range_; + bool new_premultiplied_; + QString new_colorspace_; + VideoParams::Interlacing new_interlacing_; + rational new_pixel_ar_; + VideoParams::ColorRange new_range_; - bool old_premultiplied_; - QString old_colorspace_; - VideoParams::Interlacing old_interlacing_; - rational old_pixel_ar_; - VideoParams::ColorRange old_range_; + bool old_premultiplied_; + QString old_colorspace_; + VideoParams::Interlacing old_interlacing_; + rational old_pixel_ar_; + VideoParams::ColorRange old_range_; + }; - }; + class ImageSequenceChangeCommand : public UndoCommand { + public: + ImageSequenceChangeCommand(Footage *footage, int video_index, + int64_t start_index, int64_t duration, + const rational &frame_rate); - class ImageSequenceChangeCommand : public UndoCommand { - public: - ImageSequenceChangeCommand(Footage *footage, - int video_index, - int64_t start_index, - int64_t duration, - const rational& frame_rate); + virtual Project *GetRelevantProject() const override; - virtual Project* GetRelevantProject() const override; + protected: + virtual void redo() override; + virtual void undo() override; - protected: - virtual void redo() override; - virtual void undo() override; + private: + Footage *footage_; + int video_index_; - private: - Footage *footage_; - int video_index_; + int64_t new_start_index_; + int64_t old_start_index_; - int64_t new_start_index_; - int64_t old_start_index_; - - int64_t new_duration_; - int64_t old_duration_; - - rational new_frame_rate_; - rational old_frame_rate_; - - }; + int64_t new_duration_; + int64_t old_duration_; + rational new_frame_rate_; + rational old_frame_rate_; + }; }; } diff --git a/app/dialog/footagerelink/footagerelinkdialog.cpp b/app/dialog/footagerelink/footagerelinkdialog.cpp index a608a049c..e49365735 100644 --- a/app/dialog/footagerelink/footagerelinkdialog.cpp +++ b/app/dialog/footagerelink/footagerelinkdialog.cpp @@ -29,155 +29,160 @@ #include #include -namespace olive { - -FootageRelinkDialog::FootageRelinkDialog(const QVector &footage, QWidget* parent) : - QDialog(parent), - footage_(footage) +namespace olive { - QVBoxLayout* layout = new QVBoxLayout(this); - layout->addWidget(new QLabel("The following files couldn't be found. Clips using them will be " - "unplayable until they're relinked.")); +FootageRelinkDialog::FootageRelinkDialog(const QVector &footage, + QWidget *parent) + : QDialog(parent) + , footage_(footage) +{ + QVBoxLayout *layout = new QVBoxLayout(this); - table_ = new QTreeWidget(); + layout->addWidget(new QLabel( + "The following files couldn't be found. Clips using them will be " + "unplayable until they're relinked.")); - table_->setColumnCount(3); - table_->setHeaderLabels({tr("Footage"), tr("Filename"), tr("Actions")}); - table_->setRootIsDecorated(false); - table_->setSelectionBehavior(QAbstractItemView::SelectRows); - table_->header()->setSectionsMovable(false); + table_ = new QTreeWidget(); - // Prefer stretching URL column (QHeaderView defaults to stretching the last column, which in - // our case is just a browse button) - table_->header()->setSectionResizeMode(1, QHeaderView::Stretch); - table_->header()->setStretchLastSection(false); + table_->setColumnCount(3); + table_->setHeaderLabels({ tr("Footage"), tr("Filename"), tr("Actions") }); + table_->setRootIsDecorated(false); + table_->setSelectionBehavior(QAbstractItemView::SelectRows); + table_->header()->setSectionsMovable(false); - for (int i=0; iheader()->setSectionResizeMode(1, QHeaderView::Stretch); + table_->header()->setStretchLastSection(false); - QWidget* item_actions = new QWidget(); - QHBoxLayout* item_actions_layout = new QHBoxLayout(item_actions); - QPushButton* item_browse_btn = new QPushButton(tr("Browse")); - item_browse_btn->setProperty("index", i); - connect(item_browse_btn, &QPushButton::clicked, this, &FootageRelinkDialog::BrowseForFootage); - item_actions_layout->addWidget(item_browse_btn); + for (int i = 0; i < footage.size(); i++) { + Footage *f = footage.at(i); + QTreeWidgetItem *item = new QTreeWidgetItem(); - item->setIcon(0, f->data(Node::ICON).value()); - item->setText(0, f->GetLabel()); - item->setText(1, f->filename()); + QWidget *item_actions = new QWidget(); + QHBoxLayout *item_actions_layout = new QHBoxLayout(item_actions); + QPushButton *item_browse_btn = new QPushButton(tr("Browse")); + item_browse_btn->setProperty("index", i); + connect(item_browse_btn, &QPushButton::clicked, this, + &FootageRelinkDialog::BrowseForFootage); + item_actions_layout->addWidget(item_browse_btn); - table_->addTopLevelItem(item); + item->setIcon(0, f->data(Node::ICON).value()); + item->setText(0, f->GetLabel()); + item->setText(1, f->filename()); - table_->setItemWidget(item, 2, item_actions); - } + table_->addTopLevelItem(item); - layout->addWidget(table_); + table_->setItemWidget(item, 2, item_actions); + } - QDialogButtonBox* buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); - connect(buttons, &QDialogButtonBox::accepted, this, &FootageRelinkDialog::accept); - connect(buttons, &QDialogButtonBox::rejected, this, &FootageRelinkDialog::reject); - layout->addWidget(buttons); - - setWindowTitle(tr("Relink Footage")); + layout->addWidget(table_); + QDialogButtonBox *buttons = + new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); + connect(buttons, &QDialogButtonBox::accepted, this, + &FootageRelinkDialog::accept); + connect(buttons, &QDialogButtonBox::rejected, this, + &FootageRelinkDialog::reject); + layout->addWidget(buttons); + setWindowTitle(tr("Relink Footage")); } void FootageRelinkDialog::UpdateFootageItem(int index) { - Footage* f = footage_.at(index); - QTreeWidgetItem* item = table_->topLevelItem(index); - item->setIcon(0, f->data(Node::ICON).value()); - item->setText(1, f->filename()); + Footage *f = footage_.at(index); + QTreeWidgetItem *item = table_->topLevelItem(index); + item->setIcon(0, f->data(Node::ICON).value()); + item->setText(1, f->filename()); } void FootageRelinkDialog::BrowseForFootage() { - int index = sender()->property("index").toInt(); - Footage* f = footage_.at(index); + int index = sender()->property("index").toInt(); + Footage *f = footage_.at(index); - QFileInfo info(f->filename()); + QFileInfo info(f->filename()); - QString new_fn = QFileDialog::getOpenFileName(this, - tr("Relink \"%1\"").arg(f->GetLabel()), - info.absolutePath()); + QString new_fn = QFileDialog::getOpenFileName( + this, tr("Relink \"%1\"").arg(f->GetLabel()), info.absolutePath()); - // Originally, this function would attempt to filter to the exact filename of the missing file. - // However, this would break on Windows if the filename had any spaces in it. The reason is - // Windows separates its extensions with ';' while Qt separates them with ' '. Qt isn't - // intelligent enough to determine whether it's a list of extensions or a single filename with a - // space in it, it just does a global replace of ' ' to ';'. There's no way around it, outside of - // bypassing Qt entirely and using Win32's GetOpenFileName() directly. As annoying as it is, I've - // just disabled it for now. - //QStringLiteral("%1 (\"%1\");;%2 (*)").arg(info.fileName(), tr("All Files"))); + // Originally, this function would attempt to filter to the exact filename of the missing file. + // However, this would break on Windows if the filename had any spaces in it. The reason is + // Windows separates its extensions with ';' while Qt separates them with ' '. Qt isn't + // intelligent enough to determine whether it's a list of extensions or a single filename with a + // space in it, it just does a global replace of ' ' to ';'. There's no way around it, outside of + // bypassing Qt entirely and using Win32's GetOpenFileName() directly. As annoying as it is, I've + // just disabled it for now. + //QStringLiteral("%1 (\"%1\");;%2 (*)").arg(info.fileName(), tr("All Files"))); - // We received a new filename - if (!new_fn.isEmpty()) { - // Store original dir since we might be able to use this to find other files - QDir original_dir = info.dir(); - QDir new_dir = QFileInfo(new_fn).dir(); + // We received a new filename + if (!new_fn.isEmpty()) { + // Store original dir since we might be able to use this to find other files + QDir original_dir = info.dir(); + QDir new_dir = QFileInfo(new_fn).dir(); - // Set new filename since this was set manually by the user - f->set_filename(new_fn); + // Set new filename since this was set manually by the user + f->set_filename(new_fn); - // Assume footage is valid here. We could do some decoder probing to ensure it's a usable file - // but otherwise we assume the user knows what they're doing here. + // Assume footage is valid here. We could do some decoder probing to ensure it's a usable file + // but otherwise we assume the user knows what they're doing here. - // Set footage to valid and update icon - f->SetValid(); + // Set footage to valid and update icon + f->SetValid(); - // Update item visually - UpdateFootageItem(index); + // Update item visually + UpdateFootageItem(index); - // Check all other footage files for matches - for (int it=0; itIsValid()) { - // Get footage path relative to original directory - QString relative_to_original = original_dir.relativeFilePath(other_footage->filename()); - QString absolute_to_new = new_dir.filePath(relative_to_original); + // Ignore current footage file and footage that's already valid of course + if (index != it && !other_footage->IsValid()) { + // Get footage path relative to original directory + QString relative_to_original = + original_dir.relativeFilePath(other_footage->filename()); + QString absolute_to_new = + new_dir.filePath(relative_to_original); - // Second attempt. Try appending the filename to our new filepath - if (!QFileInfo::exists(absolute_to_new)) { - QFileInfo file_info(other_footage->filename()); - absolute_to_new = new_dir.filePath(file_info.fileName()); - } + // Second attempt. Try appending the filename to our new filepath + if (!QFileInfo::exists(absolute_to_new)) { + QFileInfo file_info(other_footage->filename()); + absolute_to_new = new_dir.filePath(file_info.fileName()); + } - // Check if file exists - if (QFileInfo::exists(absolute_to_new)) { - other_footage->set_filename(absolute_to_new); - other_footage->SetValid(); - UpdateFootageItem(it); - } - } - } - } + // Check if file exists + if (QFileInfo::exists(absolute_to_new)) { + other_footage->set_filename(absolute_to_new); + other_footage->SetValid(); + UpdateFootageItem(it); + } + } + } + } - // Check where the next invalid footage is. If there is none, accept automatically. Otherwise, - // jump to that footage so the user knows where it is. - int next_invalid = -1; - for (int i=0; iIsValid()) { - next_invalid = i; - break; - } - } + // Check where the next invalid footage is. If there is none, accept automatically. Otherwise, + // jump to that footage so the user knows where it is. + int next_invalid = -1; + for (int i = 0; i < footage_.size(); i++) { + if (!footage_.at(i)->IsValid()) { + next_invalid = i; + break; + } + } - if (next_invalid == -1) { - // No more invalid footage, just accept - this->accept(); - } else { - // Jump to next invalid footage - QModelIndex idx = table_->model()->index(next_invalid, 0); - table_->selectionModel()->select(idx, - QItemSelectionModel::Select | QItemSelectionModel::Rows); - table_->scrollTo(idx); - - } + if (next_invalid == -1) { + // No more invalid footage, just accept + this->accept(); + } else { + // Jump to next invalid footage + QModelIndex idx = table_->model()->index(next_invalid, 0); + table_->selectionModel()->select(idx, QItemSelectionModel::Select | + QItemSelectionModel::Rows); + table_->scrollTo(idx); + } } } diff --git a/app/dialog/footagerelink/footagerelinkdialog.h b/app/dialog/footagerelink/footagerelinkdialog.h index 251db09b1..1d96573c6 100644 --- a/app/dialog/footagerelink/footagerelinkdialog.h +++ b/app/dialog/footagerelink/footagerelinkdialog.h @@ -26,24 +26,24 @@ #include "node/project/footage/footage.h" -namespace olive { - -class FootageRelinkDialog : public QDialog +namespace olive { - Q_OBJECT + +class FootageRelinkDialog : public QDialog { + Q_OBJECT public: - FootageRelinkDialog(const QVector& footage, QWidget* parent = nullptr); + FootageRelinkDialog(const QVector &footage, + QWidget *parent = nullptr); private: - void UpdateFootageItem(int index); + void UpdateFootageItem(int index); - QTreeWidget* table_; + QTreeWidget *table_; - QVector footage_; + QVector footage_; private slots: - void BrowseForFootage(); - + void BrowseForFootage(); }; } diff --git a/app/dialog/keyframeproperties/keyframeproperties.cpp b/app/dialog/keyframeproperties/keyframeproperties.cpp index fb508e07a..4bd79340b 100644 --- a/app/dialog/keyframeproperties/keyframeproperties.cpp +++ b/app/dialog/keyframeproperties/keyframeproperties.cpp @@ -27,215 +27,230 @@ #include "node/nodeundo.h" #include "widget/keyframeview/keyframeviewundo.h" -namespace olive { - -KeyframePropertiesDialog::KeyframePropertiesDialog(const std::vector &keys, const rational &timebase, QWidget *parent) : - QDialog(parent), - keys_(keys), - timebase_(timebase) +namespace olive { - setWindowTitle(tr("Keyframe Properties")); - QGridLayout* layout = new QGridLayout(this); +KeyframePropertiesDialog::KeyframePropertiesDialog( + const std::vector &keys, const rational &timebase, + QWidget *parent) + : QDialog(parent) + , keys_(keys) + , timebase_(timebase) +{ + setWindowTitle(tr("Keyframe Properties")); - int row = 0; + QGridLayout *layout = new QGridLayout(this); - layout->addWidget(new QLabel("Time:"), row, 0); + int row = 0; - time_slider_ = new RationalSlider(); - time_slider_->SetDisplayType(RationalSlider::kTime); - time_slider_->SetTimebase(timebase_); - layout->addWidget(time_slider_, row, 1); + layout->addWidget(new QLabel("Time:"), row, 0); - row++; + time_slider_ = new RationalSlider(); + time_slider_->SetDisplayType(RationalSlider::kTime); + time_slider_->SetTimebase(timebase_); + layout->addWidget(time_slider_, row, 1); - layout->addWidget(new QLabel("Type:"), row, 0); + row++; - type_select_ = new QComboBox(); - connect(type_select_, SIGNAL(currentIndexChanged(int)), this, SLOT(KeyTypeChanged(int))); - layout->addWidget(type_select_, row, 1); + layout->addWidget(new QLabel("Type:"), row, 0); - row++; + type_select_ = new QComboBox(); + connect(type_select_, SIGNAL(currentIndexChanged(int)), this, + SLOT(KeyTypeChanged(int))); + layout->addWidget(type_select_, row, 1); - // Bezier handles - bezier_group_ = new QGroupBox(); + row++; - QGridLayout* bezier_group_layout = new QGridLayout(bezier_group_); + // Bezier handles + bezier_group_ = new QGroupBox(); - bezier_group_layout->addWidget(new QLabel(tr("In:")), 0, 0); + QGridLayout *bezier_group_layout = new QGridLayout(bezier_group_); - bezier_in_x_slider_ = new FloatSlider(); - bezier_group_layout->addWidget(bezier_in_x_slider_, 0, 1); + bezier_group_layout->addWidget(new QLabel(tr("In:")), 0, 0); - bezier_in_y_slider_ = new FloatSlider(); - bezier_group_layout->addWidget(bezier_in_y_slider_, 0, 2); + bezier_in_x_slider_ = new FloatSlider(); + bezier_group_layout->addWidget(bezier_in_x_slider_, 0, 1); - bezier_group_layout->addWidget(new QLabel(tr("Out:")), 1, 0); + bezier_in_y_slider_ = new FloatSlider(); + bezier_group_layout->addWidget(bezier_in_y_slider_, 0, 2); - bezier_out_x_slider_ = new FloatSlider(); - bezier_group_layout->addWidget(bezier_out_x_slider_, 1, 1); + bezier_group_layout->addWidget(new QLabel(tr("Out:")), 1, 0); - bezier_out_y_slider_ = new FloatSlider(); - bezier_group_layout->addWidget(bezier_out_y_slider_, 1, 2); + bezier_out_x_slider_ = new FloatSlider(); + bezier_group_layout->addWidget(bezier_out_x_slider_, 1, 1); - layout->addWidget(bezier_group_, row, 0, 1, 2); + bezier_out_y_slider_ = new FloatSlider(); + bezier_group_layout->addWidget(bezier_out_y_slider_, 1, 2); - bool all_same_time = true; - bool can_set_time = true; + layout->addWidget(bezier_group_, row, 0, 1, 2); - bool all_same_type = true; + bool all_same_time = true; + bool can_set_time = true; - bool all_same_bezier_in_x = true; - bool all_same_bezier_in_y = true; - bool all_same_bezier_out_x = true; - bool all_same_bezier_out_y = true; + bool all_same_type = true; - for (size_t i=0;i 0) { - NodeKeyframe* prev_key = keys_.at(i-1); - NodeKeyframe* this_key = keys_.at(i); + bool all_same_bezier_in_x = true; + bool all_same_bezier_in_y = true; + bool all_same_bezier_out_x = true; + bool all_same_bezier_out_y = true; - // Determine if the keyframes are all the same time or not - if (all_same_time) { - all_same_time = (prev_key->time() == this_key->time()); - } + for (size_t i = 0; i < keys_.size(); i++) { + if (i > 0) { + NodeKeyframe *prev_key = keys_.at(i - 1); + NodeKeyframe *this_key = keys_.at(i); - // Determine if the keyframes are all the same type - if (all_same_type) { - all_same_type = (prev_key->type() == this_key->type()); - } + // Determine if the keyframes are all the same time or not + if (all_same_time) { + all_same_time = (prev_key->time() == this_key->time()); + } - // Check all four bezier control points - if (all_same_bezier_in_x) { - all_same_bezier_in_x = (prev_key->bezier_control_in().x() == this_key->bezier_control_in().x()); - } + // Determine if the keyframes are all the same type + if (all_same_type) { + all_same_type = (prev_key->type() == this_key->type()); + } - if (all_same_bezier_in_y) { - all_same_bezier_in_y = (prev_key->bezier_control_in().y() == this_key->bezier_control_in().y()); - } + // Check all four bezier control points + if (all_same_bezier_in_x) { + all_same_bezier_in_x = (prev_key->bezier_control_in().x() == + this_key->bezier_control_in().x()); + } - if (all_same_bezier_out_x) { - all_same_bezier_out_x = (prev_key->bezier_control_out().x() == this_key->bezier_control_out().x()); - } + if (all_same_bezier_in_y) { + all_same_bezier_in_y = (prev_key->bezier_control_in().y() == + this_key->bezier_control_in().y()); + } - if (all_same_bezier_out_y) { - all_same_bezier_out_y = (prev_key->bezier_control_out().y() == this_key->bezier_control_out().y()); - } - } + if (all_same_bezier_out_x) { + all_same_bezier_out_x = (prev_key->bezier_control_out().x() == + this_key->bezier_control_out().x()); + } - // Determine if any keyframes are on the same track (in which case we can't set the time) - if (can_set_time) { - for (size_t j=0;jtrack() == keys_.at(i)->track()) { - can_set_time = false; - break; - } - } - } + if (all_same_bezier_out_y) { + all_same_bezier_out_y = (prev_key->bezier_control_out().y() == + this_key->bezier_control_out().y()); + } + } - if (!all_same_time - && !all_same_type - && !can_set_time - && !all_same_bezier_in_x - && !all_same_bezier_in_y - && !all_same_bezier_out_x - && !all_same_bezier_out_y) { - break; - } - } + // Determine if any keyframes are on the same track (in which case we can't set the time) + if (can_set_time) { + for (size_t j = 0; j < keys_.size(); j++) { + if (i != j && keys_.at(j)->track() == keys_.at(i)->track()) { + can_set_time = false; + break; + } + } + } - if (all_same_time) { - time_slider_->SetValue(keys_.front()->time()); - } else { - time_slider_->SetTristate(); - } + if (!all_same_time && !all_same_type && !can_set_time && + !all_same_bezier_in_x && !all_same_bezier_in_y && + !all_same_bezier_out_x && !all_same_bezier_out_y) { + break; + } + } - time_slider_->setEnabled(can_set_time); + if (all_same_time) { + time_slider_->SetValue(keys_.front()->time()); + } else { + time_slider_->SetTristate(); + } - if (!all_same_type) { - // If all keyframes aren't the same type, add an empty item - type_select_->addItem(QStringLiteral("--"), -1); + time_slider_->setEnabled(can_set_time); - // Ensure UI updates for the index being 0 - KeyTypeChanged(0); - } + if (!all_same_type) { + // If all keyframes aren't the same type, add an empty item + type_select_->addItem(QStringLiteral("--"), -1); - type_select_->addItem(tr("Linear"), NodeKeyframe::kLinear); - type_select_->addItem(tr("Hold"), NodeKeyframe::kHold); - type_select_->addItem(tr("Bezier"), NodeKeyframe::kBezier); + // Ensure UI updates for the index being 0 + KeyTypeChanged(0); + } - if (all_same_type) { - // If all keyframes are the same type, set it here - for (int i=0;icount();i++) { - if (type_select_->itemData(i).toInt() == keys_.front()->type()) { - type_select_->setCurrentIndex(i); + type_select_->addItem(tr("Linear"), NodeKeyframe::kLinear); + type_select_->addItem(tr("Hold"), NodeKeyframe::kHold); + type_select_->addItem(tr("Bezier"), NodeKeyframe::kBezier); - // Ensure UI updates for this index - KeyTypeChanged(i); - break; - } - } - } + if (all_same_type) { + // If all keyframes are the same type, set it here + for (int i = 0; i < type_select_->count(); i++) { + if (type_select_->itemData(i).toInt() == keys_.front()->type()) { + type_select_->setCurrentIndex(i); - SetUpBezierSlider(bezier_in_x_slider_, all_same_bezier_in_x, keys_.front()->bezier_control_in().x()); - SetUpBezierSlider(bezier_in_y_slider_, all_same_bezier_in_y, keys_.front()->bezier_control_in().y()); - SetUpBezierSlider(bezier_out_x_slider_, all_same_bezier_out_x, keys_.front()->bezier_control_out().x()); - SetUpBezierSlider(bezier_out_y_slider_, all_same_bezier_out_y, keys_.front()->bezier_control_out().y()); + // Ensure UI updates for this index + KeyTypeChanged(i); + break; + } + } + } - row++; + SetUpBezierSlider(bezier_in_x_slider_, all_same_bezier_in_x, + keys_.front()->bezier_control_in().x()); + SetUpBezierSlider(bezier_in_y_slider_, all_same_bezier_in_y, + keys_.front()->bezier_control_in().y()); + SetUpBezierSlider(bezier_out_x_slider_, all_same_bezier_out_x, + keys_.front()->bezier_control_out().x()); + SetUpBezierSlider(bezier_out_y_slider_, all_same_bezier_out_y, + keys_.front()->bezier_control_out().y()); - QDialogButtonBox* buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); - buttons->setCenterButtons(true); - layout->addWidget(buttons, row, 0, 1, 2); - connect(buttons, &QDialogButtonBox::accepted, this, &QDialog::accept); - connect(buttons, &QDialogButtonBox::rejected, this, &QDialog::reject); + row++; + + QDialogButtonBox *buttons = + new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); + buttons->setCenterButtons(true); + layout->addWidget(buttons, row, 0, 1, 2); + connect(buttons, &QDialogButtonBox::accepted, this, &QDialog::accept); + connect(buttons, &QDialogButtonBox::rejected, this, &QDialog::reject); } void KeyframePropertiesDialog::accept() { - MultiUndoCommand* command = new MultiUndoCommand(); + MultiUndoCommand *command = new MultiUndoCommand(); - rational new_time = time_slider_->GetValue(); - int new_type = type_select_->currentData().toInt(); + rational new_time = time_slider_->GetValue(); + int new_type = type_select_->currentData().toInt(); - foreach (NodeKeyframe* key, keys_) { - if (time_slider_->isEnabled() && !time_slider_->IsTristate()) { - command->add_child(new NodeParamSetKeyframeTimeCommand(key, new_time)); - } + foreach (NodeKeyframe *key, keys_) { + if (time_slider_->isEnabled() && !time_slider_->IsTristate()) { + command->add_child( + new NodeParamSetKeyframeTimeCommand(key, new_time)); + } - if (new_type > -1) { - command->add_child(new KeyframeSetTypeCommand(key, static_cast(new_type))); - } + if (new_type > -1) { + command->add_child(new KeyframeSetTypeCommand( + key, static_cast(new_type))); + } - if (bezier_group_->isEnabled()) { - command->add_child(new KeyframeSetBezierControlPoint(key, - NodeKeyframe::kInHandle, - QPointF(bezier_in_x_slider_->GetValue(), bezier_in_y_slider_->GetValue()))); + if (bezier_group_->isEnabled()) { + command->add_child(new KeyframeSetBezierControlPoint( + key, NodeKeyframe::kInHandle, + QPointF(bezier_in_x_slider_->GetValue(), + bezier_in_y_slider_->GetValue()))); - command->add_child(new KeyframeSetBezierControlPoint(key, - NodeKeyframe::kOutHandle, - QPointF(bezier_out_x_slider_->GetValue(), bezier_out_y_slider_->GetValue()))); - } - } + command->add_child(new KeyframeSetBezierControlPoint( + key, NodeKeyframe::kOutHandle, + QPointF(bezier_out_x_slider_->GetValue(), + bezier_out_y_slider_->GetValue()))); + } + } - Core::instance()->undo_stack()->push(command, tr("Set Keyframe Properties")); + Core::instance()->undo_stack()->push(command, + tr("Set Keyframe Properties")); - QDialog::accept(); + QDialog::accept(); } -void KeyframePropertiesDialog::SetUpBezierSlider(FloatSlider *slider, bool all_same, double value) +void KeyframePropertiesDialog::SetUpBezierSlider(FloatSlider *slider, + bool all_same, double value) { - if (all_same) { - slider->SetValue(value); - } else { - slider->SetTristate(); - } + if (all_same) { + slider->SetValue(value); + } else { + slider->SetTristate(); + } } void KeyframePropertiesDialog::KeyTypeChanged(int index) { - bezier_group_->setEnabled(type_select_->itemData(index) == NodeKeyframe::kBezier); + bezier_group_->setEnabled(type_select_->itemData(index) == + NodeKeyframe::kBezier); } } diff --git a/app/dialog/keyframeproperties/keyframeproperties.h b/app/dialog/keyframeproperties/keyframeproperties.h index 39a76147c..d8fe48310 100644 --- a/app/dialog/keyframeproperties/keyframeproperties.h +++ b/app/dialog/keyframeproperties/keyframeproperties.h @@ -29,41 +29,42 @@ #include "widget/slider/floatslider.h" #include "widget/slider/rationalslider.h" -namespace olive { - -class KeyframePropertiesDialog : public QDialog +namespace olive { - Q_OBJECT + +class KeyframePropertiesDialog : public QDialog { + Q_OBJECT public: - KeyframePropertiesDialog(const std::vector& keys, const rational& timebase, QWidget* parent = nullptr); + KeyframePropertiesDialog(const std::vector &keys, + const rational &timebase, + QWidget *parent = nullptr); public slots: - virtual void accept() override; + virtual void accept() override; private: - void SetUpBezierSlider(FloatSlider *slider, bool all_same, double value); + void SetUpBezierSlider(FloatSlider *slider, bool all_same, double value); - const std::vector& keys_; + const std::vector &keys_; - rational timebase_; + rational timebase_; - RationalSlider* time_slider_; + RationalSlider *time_slider_; - QComboBox* type_select_; + QComboBox *type_select_; - QGroupBox* bezier_group_; + QGroupBox *bezier_group_; - FloatSlider* bezier_in_x_slider_; + FloatSlider *bezier_in_x_slider_; - FloatSlider* bezier_in_y_slider_; + FloatSlider *bezier_in_y_slider_; - FloatSlider* bezier_out_x_slider_; + FloatSlider *bezier_out_x_slider_; - FloatSlider* bezier_out_y_slider_; + FloatSlider *bezier_out_y_slider_; private slots: - void KeyTypeChanged(int index); - + void KeyTypeChanged(int index); }; } diff --git a/app/dialog/markerproperties/markerpropertiesdialog.cpp b/app/dialog/markerproperties/markerpropertiesdialog.cpp index 5d215eefe..43b83abd1 100644 --- a/app/dialog/markerproperties/markerpropertiesdialog.cpp +++ b/app/dialog/markerproperties/markerpropertiesdialog.cpp @@ -28,128 +28,139 @@ #include "core.h" -namespace olive { +namespace olive +{ #define super QDialog -MarkerPropertiesDialog::MarkerPropertiesDialog(const std::vector &markers, const rational &timebase, QWidget *parent) : - super(parent), - markers_(markers) +MarkerPropertiesDialog::MarkerPropertiesDialog( + const std::vector &markers, const rational &timebase, + QWidget *parent) + : super(parent) + , markers_(markers) { - QGridLayout *layout = new QGridLayout(this); + QGridLayout *layout = new QGridLayout(this); - int row = 0; + int row = 0; - QGroupBox *time_group = new QGroupBox(tr("Time")); - QGridLayout *time_layout = new QGridLayout(time_group); + QGroupBox *time_group = new QGroupBox(tr("Time")); + QGridLayout *time_layout = new QGridLayout(time_group); - { - int time_row = 0; + { + int time_row = 0; - time_layout->addWidget(new QLabel(tr("In:")), time_row, 0); + time_layout->addWidget(new QLabel(tr("In:")), time_row, 0); - in_slider_ = new RationalSlider(); - time_layout->addWidget(in_slider_, time_row, 1); + in_slider_ = new RationalSlider(); + time_layout->addWidget(in_slider_, time_row, 1); - time_row++; + time_row++; - time_layout->addWidget(new QLabel(tr("Out:")), time_row, 0); + time_layout->addWidget(new QLabel(tr("Out:")), time_row, 0); - out_slider_ = new RationalSlider(); - time_layout->addWidget(out_slider_, time_row, 1); - } + out_slider_ = new RationalSlider(); + time_layout->addWidget(out_slider_, time_row, 1); + } - if (markers.size() == 1) { - in_slider_->SetValue(markers.front()->time().in()); - in_slider_->SetDisplayType(RationalSlider::kTime); - in_slider_->SetTimebase(timebase); - out_slider_->SetValue(markers.front()->time().out()); - out_slider_->SetDisplayType(RationalSlider::kTime); - out_slider_->SetTimebase(timebase); - } else { - // Markers cannot be on the same time, so we disable setting time if multiple markers are selected - in_slider_->setEnabled(false); - in_slider_->SetTristate(); - out_slider_->setEnabled(false); - out_slider_->SetTristate(); - } + if (markers.size() == 1) { + in_slider_->SetValue(markers.front()->time().in()); + in_slider_->SetDisplayType(RationalSlider::kTime); + in_slider_->SetTimebase(timebase); + out_slider_->SetValue(markers.front()->time().out()); + out_slider_->SetDisplayType(RationalSlider::kTime); + out_slider_->SetTimebase(timebase); + } else { + // Markers cannot be on the same time, so we disable setting time if multiple markers are selected + in_slider_->setEnabled(false); + in_slider_->SetTristate(); + out_slider_->setEnabled(false); + out_slider_->SetTristate(); + } - layout->addWidget(time_group, row, 0, 1, 2); + layout->addWidget(time_group, row, 0, 1, 2); - row++; + row++; - layout->addWidget(new QLabel(tr("Color:")), row, 0); + layout->addWidget(new QLabel(tr("Color:")), row, 0); - color_menu_ = new ColorCodingComboBox(); - layout->addWidget(color_menu_, row, 1); + color_menu_ = new ColorCodingComboBox(); + layout->addWidget(color_menu_, row, 1); - color_menu_->SetColor(markers.front()->color()); - for (size_t i=1; icolor() != color_menu_->GetSelectedColor()) { - color_menu_->SetColor(-1); - break; - } - } + color_menu_->SetColor(markers.front()->color()); + for (size_t i = 1; i < markers.size(); i++) { + if (markers.at(i)->color() != color_menu_->GetSelectedColor()) { + color_menu_->SetColor(-1); + break; + } + } - row++; + row++; - layout->addWidget(new QLabel(tr("Name:")), row, 0); + layout->addWidget(new QLabel(tr("Name:")), row, 0); - label_edit_ = new LineEditWithFocusSignal(); - connect(label_edit_, &LineEditWithFocusSignal::Focused, this, [this]{ - label_edit_->setPlaceholderText(QString()); - }); - layout->addWidget(label_edit_, row, 1); + label_edit_ = new LineEditWithFocusSignal(); + connect(label_edit_, &LineEditWithFocusSignal::Focused, this, + [this] { label_edit_->setPlaceholderText(QString()); }); + layout->addWidget(label_edit_, row, 1); - // Determine what the startup label text should be - label_edit_->setText(markers.front()->name()); - for (size_t i=1; iname() != label_edit_->text()) { - label_edit_->clear(); - label_edit_->setPlaceholderText(tr("(multiple)")); - break; - } - } + // Determine what the startup label text should be + label_edit_->setText(markers.front()->name()); + for (size_t i = 1; i < markers.size(); i++) { + if (markers.at(i)->name() != label_edit_->text()) { + label_edit_->clear(); + label_edit_->setPlaceholderText(tr("(multiple)")); + break; + } + } - row++; + row++; - QDialogButtonBox *buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); - connect(buttons, &QDialogButtonBox::accepted, this, &MarkerPropertiesDialog::accept); - connect(buttons, &QDialogButtonBox::rejected, this, &MarkerPropertiesDialog::reject); - layout->addWidget(buttons, row, 0, 1, 2); + QDialogButtonBox *buttons = + new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); + connect(buttons, &QDialogButtonBox::accepted, this, + &MarkerPropertiesDialog::accept); + connect(buttons, &QDialogButtonBox::rejected, this, + &MarkerPropertiesDialog::reject); + layout->addWidget(buttons, row, 0, 1, 2); - setWindowTitle(tr("Edit Markers")); - label_edit_->setFocus(); + setWindowTitle(tr("Edit Markers")); + label_edit_->setFocus(); } void MarkerPropertiesDialog::accept() { - if (in_slider_->isEnabled() && in_slider_->GetValue() > out_slider_->GetValue()) { - QMessageBox::critical(this, tr("Invalid Values"), tr("In point must be less than or equal to out point.")); - return; - } + if (in_slider_->isEnabled() && + in_slider_->GetValue() > out_slider_->GetValue()) { + QMessageBox::critical( + this, tr("Invalid Values"), + tr("In point must be less than or equal to out point.")); + return; + } - MultiUndoCommand *command = new MultiUndoCommand(); + MultiUndoCommand *command = new MultiUndoCommand(); - int color = color_menu_->GetSelectedColor(); + int color = color_menu_->GetSelectedColor(); - foreach (TimelineMarker *m, markers_) { - if (color != -1) { - command->add_child(new MarkerChangeColorCommand(m, color)); - } + foreach (TimelineMarker *m, markers_) { + if (color != -1) { + command->add_child(new MarkerChangeColorCommand(m, color)); + } - if (label_edit_->placeholderText().isEmpty()) { - command->add_child(new MarkerChangeNameCommand(m, label_edit_->text())); - } - } + if (label_edit_->placeholderText().isEmpty()) { + command->add_child( + new MarkerChangeNameCommand(m, label_edit_->text())); + } + } - if (markers_.size() == 1) { - command->add_child(new MarkerChangeTimeCommand(markers_.front(), TimeRange(in_slider_->GetValue(), out_slider_->GetValue()))); - } + if (markers_.size() == 1) { + command->add_child(new MarkerChangeTimeCommand( + markers_.front(), + TimeRange(in_slider_->GetValue(), out_slider_->GetValue()))); + } - Core::instance()->undo_stack()->push(command, tr("Set Marker Properties")); + Core::instance()->undo_stack()->push(command, tr("Set Marker Properties")); - super::accept(); + super::accept(); } } diff --git a/app/dialog/markerproperties/markerpropertiesdialog.h b/app/dialog/markerproperties/markerpropertiesdialog.h index b6cff4a56..f8d407469 100644 --- a/app/dialog/markerproperties/markerpropertiesdialog.h +++ b/app/dialog/markerproperties/markerpropertiesdialog.h @@ -28,49 +28,47 @@ #include "widget/colorlabelmenu/colorcodingcombobox.h" #include "widget/slider/rationalslider.h" -namespace olive { - -class LineEditWithFocusSignal : public QLineEdit +namespace olive { - Q_OBJECT + +class LineEditWithFocusSignal : public QLineEdit { + Q_OBJECT public: - LineEditWithFocusSignal(QWidget *parent = nullptr) : - QLineEdit(parent) - { - } + LineEditWithFocusSignal(QWidget *parent = nullptr) + : QLineEdit(parent) + { + } protected: - virtual void focusInEvent(QFocusEvent *e) override - { - QLineEdit::focusInEvent(e); - emit Focused(); - } + virtual void focusInEvent(QFocusEvent *e) override + { + QLineEdit::focusInEvent(e); + emit Focused(); + } signals: - void Focused(); - + void Focused(); }; -class MarkerPropertiesDialog : public QDialog -{ - Q_OBJECT +class MarkerPropertiesDialog : public QDialog { + Q_OBJECT public: - MarkerPropertiesDialog(const std::vector &markers, const rational &timebase, QWidget *parent = nullptr); + MarkerPropertiesDialog(const std::vector &markers, + const rational &timebase, QWidget *parent = nullptr); public slots: - virtual void accept() override; + virtual void accept() override; private: - std::vector markers_; + std::vector markers_; - LineEditWithFocusSignal *label_edit_; + LineEditWithFocusSignal *label_edit_; - ColorCodingComboBox *color_menu_; + ColorCodingComboBox *color_menu_; - RationalSlider *in_slider_; - - RationalSlider *out_slider_; + RationalSlider *in_slider_; + RationalSlider *out_slider_; }; } diff --git a/app/dialog/otioproperties/otiopropertiesdialog.cpp b/app/dialog/otioproperties/otiopropertiesdialog.cpp index e153aa47b..2807880ee 100644 --- a/app/dialog/otioproperties/otiopropertiesdialog.cpp +++ b/app/dialog/otioproperties/otiopropertiesdialog.cpp @@ -26,64 +26,72 @@ #include "core.h" #include "dialog/sequence/sequence.h" -namespace olive { - -OTIOPropertiesDialog::OTIOPropertiesDialog(const QList& sequences, Project* active_project, QWidget* parent) - : - QDialog(parent), - sequences_(sequences) +namespace olive { - QVBoxLayout* layout = new QVBoxLayout(this); - QLabel *msg = new QLabel(tr("OpenTimelineIO files do not store sequence parameters (resolution, frame rate, etc.)\n\n" - "Please set the correct parameters on the sequences below (they have been set to your default sequence parameters as a starting point).")); - msg->setWordWrap(true); - layout->addWidget(msg); +OTIOPropertiesDialog::OTIOPropertiesDialog(const QList &sequences, + Project *active_project, + QWidget *parent) + : QDialog(parent) + , sequences_(sequences) +{ + QVBoxLayout *layout = new QVBoxLayout(this); - table_ = new QTreeWidget(); - table_->setColumnCount(2); - table_->setHeaderLabels({tr("Sequence"), tr("Actions")}); - table_->setRootIsDecorated(false); + QLabel *msg = new QLabel(tr( + "OpenTimelineIO files do not store sequence parameters (resolution, frame rate, etc.)\n\n" + "Please set the correct parameters on the sequences below (they have been set to your default sequence parameters as a starting point).")); + msg->setWordWrap(true); + layout->addWidget(msg); - for (int i = 0; i < sequences.size(); i++) { - QTreeWidgetItem* item = new QTreeWidgetItem(); - Sequence* s = sequences.at(i); + table_ = new QTreeWidget(); + table_->setColumnCount(2); + table_->setHeaderLabels({ tr("Sequence"), tr("Actions") }); + table_->setRootIsDecorated(false); - QWidget* item_actions = new QWidget(); - QHBoxLayout* item_actions_layout = new QHBoxLayout(item_actions); - QPushButton* item_settings_btn = new QPushButton(tr("Settings")); - item_settings_btn->setProperty("index", i); - connect(item_settings_btn, &QPushButton::clicked, this, &OTIOPropertiesDialog::SetupSequence); - item_actions_layout->addWidget(item_settings_btn); + for (int i = 0; i < sequences.size(); i++) { + QTreeWidgetItem *item = new QTreeWidgetItem(); + Sequence *s = sequences.at(i); - item->setText(0, s->GetLabel()); + QWidget *item_actions = new QWidget(); + QHBoxLayout *item_actions_layout = new QHBoxLayout(item_actions); + QPushButton *item_settings_btn = new QPushButton(tr("Settings")); + item_settings_btn->setProperty("index", i); + connect(item_settings_btn, &QPushButton::clicked, this, + &OTIOPropertiesDialog::SetupSequence); + item_actions_layout->addWidget(item_settings_btn); - table_->addTopLevelItem(item); + item->setText(0, s->GetLabel()); - table_->setItemWidget(item, 1, item_actions); - } + table_->addTopLevelItem(item); - // Stretch first column to take up as much space as possible, and second column to take as little - table_->header()->setSectionResizeMode(0, QHeaderView::Stretch); - table_->header()->setSectionResizeMode(1, QHeaderView::Fixed); - table_->header()->setStretchLastSection(false); + table_->setItemWidget(item, 1, item_actions); + } - layout->addWidget(table_); + // Stretch first column to take up as much space as possible, and second column to take as little + table_->header()->setSectionResizeMode(0, QHeaderView::Stretch); + table_->header()->setSectionResizeMode(1, QHeaderView::Fixed); + table_->header()->setStretchLastSection(false); - QDialogButtonBox* buttons = new QDialogButtonBox(QDialogButtonBox::Ok|QDialogButtonBox::Cancel); - connect(buttons, &QDialogButtonBox::accepted, this, &OTIOPropertiesDialog::accept); - connect(buttons, &QDialogButtonBox::rejected, this, &OTIOPropertiesDialog::reject); - layout->addWidget(buttons); + layout->addWidget(table_); - setWindowTitle(tr("Load OpenTimelineIO Project")); + QDialogButtonBox *buttons = + new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); + connect(buttons, &QDialogButtonBox::accepted, this, + &OTIOPropertiesDialog::accept); + connect(buttons, &QDialogButtonBox::rejected, this, + &OTIOPropertiesDialog::reject); + layout->addWidget(buttons); + + setWindowTitle(tr("Load OpenTimelineIO Project")); } -void OTIOPropertiesDialog::SetupSequence() { - int index = sender()->property("index").toInt(); - Sequence* s = sequences_.at(index); - SequenceDialog sd(s, SequenceDialog::kNew); - sd.SetUndoable(false); - sd.exec(); +void OTIOPropertiesDialog::SetupSequence() +{ + int index = sender()->property("index").toInt(); + Sequence *s = sequences_.at(index); + SequenceDialog sd(s, SequenceDialog::kNew); + sd.SetUndoable(false); + sd.exec(); } -} // namespace olive +} // namespace olive diff --git a/app/dialog/otioproperties/otiopropertiesdialog.h b/app/dialog/otioproperties/otiopropertiesdialog.h index 1e748ad4e..6ad06075d 100644 --- a/app/dialog/otioproperties/otiopropertiesdialog.h +++ b/app/dialog/otioproperties/otiopropertiesdialog.h @@ -10,30 +10,32 @@ #include "node/project/sequence/sequence.h" #include "node/project.h" -namespace olive { +namespace olive +{ - /** +/** * @brief Dialog to load setting for OTIO sequences. * * Takes a list of Sequences and allows the setting of options for each. */ - class OTIOPropertiesDialog : public QDialog { - Q_OBJECT - public: - OTIOPropertiesDialog(const QList& sequences, Project* active_project, QWidget* parent = nullptr); +class OTIOPropertiesDialog : public QDialog { + Q_OBJECT +public: + OTIOPropertiesDialog(const QList &sequences, + Project *active_project, QWidget *parent = nullptr); - private: - QTreeWidget* table_; +private: + QTreeWidget *table_; - const QList sequences_; + const QList sequences_; - private slots: - /** +private slots: + /** * @brief Brings up the Sequence settings dialog. */ - void SetupSequence(); - }; + void SetupSequence(); +}; } //namespace olive -#endif // OTIOPROPERTIESDIALOG_H +#endif // OTIOPROPERTIESDIALOG_H diff --git a/app/dialog/preferences/keysequenceeditor.cpp b/app/dialog/preferences/keysequenceeditor.cpp index bd1c41c3f..b98f3ba3b 100644 --- a/app/dialog/preferences/keysequenceeditor.cpp +++ b/app/dialog/preferences/keysequenceeditor.cpp @@ -23,55 +23,62 @@ #include #include -namespace olive { +namespace olive +{ #define super QKeySequenceEdit -KeySequenceEditor::KeySequenceEditor(QWidget* parent, QAction* a) - : super(parent), action(a) { - setKeySequence(action->shortcut()); +KeySequenceEditor::KeySequenceEditor(QWidget *parent, QAction *a) + : super(parent) + , action(a) +{ + setKeySequence(action->shortcut()); } -void KeySequenceEditor::set_action_shortcut() { - action->setShortcut(keySequence()); +void KeySequenceEditor::set_action_shortcut() +{ + action->setShortcut(keySequence()); } -void KeySequenceEditor::reset_to_default() { - setKeySequence(action->property("keydefault").toString()); +void KeySequenceEditor::reset_to_default() +{ + setKeySequence(action->property("keydefault").toString()); } -QString KeySequenceEditor::action_name() { - return action->property("id").toString(); +QString KeySequenceEditor::action_name() +{ + return action->property("id").toString(); } -QString KeySequenceEditor::export_shortcut() { - QKeySequence ks = keySequence(); - if (ks != action->property("keydefault").value()) { - return action->property("id").toString() + "\t" + ks.toString(); - } - return nullptr; +QString KeySequenceEditor::export_shortcut() +{ + QKeySequence ks = keySequence(); + if (ks != action->property("keydefault").value()) { + return action->property("id").toString() + "\t" + ks.toString(); + } + return nullptr; } void KeySequenceEditor::keyPressEvent(QKeyEvent *e) { - if (e->key() == Qt::Key_Backspace) { - clear(); - } else if (e->key() == Qt::Key_Escape) { - e->ignore(); - } else{ - super::keyPressEvent(e); - } + if (e->key() == Qt::Key_Backspace) { + clear(); + } else if (e->key() == Qt::Key_Escape) { + e->ignore(); + } else { + super::keyPressEvent(e); + } } void KeySequenceEditor::keyReleaseEvent(QKeyEvent *e) { - if (e->key() == Qt::Key_Backspace) { - // Do nothing - } else if (e->key() == Qt::Key_Escape) { - e->ignore(); - } else { - super::keyReleaseEvent(e); - } + if (e->key() == Qt::Key_Backspace) { + // Do nothing + } else if (e->key() == Qt::Key_Escape) { + e->ignore(); + } else { + super::keyReleaseEvent(e); + } } } diff --git a/app/dialog/preferences/keysequenceeditor.h b/app/dialog/preferences/keysequenceeditor.h index 6047bf268..3f68d8148 100644 --- a/app/dialog/preferences/keysequenceeditor.h +++ b/app/dialog/preferences/keysequenceeditor.h @@ -25,7 +25,8 @@ #include "common/debug.h" -namespace olive { +namespace olive +{ /** * @brief The KeySequenceEditor class @@ -34,9 +35,9 @@ namespace olive { * keyboard shortcuts to and from it. */ class KeySequenceEditor : public QKeySequenceEdit { - Q_OBJECT + Q_OBJECT public: - /** + /** * @brief KeySequenceEditor Constructor * * @param parent @@ -47,18 +48,18 @@ public: * * The QAction to link to. This cannot be changed throughout the lifetime of a KeySequenceEditor. */ - KeySequenceEditor(QWidget *parent, QAction* a); + KeySequenceEditor(QWidget *parent, QAction *a); - /** + /** * @brief Sets the attached QAction's shortcut to the shortcut entered in this field. * * This is not done automatically in case the user cancels out of the Preferences dialog, in which case the * expectation is that the changes made will not be saved. Therefore, this needs to be triggered manually when * PreferencesDialog saves. */ - void set_action_shortcut(); + void set_action_shortcut(); - /** + /** * @brief Set this shortcut back to the QAction's default shortcut * * Each QAction contains the default shortcut in its `property("default")` and can be used to restore the default @@ -68,9 +69,9 @@ public: * the QAction into this edit field. To save it into the QAction, it's necessary to call set_action_shortcut() after * calling this function. */ - void reset_to_default(); + void reset_to_default(); - /** + /** * @brief Return attached QAction's unique ID * * Each of Olive's menu actions has a unique string ID (that, unlike the text, is not translated) for matching with @@ -81,9 +82,9 @@ public: * * The QAction's unique ID. */ - QString action_name(); + QString action_name(); - /** + /** * @brief Serialize this shortcut entry into a string that can be saved to a file * * @return @@ -93,18 +94,18 @@ public: * the QAction). If the entered shortcut is the same as the QAction's default shortcut, the return value is empty * because a default shortcut does not need to be saved to a file. */ - QString export_shortcut(); + QString export_shortcut(); protected: - virtual void keyPressEvent(QKeyEvent *e) override; + virtual void keyPressEvent(QKeyEvent *e) override; - virtual void keyReleaseEvent(QKeyEvent *e) override; + virtual void keyReleaseEvent(QKeyEvent *e) override; private: - /** + /** * @brief Internal reference to the linked QAction */ - QAction* action; + QAction *action; }; } diff --git a/app/dialog/preferences/preferences.cpp b/app/dialog/preferences/preferences.cpp index 5777e929d..6ce8d44fe 100644 --- a/app/dialog/preferences/preferences.cpp +++ b/app/dialog/preferences/preferences.cpp @@ -34,24 +34,25 @@ #include "tabs/preferenceskeyboardtab.h" #include "window/mainwindow/mainwindow.h" -namespace olive { - -PreferencesDialog::PreferencesDialog(MainWindow *main_window) : - ConfigDialogBase(main_window) +namespace olive { - setWindowTitle(tr("Preferences")); - AddTab(new PreferencesGeneralTab(), tr("General")); - AddTab(new PreferencesAppearanceTab(), tr("Appearance")); - AddTab(new PreferencesBehaviorTab(), tr("Behavior")); - AddTab(new PreferencesDiskTab(), tr("Disk")); - AddTab(new PreferencesAudioTab(), tr("Audio")); - AddTab(new PreferencesKeyboardTab(main_window), tr("Keyboard")); +PreferencesDialog::PreferencesDialog(MainWindow *main_window) + : ConfigDialogBase(main_window) +{ + setWindowTitle(tr("Preferences")); + + AddTab(new PreferencesGeneralTab(), tr("General")); + AddTab(new PreferencesAppearanceTab(), tr("Appearance")); + AddTab(new PreferencesBehaviorTab(), tr("Behavior")); + AddTab(new PreferencesDiskTab(), tr("Disk")); + AddTab(new PreferencesAudioTab(), tr("Audio")); + AddTab(new PreferencesKeyboardTab(main_window), tr("Keyboard")); } void PreferencesDialog::AcceptEvent() { - Config::Save(); + Config::Save(); } } diff --git a/app/dialog/preferences/preferences.h b/app/dialog/preferences/preferences.h index 87cdb7266..faa619896 100644 --- a/app/dialog/preferences/preferences.h +++ b/app/dialog/preferences/preferences.h @@ -30,7 +30,8 @@ #include "dialog/configbase/configdialogbase.h" -namespace olive { +namespace olive +{ class MainWindow; @@ -39,16 +40,14 @@ class MainWindow; * * A dialog for the global application settings. Mostly an interface for Config. */ -class PreferencesDialog : public ConfigDialogBase -{ - Q_OBJECT +class PreferencesDialog : public ConfigDialogBase { + Q_OBJECT public: - PreferencesDialog(MainWindow *main_window); + PreferencesDialog(MainWindow *main_window); protected: - virtual void AcceptEvent() override; - + virtual void AcceptEvent() override; }; } diff --git a/app/dialog/preferences/tabs/preferencesappearancetab.cpp b/app/dialog/preferences/tabs/preferencesappearancetab.cpp index 7751a581a..e292ab185 100644 --- a/app/dialog/preferences/tabs/preferencesappearancetab.cpp +++ b/app/dialog/preferences/tabs/preferencesappearancetab.cpp @@ -31,92 +31,96 @@ #include "widget/menu/menushared.h" #include "ui/colorcoding.h" -namespace olive { +namespace olive +{ PreferencesAppearanceTab::PreferencesAppearanceTab() { - QVBoxLayout* layout = new QVBoxLayout(this); + QVBoxLayout *layout = new QVBoxLayout(this); - QGridLayout* appearance_layout = new QGridLayout(); - layout->addLayout(appearance_layout); + QGridLayout *appearance_layout = new QGridLayout(); + layout->addLayout(appearance_layout); - int row = 0; + int row = 0; - // Appearance -> Theme - appearance_layout->addWidget(new QLabel(tr("Theme")), row, 0); + // Appearance -> Theme + appearance_layout->addWidget(new QLabel(tr("Theme")), row, 0); - style_combobox_ = new QComboBox(); + style_combobox_ = new QComboBox(); - { - const QMap& themes = StyleManager::available_themes(); - QMap::const_iterator i; - for (i=themes.cbegin(); i!=themes.cend(); i++) { - style_combobox_->addItem(i.value(), i.key()); + { + const QMap &themes = StyleManager::available_themes(); + QMap::const_iterator i; + for (i = themes.cbegin(); i != themes.cend(); i++) { + style_combobox_->addItem(i.value(), i.key()); - if (StyleManager::GetStyle() == i.key()) { - style_combobox_->setCurrentIndex(style_combobox_->count()-1); - } - } - } + if (StyleManager::GetStyle() == i.key()) { + style_combobox_->setCurrentIndex(style_combobox_->count() - 1); + } + } + } - appearance_layout->addWidget(style_combobox_, row, 1); + appearance_layout->addWidget(style_combobox_, row, 1); - row++; + row++; - { - QGroupBox* color_group = new QGroupBox(); - color_group->setTitle(tr("Default Node Colors")); + { + QGroupBox *color_group = new QGroupBox(); + color_group->setTitle(tr("Default Node Colors")); - QGridLayout* color_layout = new QGridLayout(color_group); + QGridLayout *color_layout = new QGridLayout(color_group); - for (int i=0; i(i)); - color_layout->addWidget(new QLabel(cat_name), i, 0); + for (int i = 0; i < Node::kCategoryCount; i++) { + QString cat_name = + Node::GetCategoryName(static_cast(i)); + color_layout->addWidget(new QLabel(cat_name), i, 0); - ColorCodingComboBox* ccc = new ColorCodingComboBox(); - ccc->SetColor(OLIVE_CONFIG_STR(QStringLiteral("CatColor%1").arg(i)).toInt()); - color_layout->addWidget(ccc, i, 1); - color_btns_.append(ccc); - } + ColorCodingComboBox *ccc = new ColorCodingComboBox(); + ccc->SetColor( + OLIVE_CONFIG_STR(QStringLiteral("CatColor%1").arg(i)).toInt()); + color_layout->addWidget(ccc, i, 1); + color_btns_.append(ccc); + } - appearance_layout->addWidget(color_group, row, 0, 1, 2); - } + appearance_layout->addWidget(color_group, row, 0, 1, 2); + } - row++; - { - QGroupBox* marker_group = new QGroupBox(); - marker_group->setTitle(tr("Miscellaneous")); + row++; + { + QGroupBox *marker_group = new QGroupBox(); + marker_group->setTitle(tr("Miscellaneous")); - QGridLayout* marker_layout = new QGridLayout(marker_group); + QGridLayout *marker_layout = new QGridLayout(marker_group); - marker_layout->addWidget(new QLabel("Default Marker Color"), 0, 0); + marker_layout->addWidget(new QLabel("Default Marker Color"), 0, 0); - marker_btn_ = new ColorCodingComboBox(); - marker_btn_->SetColor(OLIVE_CONFIG("MarkerColor").toInt()); - marker_layout->addWidget(marker_btn_, 0, 1); + marker_btn_ = new ColorCodingComboBox(); + marker_btn_->SetColor(OLIVE_CONFIG("MarkerColor").toInt()); + marker_layout->addWidget(marker_btn_, 0, 1); - appearance_layout->addWidget(marker_group, row, 0, 1, 2); - } + appearance_layout->addWidget(marker_group, row, 0, 1, 2); + } - layout->addStretch(); + layout->addStretch(); } void PreferencesAppearanceTab::Accept(MultiUndoCommand *command) { - Q_UNUSED(command) + Q_UNUSED(command) - QString style_path = style_combobox_->currentData().toString(); + QString style_path = style_combobox_->currentData().toString(); - if (style_path != StyleManager::GetStyle()) { - StyleManager::SetStyle(style_path); - OLIVE_CONFIG("Style") = style_path; - } + if (style_path != StyleManager::GetStyle()) { + StyleManager::SetStyle(style_path); + OLIVE_CONFIG("Style") = style_path; + } - for (int i=0; iGetSelectedColor(); - } + for (int i = 0; i < color_btns_.size(); i++) { + OLIVE_CONFIG_STR(QStringLiteral("CatColor%1").arg(i)) = + color_btns_.at(i)->GetSelectedColor(); + } - OLIVE_CONFIG("MarkerColor") = marker_btn_->GetSelectedColor(); + OLIVE_CONFIG("MarkerColor") = marker_btn_->GetSelectedColor(); } } diff --git a/app/dialog/preferences/tabs/preferencesappearancetab.h b/app/dialog/preferences/tabs/preferencesappearancetab.h index 63c2c2021..6e06f0c39 100644 --- a/app/dialog/preferences/tabs/preferencesappearancetab.h +++ b/app/dialog/preferences/tabs/preferencesappearancetab.h @@ -29,26 +29,25 @@ #include "ui/style/style.h" #include "widget/colorlabelmenu/colorcodingcombobox.h" -namespace olive { - -class PreferencesAppearanceTab : public ConfigDialogBaseTab +namespace olive { - Q_OBJECT -public: - PreferencesAppearanceTab(); - virtual void Accept(MultiUndoCommand* command) override; +class PreferencesAppearanceTab : public ConfigDialogBaseTab { + Q_OBJECT +public: + PreferencesAppearanceTab(); + + virtual void Accept(MultiUndoCommand *command) override; private: - /** + /** * @brief UI widget for selecting the current UI style */ - QComboBox* style_combobox_; + QComboBox *style_combobox_; - QVector color_btns_; - - ColorCodingComboBox* marker_btn_; + QVector color_btns_; + ColorCodingComboBox *marker_btn_; }; } diff --git a/app/dialog/preferences/tabs/preferencesaudiotab.cpp b/app/dialog/preferences/tabs/preferencesaudiotab.cpp index 211f070cb..e412e6625 100644 --- a/app/dialog/preferences/tabs/preferencesaudiotab.cpp +++ b/app/dialog/preferences/tabs/preferencesaudiotab.cpp @@ -27,248 +27,291 @@ #include "audio/audiomanager.h" #include "config/config.h" -namespace olive { +namespace olive +{ PreferencesAudioTab::PreferencesAudioTab() { - QVBoxLayout* audio_tab_layout = new QVBoxLayout(this); + QVBoxLayout *audio_tab_layout = new QVBoxLayout(this); - { - // Backend Layout - QGridLayout* main_layout = new QGridLayout(); - main_layout->setContentsMargins(0, 0, 0, 0); + { + // Backend Layout + QGridLayout *main_layout = new QGridLayout(); + main_layout->setContentsMargins(0, 0, 0, 0); - int row = 0; + int row = 0; - main_layout->addWidget(new QLabel(tr("Backend:")), row, 0); + main_layout->addWidget(new QLabel(tr("Backend:")), row, 0); - audio_backend_combobox_ = new QComboBox(); - connect(audio_backend_combobox_, static_cast(&QComboBox::currentIndexChanged), this, &PreferencesAudioTab::RefreshDevices); - main_layout->addWidget(audio_backend_combobox_, row, 1); + audio_backend_combobox_ = new QComboBox(); + connect(audio_backend_combobox_, + static_cast( + &QComboBox::currentIndexChanged), + this, &PreferencesAudioTab::RefreshDevices); + main_layout->addWidget(audio_backend_combobox_, row, 1); - audio_tab_layout->addLayout(main_layout); - } + audio_tab_layout->addLayout(main_layout); + } - { - QGroupBox* groupbox = new QGroupBox(); - audio_tab_layout->addWidget(groupbox); + { + QGroupBox *groupbox = new QGroupBox(); + audio_tab_layout->addWidget(groupbox); - QVBoxLayout* layout = new QVBoxLayout(groupbox); + QVBoxLayout *layout = new QVBoxLayout(groupbox); - int row = 0; + int row = 0; - { - // Output Group - QGroupBox* output_group = new QGroupBox(); - output_group->setTitle(tr("Output")); - layout->addWidget(output_group); + { + // Output Group + QGroupBox *output_group = new QGroupBox(); + output_group->setTitle(tr("Output")); + layout->addWidget(output_group); - QGridLayout* output_layout = new QGridLayout(output_group); + QGridLayout *output_layout = new QGridLayout(output_group); - output_layout->addWidget(new QLabel(tr("Device:")), row, 0); + output_layout->addWidget(new QLabel(tr("Device:")), row, 0); - audio_output_devices_ = new QComboBox(); - output_layout->addWidget(audio_output_devices_, row, 1); + audio_output_devices_ = new QComboBox(); + output_layout->addWidget(audio_output_devices_, row, 1); - row++; + row++; - { - int output_row = 0; + { + int output_row = 0; - QGroupBox *output_param_group = new QGroupBox(tr("Advanced")); - output_layout->addWidget(output_param_group, row, 0, 1, 2); + QGroupBox *output_param_group = new QGroupBox(tr("Advanced")); + output_layout->addWidget(output_param_group, row, 0, 1, 2); - QGridLayout *output_param_layout = new QGridLayout(output_param_group); + QGridLayout *output_param_layout = + new QGridLayout(output_param_group); - output_param_layout->addWidget(new QLabel(tr("Sample Rate:")), output_row, 0); + output_param_layout->addWidget(new QLabel(tr("Sample Rate:")), + output_row, 0); - output_rate_combo_ = new SampleRateComboBox(); - output_rate_combo_->SetSampleRate(OLIVE_CONFIG("AudioOutputSampleRate").toInt()); - output_param_layout->addWidget(output_rate_combo_, output_row, 1); + output_rate_combo_ = new SampleRateComboBox(); + output_rate_combo_->SetSampleRate( + OLIVE_CONFIG("AudioOutputSampleRate").toInt()); + output_param_layout->addWidget(output_rate_combo_, output_row, + 1); - output_row++; + output_row++; - output_param_layout->addWidget(new QLabel(tr("Channel Layout:")), output_row, 0); + output_param_layout->addWidget( + new QLabel(tr("Channel Layout:")), output_row, 0); - output_ch_layout_combo_ = new ChannelLayoutComboBox(); - output_ch_layout_combo_->SetChannelLayout(OLIVE_CONFIG("AudioOutputChannelLayout").toULongLong()); - output_param_layout->addWidget(output_ch_layout_combo_, output_row, 1); + output_ch_layout_combo_ = new ChannelLayoutComboBox(); + output_ch_layout_combo_->SetChannelLayout( + OLIVE_CONFIG("AudioOutputChannelLayout").toULongLong()); + output_param_layout->addWidget(output_ch_layout_combo_, + output_row, 1); - output_row++; + output_row++; - output_param_layout->addWidget(new QLabel(tr("Sample Format:")), output_row, 0); + output_param_layout->addWidget(new QLabel(tr("Sample Format:")), + output_row, 0); - output_fmt_combo_ = new SampleFormatComboBox(); - output_fmt_combo_->SetPackedFormats(); - output_fmt_combo_->SetSampleFormat(SampleFormat::from_string(OLIVE_CONFIG("AudioOutputSampleFormat").toString().toStdString())); - output_param_layout->addWidget(output_fmt_combo_, output_row, 1); - } - } + output_fmt_combo_ = new SampleFormatComboBox(); + output_fmt_combo_->SetPackedFormats(); + output_fmt_combo_->SetSampleFormat(SampleFormat::from_string( + OLIVE_CONFIG("AudioOutputSampleFormat") + .toString() + .toStdString())); + output_param_layout->addWidget(output_fmt_combo_, output_row, + 1); + } + } - row = 0; + row = 0; - { - QGroupBox* input_group = new QGroupBox(); - input_group->setTitle(tr("Input")); - layout->addWidget(input_group); + { + QGroupBox *input_group = new QGroupBox(); + input_group->setTitle(tr("Input")); + layout->addWidget(input_group); - QGridLayout* input_layout = new QGridLayout(input_group); + QGridLayout *input_layout = new QGridLayout(input_group); - input_layout->addWidget(new QLabel(tr("Device:")), row, 0); + input_layout->addWidget(new QLabel(tr("Device:")), row, 0); - audio_input_devices_ = new QComboBox(); - input_layout->addWidget(audio_input_devices_, row, 1); + audio_input_devices_ = new QComboBox(); + input_layout->addWidget(audio_input_devices_, row, 1); - row++; + row++; - QGroupBox *recording_group = new QGroupBox(tr("Recording")); - input_layout->addWidget(recording_group, row, 0, 1, 2); + QGroupBox *recording_group = new QGroupBox(tr("Recording")); + input_layout->addWidget(recording_group, row, 0, 1, 2); - QVBoxLayout *recording_layout = new QVBoxLayout(recording_group); + QVBoxLayout *recording_layout = new QVBoxLayout(recording_group); - QHBoxLayout *fmt_layout = new QHBoxLayout(); - recording_layout->addLayout(fmt_layout); + QHBoxLayout *fmt_layout = new QHBoxLayout(); + recording_layout->addLayout(fmt_layout); - fmt_layout->addWidget(new QLabel(tr("Format:"))); + fmt_layout->addWidget(new QLabel(tr("Format:"))); - record_format_combo_ = new ExportFormatComboBox(ExportFormatComboBox::kShowAudioOnly); - record_format_combo_->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); - record_format_combo_->SetFormat(static_cast(OLIVE_CONFIG("AudioRecordingFormat").toInt())); - fmt_layout->addWidget(record_format_combo_); + record_format_combo_ = + new ExportFormatComboBox(ExportFormatComboBox::kShowAudioOnly); + record_format_combo_->setSizePolicy(QSizePolicy::Expanding, + QSizePolicy::Expanding); + record_format_combo_->SetFormat(static_cast( + OLIVE_CONFIG("AudioRecordingFormat").toInt())); + fmt_layout->addWidget(record_format_combo_); - record_options_ = new ExportAudioTab(); - record_options_->SetFormat(record_format_combo_->GetFormat()); - record_options_->SetCodec(static_cast(OLIVE_CONFIG("AudioRecordingCodec").toInt())); - record_options_->sample_rate_combobox()->SetSampleRate(OLIVE_CONFIG("AudioRecordingSampleRate").toInt()); - record_options_->channel_layout_combobox()->SetChannelLayout(OLIVE_CONFIG("AudioRecordingChannelLayout").toULongLong()); - record_options_->bit_rate_slider()->SetValue(OLIVE_CONFIG("AudioRecordingBitRate").toInt()); - record_options_->sample_format_combobox()->SetSampleFormat(SampleFormat::from_string(OLIVE_CONFIG("AudioRecordingSampleFormat").toString().toStdString())); - recording_layout->addWidget(record_options_); + record_options_ = new ExportAudioTab(); + record_options_->SetFormat(record_format_combo_->GetFormat()); + record_options_->SetCodec(static_cast( + OLIVE_CONFIG("AudioRecordingCodec").toInt())); + record_options_->sample_rate_combobox()->SetSampleRate( + OLIVE_CONFIG("AudioRecordingSampleRate").toInt()); + record_options_->channel_layout_combobox()->SetChannelLayout( + OLIVE_CONFIG("AudioRecordingChannelLayout").toULongLong()); + record_options_->bit_rate_slider()->SetValue( + OLIVE_CONFIG("AudioRecordingBitRate").toInt()); + record_options_->sample_format_combobox()->SetSampleFormat( + SampleFormat::from_string( + OLIVE_CONFIG("AudioRecordingSampleFormat") + .toString() + .toStdString())); + recording_layout->addWidget(record_options_); - connect(record_format_combo_, &ExportFormatComboBox::FormatChanged, record_options_, &ExportAudioTab::SetFormat); - } + connect(record_format_combo_, &ExportFormatComboBox::FormatChanged, + record_options_, &ExportAudioTab::SetFormat); + } - QHBoxLayout* refresh_layout = new QHBoxLayout(); - layout->addLayout(refresh_layout); - refresh_layout->addStretch(); + QHBoxLayout *refresh_layout = new QHBoxLayout(); + layout->addLayout(refresh_layout); + refresh_layout->addStretch(); - refresh_devices_btn_ = new QPushButton(tr("Refresh Devices")); - refresh_layout->addWidget(refresh_devices_btn_); + refresh_devices_btn_ = new QPushButton(tr("Refresh Devices")); + refresh_layout->addWidget(refresh_devices_btn_); - connect(refresh_devices_btn_, &QPushButton::clicked, this, &PreferencesAudioTab::HardRefreshBackends); - } + connect(refresh_devices_btn_, &QPushButton::clicked, this, + &PreferencesAudioTab::HardRefreshBackends); + } - audio_tab_layout->addStretch(); + audio_tab_layout->addStretch(); - // Populate lists - RefreshBackends(); + // Populate lists + RefreshBackends(); } void PreferencesAudioTab::Accept(MultiUndoCommand *command) { - Q_UNUSED(command) + Q_UNUSED(command) - // Get device indexes - PaDeviceIndex output_device = audio_output_devices_->currentData().value(); - PaDeviceIndex input_device = audio_input_devices_->currentData().value(); + // Get device indexes + PaDeviceIndex output_device = + audio_output_devices_->currentData().value(); + PaDeviceIndex input_device = + audio_input_devices_->currentData().value(); - // Get device names, which seem to be the closest thing we have to a "unique identifier" for them - OLIVE_CONFIG("AudioOutput") = audio_output_devices_->currentText(); - OLIVE_CONFIG("AudioInput") = audio_input_devices_->currentText(); + // Get device names, which seem to be the closest thing we have to a "unique identifier" for them + OLIVE_CONFIG("AudioOutput") = audio_output_devices_->currentText(); + OLIVE_CONFIG("AudioInput") = audio_input_devices_->currentText(); - // Set devices to be used from now on - AudioManager::instance()->SetOutputDevice(output_device); - AudioManager::instance()->SetInputDevice(input_device); + // Set devices to be used from now on + AudioManager::instance()->SetOutputDevice(output_device); + AudioManager::instance()->SetInputDevice(input_device); - OLIVE_CONFIG("AudioOutputSampleRate") = output_rate_combo_->GetSampleRate(); - OLIVE_CONFIG("AudioOutputChannelLayout") = QVariant::fromValue(output_ch_layout_combo_->GetChannelLayout()); - OLIVE_CONFIG("AudioOutputSampleFormat") = QString::fromStdString(output_fmt_combo_->GetSampleFormat().to_string()); + OLIVE_CONFIG("AudioOutputSampleRate") = output_rate_combo_->GetSampleRate(); + OLIVE_CONFIG("AudioOutputChannelLayout") = + QVariant::fromValue(output_ch_layout_combo_->GetChannelLayout()); + OLIVE_CONFIG("AudioOutputSampleFormat") = QString::fromStdString( + output_fmt_combo_->GetSampleFormat().to_string()); - OLIVE_CONFIG("AudioRecordingFormat") = record_format_combo_->GetFormat(); - OLIVE_CONFIG("AudioRecordingCodec") = record_options_->GetCodec(); - OLIVE_CONFIG("AudioRecordingSampleRate") = record_options_->sample_rate_combobox()->GetSampleRate(); - OLIVE_CONFIG("AudioRecordingChannelLayout") = QVariant::fromValue(record_options_->channel_layout_combobox()->GetChannelLayout()); - OLIVE_CONFIG("AudioRecordingBitRate") = QVariant::fromValue(record_options_->bit_rate_slider()->GetValue()); - OLIVE_CONFIG("AudioRecordingSampleFormat") = QString::fromStdString(record_options_->sample_format_combobox()->GetSampleFormat().to_string()); + OLIVE_CONFIG("AudioRecordingFormat") = record_format_combo_->GetFormat(); + OLIVE_CONFIG("AudioRecordingCodec") = record_options_->GetCodec(); + OLIVE_CONFIG("AudioRecordingSampleRate") = + record_options_->sample_rate_combobox()->GetSampleRate(); + OLIVE_CONFIG("AudioRecordingChannelLayout") = QVariant::fromValue( + record_options_->channel_layout_combobox()->GetChannelLayout()); + OLIVE_CONFIG("AudioRecordingBitRate") = + QVariant::fromValue(record_options_->bit_rate_slider()->GetValue()); + OLIVE_CONFIG("AudioRecordingSampleFormat") = + QString::fromStdString(record_options_->sample_format_combobox() + ->GetSampleFormat() + .to_string()); - emit AudioManager::instance()->OutputParamsChanged(); + emit AudioManager::instance() -> OutputParamsChanged(); } void PreferencesAudioTab::RefreshBackends() { - audio_backend_combobox_->clear(); - for (PaHostApiIndex i=0, end=Pa_GetHostApiCount(); iclear(); + for (PaHostApiIndex i = 0, end = Pa_GetHostApiCount(); i < end; i++) { + const PaHostApiInfo *info = Pa_GetHostApiInfo(i); - audio_backend_combobox_->addItem(info->name); - } + audio_backend_combobox_->addItem(info->name); + } - RefreshDevices(); + RefreshDevices(); - AttemptToSetDevicesFromConfig(); + AttemptToSetDevicesFromConfig(); } void PreferencesAudioTab::RefreshDevices() { - if (audio_backend_combobox_->count() == 0) { - return; - } + if (audio_backend_combobox_->count() == 0) { + return; + } - PaHostApiIndex host_index = audio_backend_combobox_->currentIndex(); - const PaHostApiInfo *host = Pa_GetHostApiInfo(host_index); + PaHostApiIndex host_index = audio_backend_combobox_->currentIndex(); + const PaHostApiInfo *host = Pa_GetHostApiInfo(host_index); - audio_output_devices_->clear(); - audio_input_devices_->clear(); + audio_output_devices_->clear(); + audio_input_devices_->clear(); - for (int i=0; ideviceCount; i++) { - PaDeviceIndex device_index = Pa_HostApiDeviceIndexToDeviceIndex(host_index, i); - const PaDeviceInfo *device = Pa_GetDeviceInfo(device_index); + for (int i = 0; i < host->deviceCount; i++) { + PaDeviceIndex device_index = + Pa_HostApiDeviceIndexToDeviceIndex(host_index, i); + const PaDeviceInfo *device = Pa_GetDeviceInfo(device_index); - if (device->maxOutputChannels) { - audio_output_devices_->addItem(device->name, device_index); - } + if (device->maxOutputChannels) { + audio_output_devices_->addItem(device->name, device_index); + } - if (device->maxInputChannels) { - audio_input_devices_->addItem(device->name, device_index); - } - } + if (device->maxInputChannels) { + audio_input_devices_->addItem(device->name, device_index); + } + } } void PreferencesAudioTab::HardRefreshBackends() { - AudioManager::instance()->HardReset(); - RefreshBackends(); + AudioManager::instance()->HardReset(); + RefreshBackends(); } void PreferencesAudioTab::AttemptToSetDevicesFromConfig() { - // Load with currently active devices - PaDeviceIndex current_output_index = AudioManager::instance()->GetOutputDevice(); - PaDeviceIndex current_input_index = AudioManager::instance()->GetInputDevice(); + // Load with currently active devices + PaDeviceIndex current_output_index = + AudioManager::instance()->GetOutputDevice(); + PaDeviceIndex current_input_index = + AudioManager::instance()->GetInputDevice(); - const PaDeviceInfo *current_output = nullptr, *current_input = nullptr; - if (current_output_index != paNoDevice) { - current_output = Pa_GetDeviceInfo(current_output_index); - } - if (current_input_index != paNoDevice) { - current_input = Pa_GetDeviceInfo(current_input_index); - } + const PaDeviceInfo *current_output = nullptr, *current_input = nullptr; + if (current_output_index != paNoDevice) { + current_output = Pa_GetDeviceInfo(current_output_index); + } + if (current_input_index != paNoDevice) { + current_input = Pa_GetDeviceInfo(current_input_index); + } - if (current_output || current_input) { - PaHostApiIndex host = current_output ? current_output->hostApi : current_input->hostApi; + if (current_output || current_input) { + PaHostApiIndex host = current_output ? current_output->hostApi : + current_input->hostApi; - // Set backend accordingly - audio_backend_combobox_->setCurrentIndex(host); + // Set backend accordingly + audio_backend_combobox_->setCurrentIndex(host); - // Device comboboxes should be populated correctly now - if (current_output) { - audio_output_devices_->setCurrentText(current_output->name); - } + // Device comboboxes should be populated correctly now + if (current_output) { + audio_output_devices_->setCurrentText(current_output->name); + } - if (current_input) { - audio_input_devices_->setCurrentText(current_input->name); - } - } + if (current_input) { + audio_input_devices_->setCurrentText(current_input->name); + } + } } } diff --git a/app/dialog/preferences/tabs/preferencesaudiotab.h b/app/dialog/preferences/tabs/preferencesaudiotab.h index 05ca231e8..2d8cd3f6d 100644 --- a/app/dialog/preferences/tabs/preferencesaudiotab.h +++ b/app/dialog/preferences/tabs/preferencesaudiotab.h @@ -28,56 +28,55 @@ #include "dialog/export/exportaudiotab.h" #include "dialog/export/exportformatcombobox.h" -namespace olive { - -class PreferencesAudioTab : public ConfigDialogBaseTab +namespace olive { - Q_OBJECT -public: - PreferencesAudioTab(); - virtual void Accept(MultiUndoCommand* command) override; +class PreferencesAudioTab : public ConfigDialogBaseTab { + Q_OBJECT +public: + PreferencesAudioTab(); + + virtual void Accept(MultiUndoCommand *command) override; private: - QComboBox* audio_backend_combobox_; + QComboBox *audio_backend_combobox_; - /** + /** * @brief UI widget for selecting the output audio device */ - QComboBox* audio_output_devices_; + QComboBox *audio_output_devices_; - /** + /** * @brief UI widget for selecting the input audio device */ - QComboBox* audio_input_devices_; + QComboBox *audio_input_devices_; - /** + /** * @brief UI widget for editing the recording channels */ - QComboBox* recording_combobox_; + QComboBox *recording_combobox_; - /** + /** * @brief Button that triggers a refresh of the available audio devices */ - QPushButton* refresh_devices_btn_; + QPushButton *refresh_devices_btn_; - SampleRateComboBox *output_rate_combo_; - ChannelLayoutComboBox *output_ch_layout_combo_; - SampleFormatComboBox *output_fmt_combo_; + SampleRateComboBox *output_rate_combo_; + ChannelLayoutComboBox *output_ch_layout_combo_; + SampleFormatComboBox *output_fmt_combo_; - ExportFormatComboBox *record_format_combo_; + ExportFormatComboBox *record_format_combo_; - ExportAudioTab *record_options_; + ExportAudioTab *record_options_; private slots: - void RefreshBackends(); + void RefreshBackends(); - void RefreshDevices(); + void RefreshDevices(); - void HardRefreshBackends(); - - void AttemptToSetDevicesFromConfig(); + void HardRefreshBackends(); + void AttemptToSetDevicesFromConfig(); }; } diff --git a/app/dialog/preferences/tabs/preferencesbehaviortab.cpp b/app/dialog/preferences/tabs/preferencesbehaviortab.cpp index ad184c7d1..7145de636 100644 --- a/app/dialog/preferences/tabs/preferencesbehaviortab.cpp +++ b/app/dialog/preferences/tabs/preferencesbehaviortab.cpp @@ -25,143 +25,140 @@ #include "config/config.h" -namespace olive { +namespace olive +{ PreferencesBehaviorTab::PreferencesBehaviorTab() { - QVBoxLayout* layout = new QVBoxLayout(this); + QVBoxLayout *layout = new QVBoxLayout(this); - behavior_tree_ = new QTreeWidget(); - layout->addWidget(behavior_tree_); + behavior_tree_ = new QTreeWidget(); + layout->addWidget(behavior_tree_); - behavior_tree_->setHeaderLabel(tr("Behavior")); + behavior_tree_->setHeaderLabel(tr("Behavior")); - QTreeWidgetItem* general_group = AddParent(tr("General")); - AddItem(tr("Enable hover focus"), - QStringLiteral("HoverFocus"), - tr("Panels will be considered focused when the mouse cursor is over them without having to click them."), - general_group); - AddItem(tr("Enable slider ladder"), - QStringLiteral("UseSliderLadders"), - general_group); - AddItem(tr("Scrolling zooms by default"), - QStringLiteral("ScrollZooms"), - tr("By default, scrolling will move the view around, and holding Ctrl/Cmd will make it zoom instead. " - "Enabling this will switch those, scrolling will zoom by default, and holding Ctrl/Cmd will move the view instead."), - general_group); + QTreeWidgetItem *general_group = AddParent(tr("General")); + AddItem( + tr("Enable hover focus"), QStringLiteral("HoverFocus"), + tr("Panels will be considered focused when the mouse cursor is over them without having to click them."), + general_group); + AddItem(tr("Enable slider ladder"), QStringLiteral("UseSliderLadders"), + general_group); + AddItem( + tr("Scrolling zooms by default"), QStringLiteral("ScrollZooms"), + tr("By default, scrolling will move the view around, and holding Ctrl/Cmd will make it zoom instead. " + "Enabling this will switch those, scrolling will zoom by default, and holding Ctrl/Cmd will move the view instead."), + general_group); - QTreeWidgetItem* audio_group = AddParent(tr("Audio")); - AddItem(tr("Enable audio scrubbing"), - QStringLiteral("AudioScrubbing"), - audio_group); + QTreeWidgetItem *audio_group = AddParent(tr("Audio")); + AddItem(tr("Enable audio scrubbing"), QStringLiteral("AudioScrubbing"), + audio_group); - QTreeWidgetItem* timeline_group = AddParent(tr("Timeline")); - AddItem(tr("Auto-Seek to Imported Clips"), - QStringLiteral("EnableSeekToImport"), - timeline_group); - AddItem(tr("Edit Tool Also Seeks"), - QStringLiteral("EditToolAlsoSeeks"), - timeline_group); - AddItem(tr("Edit Tool Selects Links"), - QStringLiteral("EditToolSelectsLinks"), - timeline_group); - AddItem(tr("Enable Drag Files to Timeline"), - QStringLiteral("EnableDragFilesToTimeline"), - timeline_group); - AddItem(tr("Invert Timeline Scroll Axes"), - QStringLiteral("InvertTimelineScrollAxes"), - tr("Hold ALT on any UI element to switch scrolling axes"), - timeline_group); - AddItem(tr("Seek Also Selects"), - QStringLiteral("SeekAlsoSelects"), - timeline_group); - AddItem(tr("Seek to the End of Pastes"), - QStringLiteral("PasteSeeks"), - timeline_group); - AddItem(tr("Selecting Also Seeks"), - QStringLiteral("SelectAlsoSeeks"), - timeline_group); + QTreeWidgetItem *timeline_group = AddParent(tr("Timeline")); + AddItem(tr("Auto-Seek to Imported Clips"), + QStringLiteral("EnableSeekToImport"), timeline_group); + AddItem(tr("Edit Tool Also Seeks"), QStringLiteral("EditToolAlsoSeeks"), + timeline_group); + AddItem(tr("Edit Tool Selects Links"), + QStringLiteral("EditToolSelectsLinks"), timeline_group); + AddItem(tr("Enable Drag Files to Timeline"), + QStringLiteral("EnableDragFilesToTimeline"), timeline_group); + AddItem(tr("Invert Timeline Scroll Axes"), + QStringLiteral("InvertTimelineScrollAxes"), + tr("Hold ALT on any UI element to switch scrolling axes"), + timeline_group); + AddItem(tr("Seek Also Selects"), QStringLiteral("SeekAlsoSelects"), + timeline_group); + AddItem(tr("Seek to the End of Pastes"), QStringLiteral("PasteSeeks"), + timeline_group); + AddItem(tr("Selecting Also Seeks"), QStringLiteral("SelectAlsoSeeks"), + timeline_group); - QTreeWidgetItem* playback_group = AddParent(tr("Playback")); - AddItem(tr("Ask For Name When Setting Marker"), - QStringLiteral("SetNameWithMarker"), - playback_group); - AddItem(tr("Automatically rewind at the end of a sequence"), - QStringLiteral("AutoSeekToBeginning"), - playback_group); + QTreeWidgetItem *playback_group = AddParent(tr("Playback")); + AddItem(tr("Ask For Name When Setting Marker"), + QStringLiteral("SetNameWithMarker"), playback_group); + AddItem(tr("Automatically rewind at the end of a sequence"), + QStringLiteral("AutoSeekToBeginning"), playback_group); - QTreeWidgetItem* project_group = AddParent(tr("Project")); - AddItem(tr("Drop Files on Media to Replace"), - QStringLiteral("DropFileOnMediaToReplace"), - project_group); + QTreeWidgetItem *project_group = AddParent(tr("Project")); + AddItem(tr("Drop Files on Media to Replace"), + QStringLiteral("DropFileOnMediaToReplace"), project_group); - QTreeWidgetItem* node_group = AddParent(tr("Nodes")); - AddItem(tr("Add Default Effects to New Clips"), - QStringLiteral("AddDefaultEffectsToClips"), - node_group); - AddItem(tr("Auto-Scale By Default"), - QStringLiteral("AutoscaleByDefault"), - node_group); - AddItem(tr("Splitting Clips Copies Dependencies"), - QStringLiteral("SplitClipsCopyNodes"), - tr("Multiple clips can share the same nodes. Disable this to automatically share node " - "dependencies among clips when copying or splitting them."), - node_group); + QTreeWidgetItem *node_group = AddParent(tr("Nodes")); + AddItem(tr("Add Default Effects to New Clips"), + QStringLiteral("AddDefaultEffectsToClips"), node_group); + AddItem(tr("Auto-Scale By Default"), QStringLiteral("AutoscaleByDefault"), + node_group); + AddItem( + tr("Splitting Clips Copies Dependencies"), + QStringLiteral("SplitClipsCopyNodes"), + tr("Multiple clips can share the same nodes. Disable this to automatically share node " + "dependencies among clips when copying or splitting them."), + node_group); - QTreeWidgetItem* opengl_group = AddParent(tr("OpenGL")); - AddItem(tr("Use glFinish"), - QStringLiteral("UseGLFinish"), - opengl_group); + QTreeWidgetItem *opengl_group = AddParent(tr("OpenGL")); + AddItem(tr("Use glFinish"), QStringLiteral("UseGLFinish"), opengl_group); } void PreferencesBehaviorTab::Accept(MultiUndoCommand *command) { - Q_UNUSED(command) + Q_UNUSED(command) - for (auto iterator=config_map_.begin();iterator!=config_map_.end();iterator++) { - OLIVE_CONFIG_STR(iterator.value()) = (iterator.key()->checkState(0) == Qt::Checked); - } + for (auto iterator = config_map_.begin(); iterator != config_map_.end(); + iterator++) { + OLIVE_CONFIG_STR(iterator.value()) = + (iterator.key()->checkState(0) == Qt::Checked); + } } -QTreeWidgetItem* PreferencesBehaviorTab::AddItem(const QString &text, const QString &config_key, const QString& tooltip, QTreeWidgetItem* parent) +QTreeWidgetItem *PreferencesBehaviorTab::AddItem(const QString &text, + const QString &config_key, + const QString &tooltip, + QTreeWidgetItem *parent) { - QTreeWidgetItem* item = new QTreeWidgetItem({text}); - item->setToolTip(0, tooltip); - item->setCheckState(0, OLIVE_CONFIG_STR(config_key).toBool() ? Qt::Checked : Qt::Unchecked); + QTreeWidgetItem *item = new QTreeWidgetItem({ text }); + item->setToolTip(0, tooltip); + item->setCheckState( + 0, OLIVE_CONFIG_STR(config_key).toBool() ? Qt::Checked : Qt::Unchecked); - config_map_.insert(item, config_key); + config_map_.insert(item, config_key); - if (parent) { - parent->addChild(item); - } else { - behavior_tree_->addTopLevelItem(item); - } + if (parent) { + parent->addChild(item); + } else { + behavior_tree_->addTopLevelItem(item); + } - return item; + return item; } -QTreeWidgetItem *PreferencesBehaviorTab::AddItem(const QString &text, const QString &config_key, QTreeWidgetItem *parent) +QTreeWidgetItem *PreferencesBehaviorTab::AddItem(const QString &text, + const QString &config_key, + QTreeWidgetItem *parent) { - return AddItem(text, config_key, QString(), parent); + return AddItem(text, config_key, QString(), parent); } -QTreeWidgetItem *PreferencesBehaviorTab::AddParent(const QString &text, const QString &tooltip, QTreeWidgetItem *parent) +QTreeWidgetItem *PreferencesBehaviorTab::AddParent(const QString &text, + const QString &tooltip, + QTreeWidgetItem *parent) { - QTreeWidgetItem* item = new QTreeWidgetItem({text}); - item->setToolTip(0, tooltip); + QTreeWidgetItem *item = new QTreeWidgetItem({ text }); + item->setToolTip(0, tooltip); - if (parent) { - parent->addChild(item); - } else { - behavior_tree_->addTopLevelItem(item); - } + if (parent) { + parent->addChild(item); + } else { + behavior_tree_->addTopLevelItem(item); + } - return item; + return item; } -QTreeWidgetItem *PreferencesBehaviorTab::AddParent(const QString &text, QTreeWidgetItem *parent) +QTreeWidgetItem *PreferencesBehaviorTab::AddParent(const QString &text, + QTreeWidgetItem *parent) { - return AddParent(text, QString(), parent); + return AddParent(text, QString(), parent); } } diff --git a/app/dialog/preferences/tabs/preferencesbehaviortab.h b/app/dialog/preferences/tabs/preferencesbehaviortab.h index a1a9558ce..a79c3c973 100644 --- a/app/dialog/preferences/tabs/preferencesbehaviortab.h +++ b/app/dialog/preferences/tabs/preferencesbehaviortab.h @@ -25,27 +25,30 @@ #include "dialog/configbase/configdialogbase.h" -namespace olive { - -class PreferencesBehaviorTab : public ConfigDialogBaseTab +namespace olive { - Q_OBJECT -public: - PreferencesBehaviorTab(); - virtual void Accept(MultiUndoCommand* command) override; +class PreferencesBehaviorTab : public ConfigDialogBaseTab { + Q_OBJECT +public: + PreferencesBehaviorTab(); + + virtual void Accept(MultiUndoCommand *command) override; private: - QTreeWidgetItem *AddParent(const QString& text, const QString &tooltip, QTreeWidgetItem *parent = nullptr); - QTreeWidgetItem *AddParent(const QString& text, QTreeWidgetItem *parent = nullptr); + QTreeWidgetItem *AddParent(const QString &text, const QString &tooltip, + QTreeWidgetItem *parent = nullptr); + QTreeWidgetItem *AddParent(const QString &text, + QTreeWidgetItem *parent = nullptr); - QTreeWidgetItem *AddItem(const QString& text, const QString& config_key, const QString &tooltip, QTreeWidgetItem *parent ); - QTreeWidgetItem *AddItem(const QString& text, const QString& config_key, QTreeWidgetItem *parent); + QTreeWidgetItem *AddItem(const QString &text, const QString &config_key, + const QString &tooltip, QTreeWidgetItem *parent); + QTreeWidgetItem *AddItem(const QString &text, const QString &config_key, + QTreeWidgetItem *parent); - QMap config_map_; - - QTreeWidget* behavior_tree_; + QMap config_map_; + QTreeWidget *behavior_tree_; }; } diff --git a/app/dialog/preferences/tabs/preferencesdisktab.cpp b/app/dialog/preferences/tabs/preferencesdisktab.cpp index 8aea10aab..cc04af3aa 100644 --- a/app/dialog/preferences/tabs/preferencesdisktab.cpp +++ b/app/dialog/preferences/tabs/preferencesdisktab.cpp @@ -29,94 +29,105 @@ #include "common/filefunctions.h" -namespace olive { +namespace olive +{ PreferencesDiskTab::PreferencesDiskTab() { - // Get default disk cache folder - default_disk_cache_folder_ = DiskManager::instance()->GetDefaultCacheFolder(); + // Get default disk cache folder + default_disk_cache_folder_ = + DiskManager::instance()->GetDefaultCacheFolder(); - QVBoxLayout* outer_layout = new QVBoxLayout(this); + QVBoxLayout *outer_layout = new QVBoxLayout(this); - QGroupBox* disk_management_group = new QGroupBox(tr("Disk Management")); - outer_layout->addWidget(disk_management_group); + QGroupBox *disk_management_group = new QGroupBox(tr("Disk Management")); + outer_layout->addWidget(disk_management_group); - QGridLayout* disk_management_layout = new QGridLayout(disk_management_group); + QGridLayout *disk_management_layout = + new QGridLayout(disk_management_group); - int row = 0; + int row = 0; - disk_management_layout->addWidget(new QLabel(tr("Disk Cache Location:")), row, 0); + disk_management_layout->addWidget(new QLabel(tr("Disk Cache Location:")), + row, 0); - disk_cache_location_ = new PathWidget(default_disk_cache_folder_->GetPath()); - disk_management_layout->addWidget(disk_cache_location_, row, 1); + disk_cache_location_ = + new PathWidget(default_disk_cache_folder_->GetPath()); + disk_management_layout->addWidget(disk_cache_location_, row, 1); - row++; + row++; - QPushButton* disk_cache_settings_btn = new QPushButton(tr("Disk Cache Settings")); - connect(disk_cache_settings_btn, &QPushButton::clicked, this, [this](){ - DiskManager::instance()->ShowDiskCacheSettingsDialog(disk_cache_location_->text(), this); - }); - disk_management_layout->addWidget(disk_cache_settings_btn, row, 1); + QPushButton *disk_cache_settings_btn = + new QPushButton(tr("Disk Cache Settings")); + connect(disk_cache_settings_btn, &QPushButton::clicked, this, [this]() { + DiskManager::instance()->ShowDiskCacheSettingsDialog( + disk_cache_location_->text(), this); + }); + disk_management_layout->addWidget(disk_cache_settings_btn, row, 1); - row++; + row++; - QGroupBox* cache_behavior = new QGroupBox(tr("Cache Behavior")); - outer_layout->addWidget(cache_behavior); - QGridLayout* cache_behavior_layout = new QGridLayout(cache_behavior); + QGroupBox *cache_behavior = new QGroupBox(tr("Cache Behavior")); + outer_layout->addWidget(cache_behavior); + QGridLayout *cache_behavior_layout = new QGridLayout(cache_behavior); - row = 0; + row = 0; - cache_behavior_layout->addWidget(new QLabel(tr("Cache Ahead:")), row, 0); + cache_behavior_layout->addWidget(new QLabel(tr("Cache Ahead:")), row, 0); - cache_ahead_slider_ = new FloatSlider(); - cache_ahead_slider_->SetFormat(tr("%1 seconds")); - cache_ahead_slider_->SetMinimum(0); - cache_ahead_slider_->SetValue(OLIVE_CONFIG("DiskCacheAhead").value().toDouble()); - cache_behavior_layout->addWidget(cache_ahead_slider_, row, 1); + cache_ahead_slider_ = new FloatSlider(); + cache_ahead_slider_->SetFormat(tr("%1 seconds")); + cache_ahead_slider_->SetMinimum(0); + cache_ahead_slider_->SetValue( + OLIVE_CONFIG("DiskCacheAhead").value().toDouble()); + cache_behavior_layout->addWidget(cache_ahead_slider_, row, 1); - cache_behavior_layout->addWidget(new QLabel(tr("Cache Behind:")), row, 2); + cache_behavior_layout->addWidget(new QLabel(tr("Cache Behind:")), row, 2); - cache_behind_slider_ = new FloatSlider(); - cache_behind_slider_->SetMinimum(0); - cache_behind_slider_->SetFormat(tr("%1 seconds")); - cache_behind_slider_->SetValue(OLIVE_CONFIG("DiskCacheBehind").value().toDouble()); - cache_behavior_layout->addWidget(cache_behind_slider_, row, 3); + cache_behind_slider_ = new FloatSlider(); + cache_behind_slider_->SetMinimum(0); + cache_behind_slider_->SetFormat(tr("%1 seconds")); + cache_behind_slider_->SetValue( + OLIVE_CONFIG("DiskCacheBehind").value().toDouble()); + cache_behavior_layout->addWidget(cache_behind_slider_, row, 3); - outer_layout->addStretch(); + outer_layout->addStretch(); } bool PreferencesDiskTab::Validate() { - if (disk_cache_location_->text() != default_disk_cache_folder_->GetPath()) { - // Disk cache location is changing + if (disk_cache_location_->text() != default_disk_cache_folder_->GetPath()) { + // Disk cache location is changing - // Check if the user is okay with invalidating the current cache - if (!DiskManager::ShowDiskCacheChangeConfirmationDialog(this)) { - return false; - } + // Check if the user is okay with invalidating the current cache + if (!DiskManager::ShowDiskCacheChangeConfirmationDialog(this)) { + return false; + } - // Check validity of the new path - if (!FileFunctions::DirectoryIsValid(disk_cache_location_->text())) { - QMessageBox::critical(this, - tr("Disk Cache"), - tr("Failed to set disk cache location. Access was denied.")); - return false; - } - } + // Check validity of the new path + if (!FileFunctions::DirectoryIsValid(disk_cache_location_->text())) { + QMessageBox::critical( + this, tr("Disk Cache"), + tr("Failed to set disk cache location. Access was denied.")); + return false; + } + } - return true; + return true; } void PreferencesDiskTab::Accept(MultiUndoCommand *command) { - Q_UNUSED(command) + Q_UNUSED(command) - if (disk_cache_location_->text() != default_disk_cache_folder_->GetPath()) { - default_disk_cache_folder_->SetPath(disk_cache_location_->text()); - } + if (disk_cache_location_->text() != default_disk_cache_folder_->GetPath()) { + default_disk_cache_folder_->SetPath(disk_cache_location_->text()); + } - OLIVE_CONFIG("DiskCacheBehind") = QVariant::fromValue(rational::fromDouble(cache_behind_slider_->GetValue())); - OLIVE_CONFIG("DiskCacheAhead") = QVariant::fromValue(rational::fromDouble(cache_ahead_slider_->GetValue())); + OLIVE_CONFIG("DiskCacheBehind") = QVariant::fromValue( + rational::fromDouble(cache_behind_slider_->GetValue())); + OLIVE_CONFIG("DiskCacheAhead") = QVariant::fromValue( + rational::fromDouble(cache_ahead_slider_->GetValue())); } } diff --git a/app/dialog/preferences/tabs/preferencesdisktab.h b/app/dialog/preferences/tabs/preferencesdisktab.h index 9d17420e7..7337fceac 100644 --- a/app/dialog/preferences/tabs/preferencesdisktab.h +++ b/app/dialog/preferences/tabs/preferencesdisktab.h @@ -30,27 +30,26 @@ #include "widget/slider/floatslider.h" #include "widget/path/pathwidget.h" -namespace olive { - -class PreferencesDiskTab : public ConfigDialogBaseTab +namespace olive { - Q_OBJECT + +class PreferencesDiskTab : public ConfigDialogBaseTab { + Q_OBJECT public: - PreferencesDiskTab(); + PreferencesDiskTab(); - virtual bool Validate() override; + virtual bool Validate() override; - virtual void Accept(MultiUndoCommand* command) override; + virtual void Accept(MultiUndoCommand *command) override; private: - PathWidget* disk_cache_location_; + PathWidget *disk_cache_location_; - FloatSlider* cache_ahead_slider_; + FloatSlider *cache_ahead_slider_; - FloatSlider* cache_behind_slider_; - - DiskCacheFolder* default_disk_cache_folder_; + FloatSlider *cache_behind_slider_; + DiskCacheFolder *default_disk_cache_folder_; }; } diff --git a/app/dialog/preferences/tabs/preferencesgeneraltab.cpp b/app/dialog/preferences/tabs/preferencesgeneraltab.cpp index 765e91dfe..0468f5203 100644 --- a/app/dialog/preferences/tabs/preferencesgeneraltab.cpp +++ b/app/dialog/preferences/tabs/preferencesgeneraltab.cpp @@ -30,162 +30,187 @@ #include "dialog/sequence/sequence.h" #include "node/project/sequence/sequence.h" -namespace olive { +namespace olive +{ PreferencesGeneralTab::PreferencesGeneralTab() { - QVBoxLayout* layout = new QVBoxLayout(this); + QVBoxLayout *layout = new QVBoxLayout(this); - { - QGroupBox* global_groupbox = new QGroupBox(tr("Locale")); - QGridLayout* global_layout = new QGridLayout(global_groupbox); - layout->addWidget(global_groupbox); + { + QGroupBox *global_groupbox = new QGroupBox(tr("Locale")); + QGridLayout *global_layout = new QGridLayout(global_groupbox); + layout->addWidget(global_groupbox); - int row = 0; + int row = 0; - // General -> Language - global_layout->addWidget(new QLabel(tr("Language:")), row, 0); + // General -> Language + global_layout->addWidget(new QLabel(tr("Language:")), row, 0); - language_combobox_ = new QComboBox(); + language_combobox_ = new QComboBox(); - // Add default language (en-US) - QDir language_dir(QStringLiteral(":/ts")); - QStringList languages = language_dir.entryList(); - foreach (const QString& l, languages) { - AddLanguage(l); - } + // Add default language (en-US) + QDir language_dir(QStringLiteral(":/ts")); + QStringList languages = language_dir.entryList(); + foreach (const QString &l, languages) { + AddLanguage(l); + } - QString current_language = OLIVE_CONFIG("Language").toString(); - if (current_language.isEmpty()) { - // No configured language, use system language - current_language = QLocale::system().name(); + QString current_language = OLIVE_CONFIG("Language").toString(); + if (current_language.isEmpty()) { + // No configured language, use system language + current_language = QLocale::system().name(); - // If we don't have a language for this, default to en_US - if (!languages.contains(current_language)) { - current_language = QStringLiteral("en_US"); - } - } - language_combobox_->setCurrentIndex(languages.indexOf(current_language)); + // If we don't have a language for this, default to en_US + if (!languages.contains(current_language)) { + current_language = QStringLiteral("en_US"); + } + } + language_combobox_->setCurrentIndex( + languages.indexOf(current_language)); - global_layout->addWidget(language_combobox_, row, 1); - } + global_layout->addWidget(language_combobox_, row, 1); + } - { - QGroupBox* timeline_groupbox = new QGroupBox(tr("Timeline")); - QGridLayout* timeline_layout = new QGridLayout(timeline_groupbox); - layout->addWidget(timeline_groupbox); + { + QGroupBox *timeline_groupbox = new QGroupBox(tr("Timeline")); + QGridLayout *timeline_layout = new QGridLayout(timeline_groupbox); + layout->addWidget(timeline_groupbox); - int row = 0; + int row = 0; - QLabel* autoscroll_lbl = new QLabel(tr("Auto-Scroll Method:")); - autoscroll_lbl->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); - timeline_layout->addWidget(autoscroll_lbl, row, 0); + QLabel *autoscroll_lbl = new QLabel(tr("Auto-Scroll Method:")); + autoscroll_lbl->setSizePolicy(QSizePolicy::Expanding, + QSizePolicy::Expanding); + timeline_layout->addWidget(autoscroll_lbl, row, 0); - // ComboBox indices match enum indices - autoscroll_method_ = new QComboBox(); - autoscroll_method_->addItem(tr("None"), AutoScroll::kNone); - autoscroll_method_->addItem(tr("Page Scrolling"), AutoScroll::kPage); - autoscroll_method_->addItem(tr("Smooth Scrolling"), AutoScroll::kSmooth); - autoscroll_method_->setCurrentIndex(OLIVE_CONFIG("Autoscroll").toInt()); - timeline_layout->addWidget(autoscroll_method_, row, 1); + // ComboBox indices match enum indices + autoscroll_method_ = new QComboBox(); + autoscroll_method_->addItem(tr("None"), AutoScroll::kNone); + autoscroll_method_->addItem(tr("Page Scrolling"), AutoScroll::kPage); + autoscroll_method_->addItem(tr("Smooth Scrolling"), + AutoScroll::kSmooth); + autoscroll_method_->setCurrentIndex(OLIVE_CONFIG("Autoscroll").toInt()); + timeline_layout->addWidget(autoscroll_method_, row, 1); - row++; + row++; - timeline_layout->addWidget(new QLabel(tr("Rectified Waveforms:")), row, 0); + timeline_layout->addWidget(new QLabel(tr("Rectified Waveforms:")), row, + 0); - rectified_waveforms_ = new QCheckBox(); - rectified_waveforms_->setChecked(OLIVE_CONFIG("RectifiedWaveforms").toBool()); - timeline_layout->addWidget(rectified_waveforms_, row, 1); + rectified_waveforms_ = new QCheckBox(); + rectified_waveforms_->setChecked( + OLIVE_CONFIG("RectifiedWaveforms").toBool()); + timeline_layout->addWidget(rectified_waveforms_, row, 1); - row++; + row++; - timeline_layout->addWidget(new QLabel(tr("Default Still Image Length:")), row, 0); + timeline_layout->addWidget( + new QLabel(tr("Default Still Image Length:")), row, 0); - default_still_length_ = new RationalSlider(); - default_still_length_->SetMinimum(rational(100, 1000)); - default_still_length_->SetTimebase(rational(100, 1000)); - default_still_length_->SetFormat(tr("%1 seconds")); - default_still_length_->SetValue(OLIVE_CONFIG("DefaultStillLength").value()); - timeline_layout->addWidget(default_still_length_); - } + default_still_length_ = new RationalSlider(); + default_still_length_->SetMinimum(rational(100, 1000)); + default_still_length_->SetTimebase(rational(100, 1000)); + default_still_length_->SetFormat(tr("%1 seconds")); + default_still_length_->SetValue( + OLIVE_CONFIG("DefaultStillLength").value()); + timeline_layout->addWidget(default_still_length_); + } - { - QGroupBox* autorecovery_groupbox = new QGroupBox(tr("Auto-Recovery")); - QGridLayout* autorecovery_layout = new QGridLayout(autorecovery_groupbox); - layout->addWidget(autorecovery_groupbox); + { + QGroupBox *autorecovery_groupbox = new QGroupBox(tr("Auto-Recovery")); + QGridLayout *autorecovery_layout = + new QGridLayout(autorecovery_groupbox); + layout->addWidget(autorecovery_groupbox); - int row = 0; + int row = 0; - autorecovery_layout->addWidget(new QLabel(tr("Enable Auto-Recovery:")), row, 0); + autorecovery_layout->addWidget(new QLabel(tr("Enable Auto-Recovery:")), + row, 0); - autorecovery_enabled_ = new QCheckBox(); - autorecovery_enabled_->setChecked(OLIVE_CONFIG("AutorecoveryEnabled").toBool()); - autorecovery_layout->addWidget(autorecovery_enabled_, row, 1); + autorecovery_enabled_ = new QCheckBox(); + autorecovery_enabled_->setChecked( + OLIVE_CONFIG("AutorecoveryEnabled").toBool()); + autorecovery_layout->addWidget(autorecovery_enabled_, row, 1); - row++; + row++; - autorecovery_layout->addWidget(new QLabel(tr("Auto-Recovery Interval:")), row, 0); + autorecovery_layout->addWidget( + new QLabel(tr("Auto-Recovery Interval:")), row, 0); - autorecovery_interval_ = new IntegerSlider(); - autorecovery_interval_->SetMinimum(1); - autorecovery_interval_->SetMaximum(60); - autorecovery_interval_->SetFormat(QT_TRANSLATE_N_NOOP("olive::SliderBase", "%n minute(s)"), true); - autorecovery_interval_->SetValue(OLIVE_CONFIG("AutorecoveryInterval").toLongLong()); - autorecovery_layout->addWidget(autorecovery_interval_, row, 1); + autorecovery_interval_ = new IntegerSlider(); + autorecovery_interval_->SetMinimum(1); + autorecovery_interval_->SetMaximum(60); + autorecovery_interval_->SetFormat( + QT_TRANSLATE_N_NOOP("olive::SliderBase", "%n minute(s)"), true); + autorecovery_interval_->SetValue( + OLIVE_CONFIG("AutorecoveryInterval").toLongLong()); + autorecovery_layout->addWidget(autorecovery_interval_, row, 1); - row++; + row++; - autorecovery_layout->addWidget(new QLabel(tr("Maximum Versions Per Project:")), row, 0); + autorecovery_layout->addWidget( + new QLabel(tr("Maximum Versions Per Project:")), row, 0); - autorecovery_maximum_ = new IntegerSlider(); - autorecovery_maximum_->SetMinimum(1); - autorecovery_maximum_->SetMaximum(1000); - autorecovery_maximum_->SetValue(OLIVE_CONFIG("AutorecoveryMaximum").toLongLong()); - autorecovery_layout->addWidget(autorecovery_maximum_, row, 1); + autorecovery_maximum_ = new IntegerSlider(); + autorecovery_maximum_->SetMinimum(1); + autorecovery_maximum_->SetMaximum(1000); + autorecovery_maximum_->SetValue( + OLIVE_CONFIG("AutorecoveryMaximum").toLongLong()); + autorecovery_layout->addWidget(autorecovery_maximum_, row, 1); - row++; + row++; - QPushButton* browse_autorecoveries = new QPushButton(tr("Browse Auto-Recoveries")); - connect(browse_autorecoveries, &QPushButton::clicked, Core::instance(), &Core::BrowseAutoRecoveries); - autorecovery_layout->addWidget(browse_autorecoveries, row, 1); - } + QPushButton *browse_autorecoveries = + new QPushButton(tr("Browse Auto-Recoveries")); + connect(browse_autorecoveries, &QPushButton::clicked, Core::instance(), + &Core::BrowseAutoRecoveries); + autorecovery_layout->addWidget(browse_autorecoveries, row, 1); + } - layout->addStretch(); + layout->addStretch(); } void PreferencesGeneralTab::Accept(MultiUndoCommand *command) { - Q_UNUSED(command) + Q_UNUSED(command) - OLIVE_CONFIG("RectifiedWaveforms") = rectified_waveforms_->isChecked(); + OLIVE_CONFIG("RectifiedWaveforms") = rectified_waveforms_->isChecked(); - OLIVE_CONFIG("Autoscroll") = autoscroll_method_->currentData(); + OLIVE_CONFIG("Autoscroll") = autoscroll_method_->currentData(); - OLIVE_CONFIG("DefaultStillLength") = QVariant::fromValue(default_still_length_->GetValue()); + OLIVE_CONFIG("DefaultStillLength") = + QVariant::fromValue(default_still_length_->GetValue()); - QString set_language = language_combobox_->currentData().toString(); - if (QLocale::system().name() == set_language) { - // Language is set to the system, assume this is effectively "auto" - set_language = QString(); - } + QString set_language = language_combobox_->currentData().toString(); + if (QLocale::system().name() == set_language) { + // Language is set to the system, assume this is effectively "auto" + set_language = QString(); + } - // If the language has changed, set it now - if (OLIVE_CONFIG("Language").toString() != set_language) { - OLIVE_CONFIG("Language") = set_language; - Core::instance()->SetLanguage(set_language.isEmpty() ? QLocale::system().name() : set_language); - } + // If the language has changed, set it now + if (OLIVE_CONFIG("Language").toString() != set_language) { + OLIVE_CONFIG("Language") = set_language; + Core::instance()->SetLanguage( + set_language.isEmpty() ? QLocale::system().name() : set_language); + } - OLIVE_CONFIG("AutorecoveryEnabled") = autorecovery_enabled_->isChecked(); - OLIVE_CONFIG("AutorecoveryInterval") = QVariant::fromValue(autorecovery_interval_->GetValue()); - OLIVE_CONFIG("AutorecoveryMaximum") = QVariant::fromValue(autorecovery_maximum_->GetValue()); - Core::instance()->SetAutorecoveryInterval(autorecovery_interval_->GetValue()); + OLIVE_CONFIG("AutorecoveryEnabled") = autorecovery_enabled_->isChecked(); + OLIVE_CONFIG("AutorecoveryInterval") = + QVariant::fromValue(autorecovery_interval_->GetValue()); + OLIVE_CONFIG("AutorecoveryMaximum") = + QVariant::fromValue(autorecovery_maximum_->GetValue()); + Core::instance()->SetAutorecoveryInterval( + autorecovery_interval_->GetValue()); } void PreferencesGeneralTab::AddLanguage(const QString &locale_name) { - language_combobox_->addItem(tr("%1 (%2)").arg(QLocale(locale_name).nativeLanguageName(), - locale_name));; - language_combobox_->setItemData(language_combobox_->count() - 1, locale_name); + language_combobox_->addItem(tr("%1 (%2)").arg( + QLocale(locale_name).nativeLanguageName(), locale_name)); + ; + language_combobox_->setItemData(language_combobox_->count() - 1, + locale_name); } } diff --git a/app/dialog/preferences/tabs/preferencesgeneraltab.h b/app/dialog/preferences/tabs/preferencesgeneraltab.h index b0d7988a1..60231bba7 100644 --- a/app/dialog/preferences/tabs/preferencesgeneraltab.h +++ b/app/dialog/preferences/tabs/preferencesgeneraltab.h @@ -30,33 +30,32 @@ #include "widget/slider/rationalslider.h" #include "widget/slider/integerslider.h" -namespace olive { - -class PreferencesGeneralTab : public ConfigDialogBaseTab +namespace olive { - Q_OBJECT -public: - PreferencesGeneralTab(); - virtual void Accept(MultiUndoCommand* command) override; +class PreferencesGeneralTab : public ConfigDialogBaseTab { + Q_OBJECT +public: + PreferencesGeneralTab(); + + virtual void Accept(MultiUndoCommand *command) override; private: - void AddLanguage(const QString& locale_name); + void AddLanguage(const QString &locale_name); - QComboBox* language_combobox_; + QComboBox *language_combobox_; - QComboBox* autoscroll_method_; + QComboBox *autoscroll_method_; - QCheckBox* rectified_waveforms_; + QCheckBox *rectified_waveforms_; - RationalSlider* default_still_length_; + RationalSlider *default_still_length_; - QCheckBox* autorecovery_enabled_; + QCheckBox *autorecovery_enabled_; - IntegerSlider* autorecovery_interval_; - - IntegerSlider* autorecovery_maximum_; + IntegerSlider *autorecovery_interval_; + IntegerSlider *autorecovery_maximum_; }; } diff --git a/app/dialog/preferences/tabs/preferenceskeyboardtab.cpp b/app/dialog/preferences/tabs/preferenceskeyboardtab.cpp index 37eab5abc..f6b9f0a0d 100644 --- a/app/dialog/preferences/tabs/preferenceskeyboardtab.cpp +++ b/app/dialog/preferences/tabs/preferenceskeyboardtab.cpp @@ -29,224 +29,250 @@ #include "window/mainwindow/mainwindow.h" -namespace olive { - -PreferencesKeyboardTab::PreferencesKeyboardTab(MainWindow *main_window) : - main_window_(main_window) +namespace olive { - QVBoxLayout* shortcut_layout = new QVBoxLayout(this); - QLineEdit* key_search_line = new QLineEdit(); - key_search_line->setPlaceholderText(tr("Search for action or shortcut")); - connect(key_search_line, SIGNAL(textChanged(const QString &)), this, SLOT(refine_shortcut_list(const QString &))); +PreferencesKeyboardTab::PreferencesKeyboardTab(MainWindow *main_window) + : main_window_(main_window) +{ + QVBoxLayout *shortcut_layout = new QVBoxLayout(this); - shortcut_layout->addWidget(key_search_line); + QLineEdit *key_search_line = new QLineEdit(); + key_search_line->setPlaceholderText(tr("Search for action or shortcut")); + connect(key_search_line, SIGNAL(textChanged(const QString &)), this, + SLOT(refine_shortcut_list(const QString &))); - keyboard_tree_ = new QTreeWidget(); - QTreeWidgetItem* tree_header = keyboard_tree_->headerItem(); - tree_header->setText(0, tr("Action")); - tree_header->setText(1, tr("Shortcut")); - shortcut_layout->addWidget(keyboard_tree_); + shortcut_layout->addWidget(key_search_line); - QHBoxLayout* reset_shortcut_layout = new QHBoxLayout(); + keyboard_tree_ = new QTreeWidget(); + QTreeWidgetItem *tree_header = keyboard_tree_->headerItem(); + tree_header->setText(0, tr("Action")); + tree_header->setText(1, tr("Shortcut")); + shortcut_layout->addWidget(keyboard_tree_); - QPushButton* import_shortcut_button = new QPushButton(tr("Import")); - reset_shortcut_layout->addWidget(import_shortcut_button); - connect(import_shortcut_button, SIGNAL(clicked(bool)), this, SLOT(load_shortcut_file())); + QHBoxLayout *reset_shortcut_layout = new QHBoxLayout(); - QPushButton* export_shortcut_button = new QPushButton(tr("Export")); - reset_shortcut_layout->addWidget(export_shortcut_button); - connect(export_shortcut_button, SIGNAL(clicked(bool)), this, SLOT(save_shortcut_file())); + QPushButton *import_shortcut_button = new QPushButton(tr("Import")); + reset_shortcut_layout->addWidget(import_shortcut_button); + connect(import_shortcut_button, SIGNAL(clicked(bool)), this, + SLOT(load_shortcut_file())); - reset_shortcut_layout->addStretch(); + QPushButton *export_shortcut_button = new QPushButton(tr("Export")); + reset_shortcut_layout->addWidget(export_shortcut_button); + connect(export_shortcut_button, SIGNAL(clicked(bool)), this, + SLOT(save_shortcut_file())); - QPushButton* reset_selected_shortcut_button = new QPushButton(tr("Reset Selected")); - reset_shortcut_layout->addWidget(reset_selected_shortcut_button); - connect(reset_selected_shortcut_button, SIGNAL(clicked(bool)), this, SLOT(reset_default_shortcut())); + reset_shortcut_layout->addStretch(); - QPushButton* reset_all_shortcut_button = new QPushButton(tr("Reset All")); - reset_shortcut_layout->addWidget(reset_all_shortcut_button); - connect(reset_all_shortcut_button, SIGNAL(clicked(bool)), this, SLOT(reset_all_shortcuts())); + QPushButton *reset_selected_shortcut_button = + new QPushButton(tr("Reset Selected")); + reset_shortcut_layout->addWidget(reset_selected_shortcut_button); + connect(reset_selected_shortcut_button, SIGNAL(clicked(bool)), this, + SLOT(reset_default_shortcut())); - shortcut_layout->addLayout(reset_shortcut_layout); + QPushButton *reset_all_shortcut_button = new QPushButton(tr("Reset All")); + reset_shortcut_layout->addWidget(reset_all_shortcut_button); + connect(reset_all_shortcut_button, SIGNAL(clicked(bool)), this, + SLOT(reset_all_shortcuts())); - setup_kbd_shortcuts(main_window_->menuBar()); + shortcut_layout->addLayout(reset_shortcut_layout); + + setup_kbd_shortcuts(main_window_->menuBar()); } void PreferencesKeyboardTab::Accept(MultiUndoCommand *command) { - Q_UNUSED(command) + Q_UNUSED(command) - // Save keyboard shortcuts - for (int i=0;iset_action_shortcut(); - } + // Save keyboard shortcuts + for (int i = 0; i < key_shortcut_fields_.size(); i++) { + key_shortcut_fields_.at(i)->set_action_shortcut(); + } - main_window_->SaveLayout(); + main_window_->SaveLayout(); } -void PreferencesKeyboardTab::setup_kbd_shortcuts(QMenuBar* menubar) { - QList menus = menubar->actions(); +void PreferencesKeyboardTab::setup_kbd_shortcuts(QMenuBar *menubar) +{ + QList menus = menubar->actions(); - for (int i=0;imenu(); + for (int i = 0; i < menus.size(); i++) { + QMenu *menu = menus.at(i)->menu(); - QTreeWidgetItem* item = new QTreeWidgetItem(keyboard_tree_); - item->setText(0, menu->title().replace("&", "")); + QTreeWidgetItem *item = new QTreeWidgetItem(keyboard_tree_); + item->setText(0, menu->title().replace("&", "")); - keyboard_tree_->addTopLevelItem(item); + keyboard_tree_->addTopLevelItem(item); - setup_kbd_shortcut_worker(menu, item); - } + setup_kbd_shortcut_worker(menu, item); + } - for (int i=0;iproperty("id").isNull()) { - KeySequenceEditor* editor = new KeySequenceEditor(keyboard_tree_, key_shortcut_actions_.at(i)); - keyboard_tree_->setItemWidget(key_shortcut_items_.at(i), 1, editor); - key_shortcut_fields_.append(editor); - } - } + for (int i = 0; i < key_shortcut_items_.size(); i++) { + if (!key_shortcut_actions_.at(i)->property("id").isNull()) { + KeySequenceEditor *editor = new KeySequenceEditor( + keyboard_tree_, key_shortcut_actions_.at(i)); + keyboard_tree_->setItemWidget(key_shortcut_items_.at(i), 1, editor); + key_shortcut_fields_.append(editor); + } + } } -void PreferencesKeyboardTab::setup_kbd_shortcut_worker(QMenu* menu, QTreeWidgetItem* parent) { - QList actions = menu->actions(); - for (int i=0;i actions = menu->actions(); + for (int i = 0; i < actions.size(); i++) { + QAction *a = actions.at(i); - if (!a->isSeparator() && a->property("keyignore").isNull()) { - QTreeWidgetItem* item = new QTreeWidgetItem(parent); - item->setText(0, a->text().replace("&", "")); + if (!a->isSeparator() && a->property("keyignore").isNull()) { + QTreeWidgetItem *item = new QTreeWidgetItem(parent); + item->setText(0, a->text().replace("&", "")); - parent->addChild(item); + parent->addChild(item); - if (a->menu() != nullptr) { - item->setChildIndicatorPolicy(QTreeWidgetItem::ShowIndicator); - setup_kbd_shortcut_worker(a->menu(), item); - } else { - key_shortcut_items_.append(item); - key_shortcut_actions_.append(a); - } - } - } + if (a->menu() != nullptr) { + item->setChildIndicatorPolicy(QTreeWidgetItem::ShowIndicator); + setup_kbd_shortcut_worker(a->menu(), item); + } else { + key_shortcut_items_.append(item); + key_shortcut_actions_.append(a); + } + } + } } -void PreferencesKeyboardTab::reset_default_shortcut() { - QList items = keyboard_tree_->selectedItems(); - for (int i=0;iselectedItems().at(i); - static_cast(keyboard_tree_->itemWidget(item, 1))->reset_to_default(); - } +void PreferencesKeyboardTab::reset_default_shortcut() +{ + QList items = keyboard_tree_->selectedItems(); + for (int i = 0; i < items.size(); i++) { + QTreeWidgetItem *item = keyboard_tree_->selectedItems().at(i); + static_cast(keyboard_tree_->itemWidget(item, 1)) + ->reset_to_default(); + } } -void PreferencesKeyboardTab::reset_all_shortcuts() { - if (QMessageBox::question( - this, - tr("Confirm Reset All Shortcuts"), - tr("Are you sure you wish to reset all keyboard shortcuts to their defaults?"), - QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) { - for (int i=0;ireset_to_default(); - } - } +void PreferencesKeyboardTab::reset_all_shortcuts() +{ + if (QMessageBox::question( + this, tr("Confirm Reset All Shortcuts"), + tr("Are you sure you wish to reset all keyboard shortcuts to their defaults?"), + QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) { + for (int i = 0; i < key_shortcut_fields_.size(); i++) { + key_shortcut_fields_.at(i)->reset_to_default(); + } + } } -bool PreferencesKeyboardTab::refine_shortcut_list(const QString &s, QTreeWidgetItem* parent) { - if (parent == nullptr) { - for (int i=0;itopLevelItemCount();i++) { - refine_shortcut_list(s, keyboard_tree_->topLevelItem(i)); - } +bool PreferencesKeyboardTab::refine_shortcut_list(const QString &s, + QTreeWidgetItem *parent) +{ + if (parent == nullptr) { + for (int i = 0; i < keyboard_tree_->topLevelItemCount(); i++) { + refine_shortcut_list(s, keyboard_tree_->topLevelItem(i)); + } - // Return value is `all_children_are_hidden` which doesn't matter at the top level - return false; - } else { - parent->setExpanded(!s.isEmpty()); + // Return value is `all_children_are_hidden` which doesn't matter at the top level + return false; + } else { + parent->setExpanded(!s.isEmpty()); - bool all_children_are_hidden = !s.isEmpty(); + bool all_children_are_hidden = !s.isEmpty(); - for (int i=0;ichildCount();i++) { - QTreeWidgetItem* item = parent->child(i); - if (item->childCount() > 0) { - if (!refine_shortcut_list(s, item)) { - all_children_are_hidden = false; - } - } else { - item->setHidden(false); - if (s.isEmpty()) { - all_children_are_hidden = false; - } else { - QString shortcut; - if (keyboard_tree_->itemWidget(item, 1) != nullptr) { - shortcut = static_cast(keyboard_tree_->itemWidget(item, 1))->keySequence().toString(); - } - if (item->text(0).contains(s, Qt::CaseInsensitive) || shortcut.contains(s, Qt::CaseInsensitive)) { - all_children_are_hidden = false; - } else { - item->setHidden(true); - } - } - } - } + for (int i = 0; i < parent->childCount(); i++) { + QTreeWidgetItem *item = parent->child(i); + if (item->childCount() > 0) { + if (!refine_shortcut_list(s, item)) { + all_children_are_hidden = false; + } + } else { + item->setHidden(false); + if (s.isEmpty()) { + all_children_are_hidden = false; + } else { + QString shortcut; + if (keyboard_tree_->itemWidget(item, 1) != nullptr) { + shortcut = static_cast( + keyboard_tree_->itemWidget(item, 1)) + ->keySequence() + .toString(); + } + if (item->text(0).contains(s, Qt::CaseInsensitive) || + shortcut.contains(s, Qt::CaseInsensitive)) { + all_children_are_hidden = false; + } else { + item->setHidden(true); + } + } + } + } - if (parent->text(0).contains(s, Qt::CaseInsensitive)) all_children_are_hidden = false; + if (parent->text(0).contains(s, Qt::CaseInsensitive)) + all_children_are_hidden = false; - parent->setHidden(all_children_are_hidden); + parent->setHidden(all_children_are_hidden); - return all_children_are_hidden; - } + return all_children_are_hidden; + } } -void PreferencesKeyboardTab::load_shortcut_file() { - QString fn = QFileDialog::getOpenFileName(this, tr("Import Keyboard Shortcuts")); - if (!fn.isEmpty()) { - QFile f(fn); - if (f.exists() && f.open(QFile::ReadOnly)) { - QString ba = f.readAll(); - f.close(); - for (int i=0;iaction_name()); - if (index == 0 || (index > 0 && ba.at(index-1) == '\n')) { - while (index < ba.size() && ba.at(index) != '\t') index++; - QString ks; - index++; - while (index < ba.size() && ba.at(index) != '\n') { - ks.append(ba.at(index)); - index++; - } - key_shortcut_fields_.at(i)->setKeySequence(ks); - } else { - key_shortcut_fields_.at(i)->reset_to_default(); - } - } - } else { - QMessageBox::critical( - this, - tr("Error saving shortcuts"), - tr("Failed to open file for reading") - ); - } - } +void PreferencesKeyboardTab::load_shortcut_file() +{ + QString fn = + QFileDialog::getOpenFileName(this, tr("Import Keyboard Shortcuts")); + if (!fn.isEmpty()) { + QFile f(fn); + if (f.exists() && f.open(QFile::ReadOnly)) { + QString ba = f.readAll(); + f.close(); + for (int i = 0; i < key_shortcut_fields_.size(); i++) { + int index = + ba.indexOf(key_shortcut_fields_.at(i)->action_name()); + if (index == 0 || (index > 0 && ba.at(index - 1) == '\n')) { + while (index < ba.size() && ba.at(index) != '\t') + index++; + QString ks; + index++; + while (index < ba.size() && ba.at(index) != '\n') { + ks.append(ba.at(index)); + index++; + } + key_shortcut_fields_.at(i)->setKeySequence(ks); + } else { + key_shortcut_fields_.at(i)->reset_to_default(); + } + } + } else { + QMessageBox::critical(this, tr("Error saving shortcuts"), + tr("Failed to open file for reading")); + } + } } -void PreferencesKeyboardTab::save_shortcut_file() { - QString fn = QFileDialog::getSaveFileName(this, tr("Export Keyboard Shortcuts")); - if (!fn.isEmpty()) { - QFile f(fn); - if (f.open(QFile::WriteOnly)) { - bool start = true; - for (int i=0;iexport_shortcut(); - if (!s.isEmpty()) { - if (!start) f.write("\n"); - f.write(s.toUtf8()); - start = false; - } - } - f.close(); - QMessageBox::information(this, tr("Export Shortcuts"), tr("Shortcuts exported successfully")); - } else { - QMessageBox::critical(this, tr("Error saving shortcuts"), tr("Failed to open file for writing")); - } - } +void PreferencesKeyboardTab::save_shortcut_file() +{ + QString fn = + QFileDialog::getSaveFileName(this, tr("Export Keyboard Shortcuts")); + if (!fn.isEmpty()) { + QFile f(fn); + if (f.open(QFile::WriteOnly)) { + bool start = true; + for (int i = 0; i < key_shortcut_fields_.size(); i++) { + QString s = key_shortcut_fields_.at(i)->export_shortcut(); + if (!s.isEmpty()) { + if (!start) + f.write("\n"); + f.write(s.toUtf8()); + start = false; + } + } + f.close(); + QMessageBox::information(this, tr("Export Shortcuts"), + tr("Shortcuts exported successfully")); + } else { + QMessageBox::critical(this, tr("Error saving shortcuts"), + tr("Failed to open file for writing")); + } + } } } diff --git a/app/dialog/preferences/tabs/preferenceskeyboardtab.h b/app/dialog/preferences/tabs/preferenceskeyboardtab.h index f66e61f57..9bc887c0f 100644 --- a/app/dialog/preferences/tabs/preferenceskeyboardtab.h +++ b/app/dialog/preferences/tabs/preferenceskeyboardtab.h @@ -27,42 +27,42 @@ #include "dialog/configbase/configdialogbase.h" #include "../keysequenceeditor.h" -namespace olive { +namespace olive +{ class MainWindow; -class PreferencesKeyboardTab : public ConfigDialogBaseTab -{ - Q_OBJECT +class PreferencesKeyboardTab : public ConfigDialogBaseTab { + Q_OBJECT public: - PreferencesKeyboardTab(MainWindow* main_window); + PreferencesKeyboardTab(MainWindow *main_window); - virtual void Accept(MultiUndoCommand* command) override; + virtual void Accept(MultiUndoCommand *command) override; private slots: - /** + /** * @brief Show a file dialog to load an external shortcut preset from file */ - void load_shortcut_file(); + void load_shortcut_file(); - /** + /** * @brief Show a file dialog to save an external shortcut preset from file */ - void save_shortcut_file(); + void save_shortcut_file(); - /** + /** * @brief Reset all selected shortcuts in keyboard_tree to their defaults */ - void reset_default_shortcut(); + void reset_default_shortcut(); - /** + /** * @brief Reset all shortcuts indiscriminately to their defaults * * This is safe to call directly as it'll ask the user if they wish to do so before it resets. */ - void reset_all_shortcuts(); + void reset_all_shortcuts(); - /** + /** * @brief Shows/hides shortcut entries according to a shortcut query. * * This function can be directly connected to QLineEdit::textChanged() for simplicity. @@ -82,19 +82,20 @@ private slots: * If so, TRUE is returned so the parent is shown too (even if it doesn't match the search query). If not, FALSE is * returned so the parent is hidden. */ - bool refine_shortcut_list(const QString &s, QTreeWidgetItem* parent = nullptr); + bool refine_shortcut_list(const QString &s, + QTreeWidgetItem *parent = nullptr); private: - /** + /** * @brief Populate keyboard shortcut panel with keyboard shortcuts from the menu bar * * @param menu * * A reference to the main application's menu bar. Usually MainWindow::menuBar(). */ - void setup_kbd_shortcuts(QMenuBar* menu); + void setup_kbd_shortcuts(QMenuBar *menu); - /** + /** * @brief Internal function called by setup_kbd_shortcuts() to traverse down the menu bar's hierarchy and populate the * shortcut panel. * @@ -110,33 +111,32 @@ private: * * The parent item to add QTreeWidgetItems to. */ - void setup_kbd_shortcut_worker(QMenu* menu, QTreeWidgetItem* parent); + void setup_kbd_shortcut_worker(QMenu *menu, QTreeWidgetItem *parent); - /** + /** * @brief UI widget for editing keyboard shortcuts */ - QTreeWidget* keyboard_tree_; + QTreeWidget *keyboard_tree_; - /** + /** * @brief List of keyboard shortcut actions that can be triggered (links with key_shortcut_items and * key_shortcut_fields) */ - QVector key_shortcut_actions_; + QVector key_shortcut_actions_; - /** + /** * @brief List of keyboard shortcut items in keyboard_tree corresponding to existing actions (links with * key_shortcut_actions and key_shortcut_fields) */ - QVector key_shortcut_items_; + QVector key_shortcut_items_; - /** + /** * @brief List of keyboard shortcut editing fields in keyboard_tree corresponding to existing actions (links with * key_shortcut_actions and key_shortcut_fields) */ - QVector key_shortcut_fields_; - - MainWindow *main_window_; + QVector key_shortcut_fields_; + MainWindow *main_window_; }; } diff --git a/app/dialog/progress/progress.cpp b/app/dialog/progress/progress.cpp index 45d374498..9a5e30be3 100644 --- a/app/dialog/progress/progress.cpp +++ b/app/dialog/progress/progress.cpp @@ -27,116 +27,126 @@ #include "window/mainwindow/mainwindow.h" -namespace olive { +namespace olive +{ #define super QDialog -ProgressDialog::ProgressDialog(const QString& message, const QString& title, QWidget *parent) : - super(parent), - show_progress_(true), - first_show_(true) +ProgressDialog::ProgressDialog(const QString &message, const QString &title, + QWidget *parent) + : super(parent) + , show_progress_(true) + , first_show_(true) { - if (!title.isEmpty()) { - setWindowTitle(title); - } + if (!title.isEmpty()) { + setWindowTitle(title); + } - QVBoxLayout* layout = new QVBoxLayout(this); + QVBoxLayout *layout = new QVBoxLayout(this); - layout->addWidget(new QLabel(message)); + layout->addWidget(new QLabel(message)); - bar_ = new QProgressBar(); - bar_->setMinimum(0); - bar_->setValue(0); - bar_->setMaximum(100); - layout->addWidget(bar_); + bar_ = new QProgressBar(); + bar_->setMinimum(0); + bar_->setValue(0); + bar_->setMaximum(100); + layout->addWidget(bar_); - elapsed_timer_lbl_ = new ElapsedCounterWidget(); - layout->addWidget(elapsed_timer_lbl_); + elapsed_timer_lbl_ = new ElapsedCounterWidget(); + layout->addWidget(elapsed_timer_lbl_); - QHBoxLayout* cancel_layout = new QHBoxLayout(); - layout->addLayout(cancel_layout); - cancel_layout->setContentsMargins(0, 0, 0, 0); - cancel_layout->setSpacing(0); - cancel_layout->addStretch(); + QHBoxLayout *cancel_layout = new QHBoxLayout(); + layout->addLayout(cancel_layout); + cancel_layout->setContentsMargins(0, 0, 0, 0); + cancel_layout->setSpacing(0); + cancel_layout->addStretch(); - QPushButton* cancel_btn = new QPushButton(tr("Cancel")); + QPushButton *cancel_btn = new QPushButton(tr("Cancel")); - // Signal that derivatives can connect to - connect(cancel_btn, &QPushButton::clicked, this, &ProgressDialog::Cancelled, Qt::DirectConnection); + // Signal that derivatives can connect to + connect(cancel_btn, &QPushButton::clicked, this, &ProgressDialog::Cancelled, + Qt::DirectConnection); - // Stop updating the elapsed/remaining timers - connect(cancel_btn, &QPushButton::clicked, elapsed_timer_lbl_, &ElapsedCounterWidget::Stop); + // Stop updating the elapsed/remaining timers + connect(cancel_btn, &QPushButton::clicked, elapsed_timer_lbl_, + &ElapsedCounterWidget::Stop); - // Disable the button so that users know they don't need to keep clicking it - connect(cancel_btn, &QPushButton::clicked, this, &ProgressDialog::DisableSenderWidget); + // Disable the button so that users know they don't need to keep clicking it + connect(cancel_btn, &QPushButton::clicked, this, + &ProgressDialog::DisableSenderWidget); - // Prevent the progress bar from continuing to move - connect(cancel_btn, &QPushButton::clicked, this, &ProgressDialog::DisableProgressWidgets); + // Prevent the progress bar from continuing to move + connect(cancel_btn, &QPushButton::clicked, this, + &ProgressDialog::DisableProgressWidgets); - cancel_layout->addWidget(cancel_btn); + cancel_layout->addWidget(cancel_btn); - cancel_layout->addStretch(); + cancel_layout->addStretch(); } void ProgressDialog::showEvent(QShowEvent *e) { - super::showEvent(e); + super::showEvent(e); - if (first_show_) { - elapsed_timer_lbl_->Start(); + if (first_show_) { + elapsed_timer_lbl_->Start(); - Core::instance()->main_window()->SetApplicationProgressStatus(MainWindow::kProgressShow); + Core::instance()->main_window()->SetApplicationProgressStatus( + MainWindow::kProgressShow); - first_show_ = false; - } + first_show_ = false; + } } void ProgressDialog::closeEvent(QCloseEvent *e) { - super::closeEvent(e); + super::closeEvent(e); - Core::instance()->main_window()->SetApplicationProgressStatus(MainWindow::kProgressNone); + Core::instance()->main_window()->SetApplicationProgressStatus( + MainWindow::kProgressNone); - elapsed_timer_lbl_->Stop(); + elapsed_timer_lbl_->Stop(); - first_show_ = true; + first_show_ = true; } void ProgressDialog::SetProgress(double value) { - if (!show_progress_) { - return; - } + if (!show_progress_) { + return; + } - int percent = qRound(100.0 * value); + int percent = qRound(100.0 * value); - bar_->setValue(percent); - elapsed_timer_lbl_->SetProgress(value); + bar_->setValue(percent); + elapsed_timer_lbl_->SetProgress(value); - Core::instance()->main_window()->SetApplicationProgressValue(percent); + Core::instance()->main_window()->SetApplicationProgressValue(percent); } -void ProgressDialog::ShowErrorMessage(const QString &title, const QString &message) +void ProgressDialog::ShowErrorMessage(const QString &title, + const QString &message) { - Core::instance()->main_window()->SetApplicationProgressStatus(MainWindow::kProgressError); + Core::instance()->main_window()->SetApplicationProgressStatus( + MainWindow::kProgressError); - QMessageBox b(this); - b.setIcon(QMessageBox::Critical); - b.setWindowModality(Qt::WindowModal); - b.setWindowTitle(title); - b.setText(message); - b.addButton(QMessageBox::Ok); - b.exec(); + QMessageBox b(this); + b.setIcon(QMessageBox::Critical); + b.setWindowModality(Qt::WindowModal); + b.setWindowTitle(title); + b.setText(message); + b.addButton(QMessageBox::Ok); + b.exec(); } void ProgressDialog::DisableSenderWidget() { - static_cast(sender())->setEnabled(false); + static_cast(sender())->setEnabled(false); } void ProgressDialog::DisableProgressWidgets() { - show_progress_ = false; + show_progress_ = false; } } diff --git a/app/dialog/progress/progress.h b/app/dialog/progress/progress.h index 4352c5868..e1c31bfc0 100644 --- a/app/dialog/progress/progress.h +++ b/app/dialog/progress/progress.h @@ -27,42 +27,42 @@ #include "common/debug.h" #include "widget/taskview/elapsedcounterwidget.h" -namespace olive { - -class ProgressDialog : public QDialog +namespace olive { - Q_OBJECT + +class ProgressDialog : public QDialog { + Q_OBJECT public: - ProgressDialog(const QString &message, const QString &title, QWidget* parent = nullptr); + ProgressDialog(const QString &message, const QString &title, + QWidget *parent = nullptr); protected: - virtual void showEvent(QShowEvent* e) override; + virtual void showEvent(QShowEvent *e) override; - virtual void closeEvent(QCloseEvent *) override; + virtual void closeEvent(QCloseEvent *) override; public slots: - void SetProgress(double value); + void SetProgress(double value); signals: - void Cancelled(); + void Cancelled(); protected: - void ShowErrorMessage(const QString& title, const QString& message); + void ShowErrorMessage(const QString &title, const QString &message); private: - QProgressBar* bar_; + QProgressBar *bar_; - ElapsedCounterWidget* elapsed_timer_lbl_; + ElapsedCounterWidget *elapsed_timer_lbl_; - bool show_progress_; + bool show_progress_; - bool first_show_; + bool first_show_; private slots: - void DisableSenderWidget(); - - void DisableProgressWidgets(); + void DisableSenderWidget(); + void DisableProgressWidgets(); }; } diff --git a/app/dialog/projectproperties/projectproperties.cpp b/app/dialog/projectproperties/projectproperties.cpp index e059e9ac9..49b4d90d7 100644 --- a/app/dialog/projectproperties/projectproperties.cpp +++ b/app/dialog/projectproperties/projectproperties.cpp @@ -32,234 +32,271 @@ #include "node/color/colormanager/colormanager.h" #include "render/diskmanager.h" -namespace olive { +namespace olive +{ #define super QDialog -ProjectPropertiesDialog::ProjectPropertiesDialog(Project* p, QWidget *parent) : - super(parent), - working_project_(p), - ocio_config_is_valid_(true) +ProjectPropertiesDialog::ProjectPropertiesDialog(Project *p, QWidget *parent) + : super(parent) + , working_project_(p) + , ocio_config_is_valid_(true) { - QVBoxLayout* layout = new QVBoxLayout(this); + QVBoxLayout *layout = new QVBoxLayout(this); - setWindowTitle(tr("Project Properties for '%1'").arg(working_project_->name())); + setWindowTitle( + tr("Project Properties for '%1'").arg(working_project_->name())); - QTabWidget* tabs = new QTabWidget; - layout->addWidget(tabs); + QTabWidget *tabs = new QTabWidget; + layout->addWidget(tabs); - { - // Color management group - QWidget* color_group = new QWidget(); + { + // Color management group + QWidget *color_group = new QWidget(); - QVBoxLayout* color_outer_layout = new QVBoxLayout(color_group); + QVBoxLayout *color_outer_layout = new QVBoxLayout(color_group); - QGridLayout* color_layout = new QGridLayout(); - color_outer_layout->addLayout(color_layout); + QGridLayout *color_layout = new QGridLayout(); + color_outer_layout->addLayout(color_layout); - int row = 0; + int row = 0; - color_layout->addWidget(new QLabel(tr("OpenColorIO Configuration:")), row, 0); + color_layout->addWidget(new QLabel(tr("OpenColorIO Configuration:")), + row, 0); - ocio_filename_ = new QLineEdit(); - ocio_filename_->setPlaceholderText(tr("(default)")); - color_layout->addWidget(ocio_filename_, row, 1); + ocio_filename_ = new QLineEdit(); + ocio_filename_->setPlaceholderText(tr("(default)")); + color_layout->addWidget(ocio_filename_, row, 1); - row++; + row++; - color_layout->addWidget(new QLabel(tr("Default Input Color Space:")), row, 0); + color_layout->addWidget(new QLabel(tr("Default Input Color Space:")), + row, 0); - default_input_colorspace_ = new QComboBox(); - color_layout->addWidget(default_input_colorspace_, row, 1, 1, 2); + default_input_colorspace_ = new QComboBox(); + color_layout->addWidget(default_input_colorspace_, row, 1, 1, 2); - row++; + row++; - color_layout->addWidget(new QLabel(tr("Reference Space:")), row, 0); + color_layout->addWidget(new QLabel(tr("Reference Space:")), row, 0); - reference_space_ = new QComboBox(this); - reference_space_->addItem(tr("Scene Linear"), OCIO::ROLE_SCENE_LINEAR); - reference_space_->addItem(tr("Compositing Log"), OCIO::ROLE_COMPOSITING_LOG); - QtUtils::SetComboBoxData(reference_space_, p->GetColorReferenceSpace()); - color_layout->addWidget(reference_space_, row, 1, 1, 2); + reference_space_ = new QComboBox(this); + reference_space_->addItem(tr("Scene Linear"), OCIO::ROLE_SCENE_LINEAR); + reference_space_->addItem(tr("Compositing Log"), + OCIO::ROLE_COMPOSITING_LOG); + QtUtils::SetComboBoxData(reference_space_, p->GetColorReferenceSpace()); + color_layout->addWidget(reference_space_, row, 1, 1, 2); - row++; + row++; - QPushButton* browse_btn = new QPushButton(tr("Browse")); - color_layout->addWidget(browse_btn, 0, 2); - connect(browse_btn, &QPushButton::clicked, this, &ProjectPropertiesDialog::BrowseForOCIOConfig); + QPushButton *browse_btn = new QPushButton(tr("Browse")); + color_layout->addWidget(browse_btn, 0, 2); + connect(browse_btn, &QPushButton::clicked, this, + &ProjectPropertiesDialog::BrowseForOCIOConfig); - ocio_filename_->setText(working_project_->color_manager()->GetConfigFilename()); + ocio_filename_->setText( + working_project_->color_manager()->GetConfigFilename()); - connect(ocio_filename_, &QLineEdit::textChanged, this, &ProjectPropertiesDialog::OCIOFilenameUpdated); - OCIOFilenameUpdated(); + connect(ocio_filename_, &QLineEdit::textChanged, this, + &ProjectPropertiesDialog::OCIOFilenameUpdated); + OCIOFilenameUpdated(); - tabs->addTab(color_group, tr("Color Management")); + tabs->addTab(color_group, tr("Color Management")); - color_outer_layout->addStretch(); - } + color_outer_layout->addStretch(); + } - { - // Cache group - QWidget* cache_group = new QWidget(); + { + // Cache group + QWidget *cache_group = new QWidget(); - QVBoxLayout* cache_layout = new QVBoxLayout(cache_group); + QVBoxLayout *cache_layout = new QVBoxLayout(cache_group); - QButtonGroup* disk_cache_btn_group = new QButtonGroup(); + QButtonGroup *disk_cache_btn_group = new QButtonGroup(); - // Create radio buttons and add to widget and button group - disk_cache_radios_[Project::kCacheUseDefaultLocation] = new QRadioButton(tr("Use Default Location")); - disk_cache_radios_[Project::kCacheStoreAlongsideProject] = new QRadioButton(tr("Store Alongside Project")); - disk_cache_radios_[Project::kCacheCustomPath] = new QRadioButton(tr("Use Custom Location:")); - for (int i=0; iaddButton(disk_cache_radios_[i]); - cache_layout->addWidget(disk_cache_radios_[i]); - } + // Create radio buttons and add to widget and button group + disk_cache_radios_[Project::kCacheUseDefaultLocation] = + new QRadioButton(tr("Use Default Location")); + disk_cache_radios_[Project::kCacheStoreAlongsideProject] = + new QRadioButton(tr("Store Alongside Project")); + disk_cache_radios_[Project::kCacheCustomPath] = + new QRadioButton(tr("Use Custom Location:")); + for (int i = 0; i < kDiskCacheRadioCount; i++) { + disk_cache_btn_group->addButton(disk_cache_radios_[i]); + cache_layout->addWidget(disk_cache_radios_[i]); + } - // Create custom cache path widget - custom_cache_path_ = new PathWidget(working_project_->GetCustomCachePath(), this); - custom_cache_path_->setEnabled(false); - cache_layout->addWidget(custom_cache_path_); + // Create custom cache path widget + custom_cache_path_ = + new PathWidget(working_project_->GetCustomCachePath(), this); + custom_cache_path_->setEnabled(false); + cache_layout->addWidget(custom_cache_path_); - // Ensure custom cache path "enabled" is tied to the radio button being checked - connect(disk_cache_radios_[Project::kCacheCustomPath], &QRadioButton::toggled, custom_cache_path_, &PathWidget::setEnabled); + // Ensure custom cache path "enabled" is tied to the radio button being checked + connect(disk_cache_radios_[Project::kCacheCustomPath], + &QRadioButton::toggled, custom_cache_path_, + &PathWidget::setEnabled); - // Check the radio button that should currently be active - disk_cache_radios_[working_project_->GetCacheLocationSetting()]->setChecked(true); + // Check the radio button that should currently be active + disk_cache_radios_[working_project_->GetCacheLocationSetting()] + ->setChecked(true); - // Add disk cache settings button - QPushButton* disk_cache_settings_btn = new QPushButton(tr("Disk Cache Settings")); - connect(disk_cache_settings_btn, &QPushButton::clicked, this, &ProjectPropertiesDialog::OpenDiskCacheSettings); - cache_layout->addWidget(disk_cache_settings_btn); + // Add disk cache settings button + QPushButton *disk_cache_settings_btn = + new QPushButton(tr("Disk Cache Settings")); + connect(disk_cache_settings_btn, &QPushButton::clicked, this, + &ProjectPropertiesDialog::OpenDiskCacheSettings); + cache_layout->addWidget(disk_cache_settings_btn); - tabs->addTab(cache_group, tr("Disk Cache")); - } + tabs->addTab(cache_group, tr("Disk Cache")); + } - QDialogButtonBox* dialog_btns = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, - Qt::Horizontal); - layout->addWidget(dialog_btns); - connect(dialog_btns, &QDialogButtonBox::accepted, this, &ProjectPropertiesDialog::accept); - connect(dialog_btns, &QDialogButtonBox::rejected, this, &ProjectPropertiesDialog::reject); + QDialogButtonBox *dialog_btns = new QDialogButtonBox( + QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal); + layout->addWidget(dialog_btns); + connect(dialog_btns, &QDialogButtonBox::accepted, this, + &ProjectPropertiesDialog::accept); + connect(dialog_btns, &QDialogButtonBox::rejected, this, + &ProjectPropertiesDialog::reject); } void ProjectPropertiesDialog::accept() { - if (!ocio_config_is_valid_) { - QMessageBox mb(this); - mb.setWindowModality(Qt::WindowModal); - mb.setIcon(QMessageBox::Critical); - mb.setWindowTitle(tr("OpenColorIO Config Error")); - mb.setText(tr("Failed to set OpenColorIO configuration: %1").arg(ocio_config_error_)); - mb.addButton(QMessageBox::Ok); - mb.exec(); - return; - } + if (!ocio_config_is_valid_) { + QMessageBox mb(this); + mb.setWindowModality(Qt::WindowModal); + mb.setIcon(QMessageBox::Critical); + mb.setWindowTitle(tr("OpenColorIO Config Error")); + mb.setText(tr("Failed to set OpenColorIO configuration: %1") + .arg(ocio_config_error_)); + mb.addButton(QMessageBox::Ok); + mb.exec(); + return; + } - if (disk_cache_radios_[Project::kCacheUseDefaultLocation]->isChecked()) { - // Keep new cache path empty, which means default - } else if (disk_cache_radios_[Project::kCacheStoreAlongsideProject]->isChecked()) { - // Ensure alongside project path is valid - if (!VerifyPathAndWarnIfBad(working_project_->get_cache_alongside_project_path())) { - return; - } - } else { - // Ensure custom path is valid - if (!VerifyPathAndWarnIfBad(custom_cache_path_->text())) { - return; - } - } + if (disk_cache_radios_[Project::kCacheUseDefaultLocation]->isChecked()) { + // Keep new cache path empty, which means default + } else if (disk_cache_radios_[Project::kCacheStoreAlongsideProject] + ->isChecked()) { + // Ensure alongside project path is valid + if (!VerifyPathAndWarnIfBad( + working_project_->get_cache_alongside_project_path())) { + return; + } + } else { + // Ensure custom path is valid + if (!VerifyPathAndWarnIfBad(custom_cache_path_->text())) { + return; + } + } - if (custom_cache_path_->text() != working_project_->GetCustomCachePath()) { - // Check if the user is okay with invalidating the current cache - if (!DiskManager::ShowDiskCacheChangeConfirmationDialog(this)) { - return; - } + if (custom_cache_path_->text() != working_project_->GetCustomCachePath()) { + // Check if the user is okay with invalidating the current cache + if (!DiskManager::ShowDiskCacheChangeConfirmationDialog(this)) { + return; + } - working_project_->SetCustomCachePath(custom_cache_path_->text()); + working_project_->SetCustomCachePath(custom_cache_path_->text()); - emit DiskManager::instance()->InvalidateProject(working_project_); - } + emit DiskManager::instance() -> InvalidateProject(working_project_); + } - // This should ripple changes throughout the graph/cache that the color config has changed, and - // therefore should be done after the cache path is changed - if (working_project_->color_manager()->GetConfigFilename() != ocio_filename_->text()) { - working_project_->color_manager()->SetConfigFilename(ocio_filename_->text()); - } - if (working_project_->color_manager()->GetDefaultInputColorSpace() != default_input_colorspace_->currentText()) { - working_project_->color_manager()->SetDefaultInputColorSpace(default_input_colorspace_->currentText()); - } - if (working_project_->GetColorReferenceSpace() != reference_space_->currentData().toString()) { - working_project_->SetColorReferenceSpace(reference_space_->currentData().toString()); - } + // This should ripple changes throughout the graph/cache that the color config has changed, and + // therefore should be done after the cache path is changed + if (working_project_->color_manager()->GetConfigFilename() != + ocio_filename_->text()) { + working_project_->color_manager()->SetConfigFilename( + ocio_filename_->text()); + } + if (working_project_->color_manager()->GetDefaultInputColorSpace() != + default_input_colorspace_->currentText()) { + working_project_->color_manager()->SetDefaultInputColorSpace( + default_input_colorspace_->currentText()); + } + if (working_project_->GetColorReferenceSpace() != + reference_space_->currentData().toString()) { + working_project_->SetColorReferenceSpace( + reference_space_->currentData().toString()); + } - super::accept(); + super::accept(); } bool ProjectPropertiesDialog::VerifyPathAndWarnIfBad(const QString &path) { - if (!FileFunctions::DirectoryIsValid(path)) { - QMessageBox mb(this); - mb.setWindowModality(Qt::WindowModal); - mb.setIcon(QMessageBox::Critical); - mb.setWindowTitle(tr("Invalid path")); - mb.setText(tr("The custom cache path is invalid. Please check it and try again.")); - mb.addButton(QMessageBox::Ok); - mb.exec(); - return false; - } + if (!FileFunctions::DirectoryIsValid(path)) { + QMessageBox mb(this); + mb.setWindowModality(Qt::WindowModal); + mb.setIcon(QMessageBox::Critical); + mb.setWindowTitle(tr("Invalid path")); + mb.setText(tr( + "The custom cache path is invalid. Please check it and try again.")); + mb.addButton(QMessageBox::Ok); + mb.exec(); + return false; + } - return true; + return true; } void ProjectPropertiesDialog::BrowseForOCIOConfig() { - QString fn = QFileDialog::getOpenFileName(this, tr("Browse for OpenColorIO configuration")); - if (!fn.isEmpty()) { - ocio_filename_->setText(fn); - } + QString fn = QFileDialog::getOpenFileName( + this, tr("Browse for OpenColorIO configuration")); + if (!fn.isEmpty()) { + ocio_filename_->setText(fn); + } } void ProjectPropertiesDialog::OCIOFilenameUpdated() { - default_input_colorspace_->clear(); + default_input_colorspace_->clear(); - try { - OCIO::ConstConfigRcPtr c; + try { + OCIO::ConstConfigRcPtr c; - if (ocio_filename_->text().isEmpty()) { - c = ColorManager::GetDefaultConfig(); - } else { - c = ColorManager::CreateConfigFromFile(ocio_filename_->text()); - } + if (ocio_filename_->text().isEmpty()) { + c = ColorManager::GetDefaultConfig(); + } else { + c = ColorManager::CreateConfigFromFile(ocio_filename_->text()); + } - ocio_filename_->setStyleSheet(QString()); - ocio_config_is_valid_ = true; + ocio_filename_->setStyleSheet(QString()); + ocio_config_is_valid_ = true; - // List input color spaces - QStringList input_cs = ColorManager::ListAvailableColorspaces(c); + // List input color spaces + QStringList input_cs = ColorManager::ListAvailableColorspaces(c); - foreach (QString cs, input_cs) { - default_input_colorspace_->addItem(cs); + foreach (QString cs, input_cs) { + default_input_colorspace_->addItem(cs); - if (cs == working_project_->color_manager()->GetDefaultInputColorSpace()) { - default_input_colorspace_->setCurrentIndex(default_input_colorspace_->count()-1); - } - } - } catch (OCIO::Exception& e) { - ocio_config_is_valid_ = false; - ocio_filename_->setStyleSheet(QStringLiteral("QLineEdit {color: red;}")); - ocio_config_error_ = e.what(); - } + if (cs == + working_project_->color_manager()->GetDefaultInputColorSpace()) { + default_input_colorspace_->setCurrentIndex( + default_input_colorspace_->count() - 1); + } + } + } catch (OCIO::Exception &e) { + ocio_config_is_valid_ = false; + ocio_filename_->setStyleSheet( + QStringLiteral("QLineEdit {color: red;}")); + ocio_config_error_ = e.what(); + } } void ProjectPropertiesDialog::OpenDiskCacheSettings() { - if (disk_cache_radios_[Project::kCacheUseDefaultLocation]->isChecked()) { - DiskManager::instance()->ShowDiskCacheSettingsDialog(DiskManager::instance()->GetDefaultCacheFolder(), this); - } else if (disk_cache_radios_[Project::kCacheStoreAlongsideProject]->isChecked()) { - DiskManager::instance()->ShowDiskCacheSettingsDialog(working_project_->get_cache_alongside_project_path(), this); - } else { - DiskManager::instance()->ShowDiskCacheSettingsDialog(custom_cache_path_->text(), this); - } + if (disk_cache_radios_[Project::kCacheUseDefaultLocation]->isChecked()) { + DiskManager::instance()->ShowDiskCacheSettingsDialog( + DiskManager::instance()->GetDefaultCacheFolder(), this); + } else if (disk_cache_radios_[Project::kCacheStoreAlongsideProject] + ->isChecked()) { + DiskManager::instance()->ShowDiskCacheSettingsDialog( + working_project_->get_cache_alongside_project_path(), this); + } else { + DiskManager::instance()->ShowDiskCacheSettingsDialog( + custom_cache_path_->text(), this); + } } } diff --git a/app/dialog/projectproperties/projectproperties.h b/app/dialog/projectproperties/projectproperties.h index 46b3131ea..90f8909d4 100644 --- a/app/dialog/projectproperties/projectproperties.h +++ b/app/dialog/projectproperties/projectproperties.h @@ -31,44 +31,43 @@ #include "node/project.h" #include "widget/path/pathwidget.h" -namespace olive { - -class ProjectPropertiesDialog : public QDialog +namespace olive { - Q_OBJECT + +class ProjectPropertiesDialog : public QDialog { + Q_OBJECT public: - ProjectPropertiesDialog(Project *p, QWidget* parent); + ProjectPropertiesDialog(Project *p, QWidget *parent); public slots: - virtual void accept() override; + virtual void accept() override; private: - bool VerifyPathAndWarnIfBad(const QString &path); + bool VerifyPathAndWarnIfBad(const QString &path); - Project* working_project_; + Project *working_project_; - QLineEdit* ocio_filename_; + QLineEdit *ocio_filename_; - QComboBox* default_input_colorspace_; + QComboBox *default_input_colorspace_; - QComboBox *reference_space_; + QComboBox *reference_space_; - bool ocio_config_is_valid_; + bool ocio_config_is_valid_; - QString ocio_config_error_; + QString ocio_config_error_; - PathWidget* custom_cache_path_; + PathWidget *custom_cache_path_; - static const int kDiskCacheRadioCount = 3; - QRadioButton *disk_cache_radios_[kDiskCacheRadioCount]; + static const int kDiskCacheRadioCount = 3; + QRadioButton *disk_cache_radios_[kDiskCacheRadioCount]; private slots: - void BrowseForOCIOConfig(); + void BrowseForOCIOConfig(); - void OCIOFilenameUpdated(); - - void OpenDiskCacheSettings(); + void OCIOFilenameUpdated(); + void OpenDiskCacheSettings(); }; } diff --git a/app/dialog/rendercancel/rendercancel.cpp b/app/dialog/rendercancel/rendercancel.cpp index 95d627834..b1a2e14c9 100644 --- a/app/dialog/rendercancel/rendercancel.cpp +++ b/app/dialog/rendercancel/rendercancel.cpp @@ -20,63 +20,67 @@ #include "rendercancel.h" -namespace olive { +namespace olive +{ -RenderCancelDialog::RenderCancelDialog(QWidget *parent) : - ProgressDialog(tr("Waiting for workers to finish..."), tr("Renderer"), parent), - busy_workers_(0), - total_workers_(0) +RenderCancelDialog::RenderCancelDialog(QWidget *parent) + : ProgressDialog(tr("Waiting for workers to finish..."), tr("Renderer"), + parent) + , busy_workers_(0) + , total_workers_(0) { } void RenderCancelDialog::RunIfWorkersAreBusy() { - if (busy_workers_ > 0) { - waiting_workers_ = busy_workers_; + if (busy_workers_ > 0) { + waiting_workers_ = busy_workers_; - exec(); - } + exec(); + } } void RenderCancelDialog::SetWorkerCount(int count) { - total_workers_ = count; + total_workers_ = count; - UpdateProgress(); + UpdateProgress(); } void RenderCancelDialog::WorkerStarted() { - busy_workers_++; + busy_workers_++; - UpdateProgress(); + UpdateProgress(); } void RenderCancelDialog::WorkerDone() { - busy_workers_--; + busy_workers_--; - UpdateProgress(); + UpdateProgress(); } void RenderCancelDialog::showEvent(QShowEvent *event) { - QDialog::showEvent(event); - - UpdateProgress(); + QDialog::showEvent(event); + + UpdateProgress(); } void RenderCancelDialog::UpdateProgress() { - if (!total_workers_ || !isVisible()) { - return; - } + if (!total_workers_ || !isVisible()) { + return; + } - SetProgress(qRound(100.0 * static_cast(waiting_workers_ - busy_workers_) / static_cast(waiting_workers_))); + SetProgress( + qRound(100.0 * static_cast(waiting_workers_ - busy_workers_) / + static_cast(waiting_workers_))); - if (busy_workers_ == 0) { - accept(); - } + if (busy_workers_ == 0) { + accept(); + } } } diff --git a/app/dialog/rendercancel/rendercancel.h b/app/dialog/rendercancel/rendercancel.h index a3f12b3f4..4e3dcac87 100644 --- a/app/dialog/rendercancel/rendercancel.h +++ b/app/dialog/rendercancel/rendercancel.h @@ -23,35 +23,34 @@ #include "dialog/progress/progress.h" -namespace olive { - -class RenderCancelDialog : public ProgressDialog +namespace olive { - Q_OBJECT + +class RenderCancelDialog : public ProgressDialog { + Q_OBJECT public: - RenderCancelDialog(QWidget* parent = nullptr); + RenderCancelDialog(QWidget *parent = nullptr); - void RunIfWorkersAreBusy(); + void RunIfWorkersAreBusy(); - void SetWorkerCount(int count); + void SetWorkerCount(int count); - void WorkerStarted(); + void WorkerStarted(); public slots: - void WorkerDone(); + void WorkerDone(); protected: - virtual void showEvent(QShowEvent* event) override; + virtual void showEvent(QShowEvent *event) override; private: - void UpdateProgress(); + void UpdateProgress(); - int busy_workers_; + int busy_workers_; - int total_workers_; - - int waiting_workers_; + int total_workers_; + int waiting_workers_; }; } diff --git a/app/dialog/sequence/presetmanager.h b/app/dialog/sequence/presetmanager.h index a61c323ea..0b7b3f28d 100644 --- a/app/dialog/sequence/presetmanager.h +++ b/app/dialog/sequence/presetmanager.h @@ -35,210 +35,213 @@ #include "common/filefunctions.h" #include "common/xmlutils.h" -namespace olive { - -class Preset +namespace olive { + +class Preset { public: - Preset() = default; + Preset() = default; - virtual ~Preset(){} + virtual ~Preset() + { + } - const QString& GetName() const - { - return name_; - } + const QString &GetName() const + { + return name_; + } - void SetName(const QString& s) - { - name_ = s; - } + void SetName(const QString &s) + { + name_ = s; + } - virtual void Load(QXmlStreamReader* reader) = 0; + virtual void Load(QXmlStreamReader *reader) = 0; - virtual void Save(QXmlStreamWriter* writer) const = 0; + virtual void Save(QXmlStreamWriter *writer) const = 0; private: - QString name_; - + QString name_; }; using PresetPtr = std::shared_ptr; -template -class PresetManager -{ +template class PresetManager { public: - PresetManager(QWidget* parent, const QString& preset_name) : - preset_name_(preset_name), - parent_(parent) - { - // Load custom preset data from file - QFile preset_file(GetCustomPresetFilename()); - if (preset_file.open(QFile::ReadOnly)) { - QXmlStreamReader reader(&preset_file); + PresetManager(QWidget *parent, const QString &preset_name) + : preset_name_(preset_name) + , parent_(parent) + { + // Load custom preset data from file + QFile preset_file(GetCustomPresetFilename()); + if (preset_file.open(QFile::ReadOnly)) { + QXmlStreamReader reader(&preset_file); - while (XMLReadNextStartElement(&reader)) { - if (reader.name() == QStringLiteral("presets")) { - while (XMLReadNextStartElement(&reader)) { - if (reader.name() == QStringLiteral("preset")) { - PresetPtr p = std::make_unique(); + while (XMLReadNextStartElement(&reader)) { + if (reader.name() == QStringLiteral("presets")) { + while (XMLReadNextStartElement(&reader)) { + if (reader.name() == QStringLiteral("preset")) { + PresetPtr p = std::make_unique(); - p->Load(&reader); + p->Load(&reader); - custom_preset_data_.append(p); - } else { - reader.skipCurrentElement(); - } - } - } else { - reader.skipCurrentElement(); - } - } + custom_preset_data_.append(p); + } else { + reader.skipCurrentElement(); + } + } + } else { + reader.skipCurrentElement(); + } + } - preset_file.close(); - } - } + preset_file.close(); + } + } - ~PresetManager() - { - // Save custom presets to disk - QFile preset_file(GetCustomPresetFilename()); - if (preset_file.open(QFile::WriteOnly)) { - QXmlStreamWriter writer(&preset_file); - writer.setAutoFormatting(true); + ~PresetManager() + { + // Save custom presets to disk + QFile preset_file(GetCustomPresetFilename()); + if (preset_file.open(QFile::WriteOnly)) { + QXmlStreamWriter writer(&preset_file); + writer.setAutoFormatting(true); - writer.writeStartDocument(); + writer.writeStartDocument(); - writer.writeStartElement(QStringLiteral("presets")); + writer.writeStartElement(QStringLiteral("presets")); - foreach (PresetPtr p, custom_preset_data_) { - writer.writeStartElement(QStringLiteral("preset")); + foreach (PresetPtr p, custom_preset_data_) { + writer.writeStartElement(QStringLiteral("preset")); - p->Save(&writer); + p->Save(&writer); - writer.writeEndElement(); // preset - } + writer.writeEndElement(); // preset + } - writer.writeEndElement(); // presets + writer.writeEndElement(); // presets - writer.writeEndDocument(); + writer.writeEndDocument(); - preset_file.close(); - } - } + preset_file.close(); + } + } - QString GetPresetName(QString start) const - { - bool ok; + QString GetPresetName(QString start) const + { + bool ok; - forever { - start = QInputDialog::getText(parent_, - QCoreApplication::translate("PresetManager", "Save Preset"), - QCoreApplication::translate("PresetManager", "Set preset name:"), - QLineEdit::Normal, - start, - &ok); + forever + { + start = QInputDialog::getText( + parent_, + QCoreApplication::translate("PresetManager", "Save Preset"), + QCoreApplication::translate("PresetManager", + "Set preset name:"), + QLineEdit::Normal, start, &ok); - if (!ok) { - // Dialog cancelled - leave function entirely - return QString(); - } + if (!ok) { + // Dialog cancelled - leave function entirely + return QString(); + } - if (start.isEmpty()) { - // No preset name entered, start loop over - QMessageBox::critical(parent_, - QCoreApplication::translate("PresetManager", "Invalid preset name"), - QCoreApplication::translate("PresetManager", "You must enter a preset name"), - QMessageBox::Ok); - } else { - break; - } - } + if (start.isEmpty()) { + // No preset name entered, start loop over + QMessageBox::critical( + parent_, + QCoreApplication::translate("PresetManager", + "Invalid preset name"), + QCoreApplication::translate("PresetManager", + "You must enter a preset name"), + QMessageBox::Ok); + } else { + break; + } + } - return start; - } + return start; + } - enum SaveStatus { - kAppended, - kReplaced, - kNotSaved - }; + enum SaveStatus { kAppended, kReplaced, kNotSaved }; - SaveStatus SavePreset(PresetPtr preset) - { - QString preset_name; - int existing_preset; + SaveStatus SavePreset(PresetPtr preset) + { + QString preset_name; + int existing_preset; - forever { - preset_name = GetPresetName(preset_name); + forever + { + preset_name = GetPresetName(preset_name); - if (preset_name.isEmpty()) { - // Dialog cancelled - leave function entirely - return kNotSaved; - } + if (preset_name.isEmpty()) { + // Dialog cancelled - leave function entirely + return kNotSaved; + } - existing_preset = -1; - for (int i=0; iGetName() == preset_name) { - existing_preset = i; - break; - } - } + existing_preset = -1; + for (int i = 0; i < custom_preset_data_.size(); i++) { + if (custom_preset_data_.at(i)->GetName() == preset_name) { + existing_preset = i; + break; + } + } - if (existing_preset == -1 - || QMessageBox::question(parent_, - QCoreApplication::translate("PresetManager", "Preset exists"), - QCoreApplication::translate("PresetManager", - "A preset with this name already exists. " - "Would you like to replace it?")) == QMessageBox::Yes) { - break; - } - } + if (existing_preset == -1 || + QMessageBox::question( + parent_, + QCoreApplication::translate("PresetManager", + "Preset exists"), + QCoreApplication::translate( + "PresetManager", + "A preset with this name already exists. " + "Would you like to replace it?")) == QMessageBox::Yes) { + break; + } + } - preset->SetName(preset_name); + preset->SetName(preset_name); - if (existing_preset >= 0) { - custom_preset_data_.replace(existing_preset, preset); - return kReplaced; - } else { - custom_preset_data_.append(preset); - return kAppended; - } - } + if (existing_preset >= 0) { + custom_preset_data_.replace(existing_preset, preset); + return kReplaced; + } else { + custom_preset_data_.append(preset); + return kAppended; + } + } - QString GetCustomPresetFilename() const - { - return QDir(FileFunctions::GetConfigurationLocation()).filePath(preset_name_); - } + QString GetCustomPresetFilename() const + { + return QDir(FileFunctions::GetConfigurationLocation()) + .filePath(preset_name_); + } - PresetPtr GetPreset(int index) - { - return custom_preset_data_.at(index); - } + PresetPtr GetPreset(int index) + { + return custom_preset_data_.at(index); + } - void DeletePreset(int index) - { - custom_preset_data_.removeAt(index); - } + void DeletePreset(int index) + { + custom_preset_data_.removeAt(index); + } - int GetNumberOfPresets() const - { - return custom_preset_data_.size(); - } + int GetNumberOfPresets() const + { + return custom_preset_data_.size(); + } - const QVector& GetPresetData() const - { - return custom_preset_data_; - } + const QVector &GetPresetData() const + { + return custom_preset_data_; + } private: - QVector custom_preset_data_; + QVector custom_preset_data_; - QString preset_name_; - - QWidget* parent_; + QString preset_name_; + QWidget *parent_; }; } diff --git a/app/dialog/sequence/sequence.cpp b/app/dialog/sequence/sequence.cpp index d6a109f1c..dee6df698 100644 --- a/app/dialog/sequence/sequence.cpp +++ b/app/dialog/sequence/sequence.cpp @@ -35,194 +35,213 @@ #include "common/qtutils.h" #include "undo/undostack.h" -namespace olive { - -SequenceDialog::SequenceDialog(Sequence* s, Type t, QWidget* parent) : - QDialog(parent), - sequence_(s), - make_undoable_(true) +namespace olive { - QVBoxLayout* layout = new QVBoxLayout(this); - QSplitter* splitter = new QSplitter(); - layout->addWidget(splitter); +SequenceDialog::SequenceDialog(Sequence *s, Type t, QWidget *parent) + : QDialog(parent) + , sequence_(s) + , make_undoable_(true) +{ + QVBoxLayout *layout = new QVBoxLayout(this); - preset_tab_ = new SequenceDialogPresetTab(); - splitter->addWidget(preset_tab_); + QSplitter *splitter = new QSplitter(); + layout->addWidget(splitter); - parameter_tab_ = new SequenceDialogParameterTab(sequence_); - splitter->addWidget(parameter_tab_); + preset_tab_ = new SequenceDialogPresetTab(); + splitter->addWidget(preset_tab_); - connect(preset_tab_, &SequenceDialogPresetTab::PresetChanged, - parameter_tab_, &SequenceDialogParameterTab::PresetChanged); - connect(preset_tab_, &SequenceDialogPresetTab::PresetAccepted, - this, &SequenceDialog::accept); - connect(parameter_tab_, &SequenceDialogParameterTab::SaveParametersAsPreset, - preset_tab_, &SequenceDialogPresetTab::SaveParametersAsPreset); + parameter_tab_ = new SequenceDialogParameterTab(sequence_); + splitter->addWidget(parameter_tab_); - // Set up name section - QHBoxLayout* name_layout = new QHBoxLayout(); - name_layout->addWidget(new QLabel(tr("Name:"))); - name_field_ = new QLineEdit(); - name_layout->addWidget(name_field_); - layout->addLayout(name_layout); + connect(preset_tab_, &SequenceDialogPresetTab::PresetChanged, + parameter_tab_, &SequenceDialogParameterTab::PresetChanged); + connect(preset_tab_, &SequenceDialogPresetTab::PresetAccepted, this, + &SequenceDialog::accept); + connect(parameter_tab_, &SequenceDialogParameterTab::SaveParametersAsPreset, + preset_tab_, &SequenceDialogPresetTab::SaveParametersAsPreset); - // Set up dialog buttons - QDialogButtonBox* buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); - QPushButton *default_btn = buttons->addButton(tr("Set As Default"), QDialogButtonBox::ActionRole); - connect(buttons, &QDialogButtonBox::accepted, this, &SequenceDialog::accept); - connect(buttons, &QDialogButtonBox::rejected, this, &SequenceDialog::reject); - connect(default_btn, &QPushButton::clicked, this, &SequenceDialog::SetAsDefaultClicked); - layout->addWidget(buttons); + // Set up name section + QHBoxLayout *name_layout = new QHBoxLayout(); + name_layout->addWidget(new QLabel(tr("Name:"))); + name_field_ = new QLineEdit(); + name_layout->addWidget(name_field_); + layout->addLayout(name_layout); - // Set window title based on type - switch (t) { - case kNew: - setWindowTitle(tr("New Sequence")); - break; - case kExisting: - setWindowTitle(tr("Editing \"%1\"").arg(sequence_->GetLabel())); - break; - } + // Set up dialog buttons + QDialogButtonBox *buttons = + new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); + QPushButton *default_btn = + buttons->addButton(tr("Set As Default"), QDialogButtonBox::ActionRole); + connect(buttons, &QDialogButtonBox::accepted, this, + &SequenceDialog::accept); + connect(buttons, &QDialogButtonBox::rejected, this, + &SequenceDialog::reject); + connect(default_btn, &QPushButton::clicked, this, + &SequenceDialog::SetAsDefaultClicked); + layout->addWidget(buttons); - name_field_->setText(sequence_->GetLabel()); + // Set window title based on type + switch (t) { + case kNew: + setWindowTitle(tr("New Sequence")); + break; + case kExisting: + setWindowTitle(tr("Editing \"%1\"").arg(sequence_->GetLabel())); + break; + } + + name_field_->setText(sequence_->GetLabel()); } void SequenceDialog::SetUndoable(bool u) { - make_undoable_ = u; + make_undoable_ = u; } void SequenceDialog::SetNameIsEditable(bool e) { - name_field_->setEnabled(e); + name_field_->setEnabled(e); } void SequenceDialog::accept() { - if (name_field_->isEnabled() && name_field_->text().isEmpty()) { - QtUtils::MsgBox(this, QMessageBox::Critical, tr("Error editing Sequence"), tr("Please enter a name for this Sequence.")); - return; - } + if (name_field_->isEnabled() && name_field_->text().isEmpty()) { + QtUtils::MsgBox(this, QMessageBox::Critical, + tr("Error editing Sequence"), + tr("Please enter a name for this Sequence.")); + return; + } - if (!VideoParams::FormatIsFloat(parameter_tab_->GetSelectedPreviewFormat()) - && !OLIVE_CONFIG("PreviewNonFloatDontAskAgain").toBool()) { - QMessageBox b(this); - QCheckBox *dont_show_again_ = new QCheckBox(tr("Don't ask me again")); + if (!VideoParams::FormatIsFloat( + parameter_tab_->GetSelectedPreviewFormat()) && + !OLIVE_CONFIG("PreviewNonFloatDontAskAgain").toBool()) { + QMessageBox b(this); + QCheckBox *dont_show_again_ = new QCheckBox(tr("Don't ask me again")); - b.setIcon(QMessageBox::Warning); - b.setWindowTitle(tr("Low Quality Preview")); - b.setText(tr("The preview resolution has been set to a non-float format. This may cause banding and clipping artifacts in the preview.\n\n" - "Do you wish to continue?")); - b.setCheckBox(dont_show_again_); + b.setIcon(QMessageBox::Warning); + b.setWindowTitle(tr("Low Quality Preview")); + b.setText(tr( + "The preview resolution has been set to a non-float format. This may cause banding and clipping artifacts in the preview.\n\n" + "Do you wish to continue?")); + b.setCheckBox(dont_show_again_); - b.addButton(QMessageBox::Yes); - b.addButton(QMessageBox::No); + b.addButton(QMessageBox::Yes); + b.addButton(QMessageBox::No); - if (b.exec() == QMessageBox::No) { - return; - } + if (b.exec() == QMessageBox::No) { + return; + } - if (dont_show_again_->isChecked()) { - OLIVE_CONFIG("PreviewNonFloatDontAskAgain") = true; - } - } + if (dont_show_again_->isChecked()) { + OLIVE_CONFIG("PreviewNonFloatDontAskAgain") = true; + } + } - // Generate video and audio parameter structs from data - VideoParams video_params = VideoParams(parameter_tab_->GetSelectedVideoWidth(), - parameter_tab_->GetSelectedVideoHeight(), - parameter_tab_->GetSelectedVideoFrameRate().flipped(), - parameter_tab_->GetSelectedPreviewFormat(), - VideoParams::kInternalChannelCount, - parameter_tab_->GetSelectedVideoPixelAspect(), - parameter_tab_->GetSelectedVideoInterlacingMode(), - parameter_tab_->GetSelectedPreviewResolution()); + // Generate video and audio parameter structs from data + VideoParams video_params = + VideoParams(parameter_tab_->GetSelectedVideoWidth(), + parameter_tab_->GetSelectedVideoHeight(), + parameter_tab_->GetSelectedVideoFrameRate().flipped(), + parameter_tab_->GetSelectedPreviewFormat(), + VideoParams::kInternalChannelCount, + parameter_tab_->GetSelectedVideoPixelAspect(), + parameter_tab_->GetSelectedVideoInterlacingMode(), + parameter_tab_->GetSelectedPreviewResolution()); - AudioParams audio_params = AudioParams(parameter_tab_->GetSelectedAudioSampleRate(), - parameter_tab_->GetSelectedAudioChannelLayout(), - Sequence::kDefaultSampleFormat); + AudioParams audio_params = + AudioParams(parameter_tab_->GetSelectedAudioSampleRate(), + parameter_tab_->GetSelectedAudioChannelLayout(), + Sequence::kDefaultSampleFormat); - if (make_undoable_) { + if (make_undoable_) { + // Make undoable command to change the parameters + SequenceParamCommand *param_command = new SequenceParamCommand( + sequence_, video_params, audio_params, name_field_->text(), + parameter_tab_->GetSelectedPreviewAutoCache()); - // Make undoable command to change the parameters - SequenceParamCommand* param_command = new SequenceParamCommand(sequence_, - video_params, - audio_params, - name_field_->text(), - parameter_tab_->GetSelectedPreviewAutoCache()); + Core::instance()->undo_stack()->push( + param_command, + tr("Set Sequence Parameters For \"%1\"").arg(sequence_->GetLabel())); - Core::instance()->undo_stack()->push(param_command, tr("Set Sequence Parameters For \"%1\"").arg(sequence_->GetLabel())); + } else { + // Set sequence values directly with no undo command + sequence_->SetVideoParams(video_params); + sequence_->SetAudioParams(audio_params); + sequence_->SetLabel(name_field_->text()); + sequence_->SetVideoAutoCacheEnabled( + parameter_tab_->GetSelectedPreviewAutoCache()); + } - } else { - // Set sequence values directly with no undo command - sequence_->SetVideoParams(video_params); - sequence_->SetAudioParams(audio_params); - sequence_->SetLabel(name_field_->text()); - sequence_->SetVideoAutoCacheEnabled(parameter_tab_->GetSelectedPreviewAutoCache()); - } - - QDialog::accept(); + QDialog::accept(); } void SequenceDialog::SetAsDefaultClicked() { - if (QtUtils::MsgBox(this, QMessageBox::Question, tr("Confirm Set As Default"), - tr("Are you sure you want to set the current parameters as defaults?"), - QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) { - // Maybe replace with Preset system - OLIVE_CONFIG("DefaultSequenceWidth") = parameter_tab_->GetSelectedVideoWidth(); - OLIVE_CONFIG("DefaultSequenceHeight") = parameter_tab_->GetSelectedVideoHeight(); - OLIVE_CONFIG("DefaultSequencePixelAspect") = QVariant::fromValue(parameter_tab_->GetSelectedVideoPixelAspect()); - OLIVE_CONFIG("DefaultSequenceFrameRate") = QVariant::fromValue(parameter_tab_->GetSelectedVideoFrameRate().flipped()); - OLIVE_CONFIG("DefaultSequenceInterlacing") = parameter_tab_->GetSelectedVideoInterlacingMode(); - OLIVE_CONFIG("DefaultSequenceAudioFrequency") = parameter_tab_->GetSelectedAudioSampleRate(); - OLIVE_CONFIG("DefaultSequenceAudioLayout") = QVariant::fromValue(parameter_tab_->GetSelectedAudioChannelLayout()); - } + if (QtUtils::MsgBox( + this, QMessageBox::Question, tr("Confirm Set As Default"), + tr("Are you sure you want to set the current parameters as defaults?"), + QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) { + // Maybe replace with Preset system + OLIVE_CONFIG("DefaultSequenceWidth") = + parameter_tab_->GetSelectedVideoWidth(); + OLIVE_CONFIG("DefaultSequenceHeight") = + parameter_tab_->GetSelectedVideoHeight(); + OLIVE_CONFIG("DefaultSequencePixelAspect") = + QVariant::fromValue(parameter_tab_->GetSelectedVideoPixelAspect()); + OLIVE_CONFIG("DefaultSequenceFrameRate") = QVariant::fromValue( + parameter_tab_->GetSelectedVideoFrameRate().flipped()); + OLIVE_CONFIG("DefaultSequenceInterlacing") = + parameter_tab_->GetSelectedVideoInterlacingMode(); + OLIVE_CONFIG("DefaultSequenceAudioFrequency") = + parameter_tab_->GetSelectedAudioSampleRate(); + OLIVE_CONFIG("DefaultSequenceAudioLayout") = QVariant::fromValue( + parameter_tab_->GetSelectedAudioChannelLayout()); + } } -SequenceDialog::SequenceParamCommand::SequenceParamCommand(Sequence* s, - const VideoParams& video_params, - const AudioParams &audio_params, - const QString& name, bool autocache) : - sequence_(s), - new_video_params_(video_params), - new_audio_params_(audio_params), - new_name_(name), - new_autocache_(autocache), - old_video_params_(s->GetVideoParams()), - old_audio_params_(s->GetAudioParams()), - old_name_(s->GetLabel()), - old_autocache_(s->IsVideoAutoCacheEnabled()) +SequenceDialog::SequenceParamCommand::SequenceParamCommand( + Sequence *s, const VideoParams &video_params, + const AudioParams &audio_params, const QString &name, bool autocache) + : sequence_(s) + , new_video_params_(video_params) + , new_audio_params_(audio_params) + , new_name_(name) + , new_autocache_(autocache) + , old_video_params_(s->GetVideoParams()) + , old_audio_params_(s->GetAudioParams()) + , old_name_(s->GetLabel()) + , old_autocache_(s->IsVideoAutoCacheEnabled()) { } Project *SequenceDialog::SequenceParamCommand::GetRelevantProject() const { - return sequence_->project(); + return sequence_->project(); } void SequenceDialog::SequenceParamCommand::redo() { - if (sequence_->GetVideoParams() != new_video_params_) { - sequence_->SetVideoParams(new_video_params_); - } - if (sequence_->GetAudioParams() != new_audio_params_) { - sequence_->SetAudioParams(new_audio_params_); - } - sequence_->SetLabel(new_name_); - sequence_->SetVideoAutoCacheEnabled(new_autocache_); + if (sequence_->GetVideoParams() != new_video_params_) { + sequence_->SetVideoParams(new_video_params_); + } + if (sequence_->GetAudioParams() != new_audio_params_) { + sequence_->SetAudioParams(new_audio_params_); + } + sequence_->SetLabel(new_name_); + sequence_->SetVideoAutoCacheEnabled(new_autocache_); } void SequenceDialog::SequenceParamCommand::undo() { - if (sequence_->GetVideoParams() != old_video_params_) { - sequence_->SetVideoParams(old_video_params_); - } - if (sequence_->GetAudioParams() != old_audio_params_) { - sequence_->SetAudioParams(old_audio_params_); - } - sequence_->SetLabel(old_name_); - sequence_->SetVideoAutoCacheEnabled(old_autocache_); + if (sequence_->GetVideoParams() != old_video_params_) { + sequence_->SetVideoParams(old_video_params_); + } + if (sequence_->GetAudioParams() != old_audio_params_) { + sequence_->SetAudioParams(old_audio_params_); + } + sequence_->SetLabel(old_name_); + sequence_->SetVideoAutoCacheEnabled(old_autocache_); } } diff --git a/app/dialog/sequence/sequence.h b/app/dialog/sequence/sequence.h index cb3862127..cfc4af3ef 100644 --- a/app/dialog/sequence/sequence.h +++ b/app/dialog/sequence/sequence.h @@ -30,7 +30,8 @@ #include "sequencedialogpresettab.h" #include "undo/undocommand.h" -namespace olive { +namespace olive +{ /** * @brief A dialog for editing Sequence parameters @@ -46,19 +47,15 @@ namespace olive { * latter will be the main undoable action, the parameter editing doesn't have to be undoable since to the user they'll * be viewed as one single action (see SetUndoable()). */ -class SequenceDialog : public QDialog -{ - Q_OBJECT +class SequenceDialog : public QDialog { + Q_OBJECT public: - /** + /** * @brief Used to set the dialog mode of operation (see SequenceDialog()) */ - enum Type { - kNew, - kExisting - }; + enum Type { kNew, kExisting }; - /** + /** * @brief SequenceDialog Constructor * * @param s @@ -70,73 +67,70 @@ public: * @param parent * QWidget parent */ - SequenceDialog(Sequence* s, Type t = kExisting, QWidget* parent = nullptr); + SequenceDialog(Sequence *s, Type t = kExisting, QWidget *parent = nullptr); - /** + /** * @brief Set whether the parameter changes should be made into an undo command or not * * Defaults to true. */ - void SetUndoable(bool u); + void SetUndoable(bool u); - /** + /** * @brief Set whether the name of this Sequence can be edited with this dialog * * Defaults to true. */ - void SetNameIsEditable(bool e); + void SetNameIsEditable(bool e); public slots: - /** + /** * @brief Function called when the user presses OK */ - virtual void accept() override; + virtual void accept() override; private: - Sequence* sequence_; + Sequence *sequence_; - SequenceDialogPresetTab* preset_tab_; + SequenceDialogPresetTab *preset_tab_; - SequenceDialogParameterTab* parameter_tab_; + SequenceDialogParameterTab *parameter_tab_; - bool make_undoable_; + bool make_undoable_; - QLineEdit* name_field_; + QLineEdit *name_field_; - /** + /** * @brief An UndoCommand for setting the parameters on a sequence */ - class SequenceParamCommand : public UndoCommand { - public: - SequenceParamCommand(Sequence* s, - const VideoParams& video_params, - const AudioParams& audio_params, - const QString& name, - bool autocache); + class SequenceParamCommand : public UndoCommand { + public: + SequenceParamCommand(Sequence *s, const VideoParams &video_params, + const AudioParams &audio_params, + const QString &name, bool autocache); - virtual Project* GetRelevantProject() const override; + virtual Project *GetRelevantProject() const override; - protected: - virtual void redo() override; - virtual void undo() override; + protected: + virtual void redo() override; + virtual void undo() override; - private: - Sequence* sequence_; + private: + Sequence *sequence_; - VideoParams new_video_params_; - AudioParams new_audio_params_; - QString new_name_; - bool new_autocache_; + VideoParams new_video_params_; + AudioParams new_audio_params_; + QString new_name_; + bool new_autocache_; - VideoParams old_video_params_; - AudioParams old_audio_params_; - QString old_name_; - bool old_autocache_; - }; + VideoParams old_video_params_; + AudioParams old_audio_params_; + QString old_name_; + bool old_autocache_; + }; private slots: - void SetAsDefaultClicked(); - + void SetAsDefaultClicked(); }; } diff --git a/app/dialog/sequence/sequencedialogparametertab.cpp b/app/dialog/sequence/sequencedialogparametertab.cpp index 4f25e176a..d615a77d4 100644 --- a/app/dialog/sequence/sequencedialogparametertab.cpp +++ b/app/dialog/sequence/sequencedialogparametertab.cpp @@ -7,150 +7,149 @@ #include "core.h" -namespace olive { - -SequenceDialogParameterTab::SequenceDialogParameterTab(Sequence* sequence, QWidget* parent) : - QWidget(parent) +namespace olive { - QVBoxLayout* layout = new QVBoxLayout(this); - int row = 0; +SequenceDialogParameterTab::SequenceDialogParameterTab(Sequence *sequence, + QWidget *parent) + : QWidget(parent) +{ + QVBoxLayout *layout = new QVBoxLayout(this); - // Set up video section - QGroupBox* video_group = new QGroupBox(); - video_group->setTitle(tr("Video")); - QGridLayout *video_layout = new QGridLayout(video_group); - video_layout->addWidget(new QLabel(tr("Width:")), row, 0); - width_slider_ = new IntegerSlider(); - width_slider_->SetMinimum(0); - video_layout->addWidget(width_slider_, row, 1); - row++; - video_layout->addWidget(new QLabel(tr("Height:")), row, 0); - height_slider_ = new IntegerSlider(); - height_slider_->SetMinimum(0); - video_layout->addWidget(height_slider_, row, 1); - row++; - video_layout->addWidget(new QLabel(tr("Frame Rate:")), row, 0); - framerate_combo_ = new FrameRateComboBox(); - video_layout->addWidget(framerate_combo_, row, 1); - row++; - video_layout->addWidget(new QLabel(tr("Pixel Aspect Ratio:")), row, 0); - pixelaspect_combo_ = new PixelAspectRatioComboBox(); - video_layout->addWidget(pixelaspect_combo_, row, 1); - row++; - video_layout->addWidget(new QLabel(tr("Interlacing:")), row, 0); - interlacing_combo_ = new InterlacedComboBox(); - video_layout->addWidget(interlacing_combo_, row, 1); - layout->addWidget(video_group); + int row = 0; - row = 0; + // Set up video section + QGroupBox *video_group = new QGroupBox(); + video_group->setTitle(tr("Video")); + QGridLayout *video_layout = new QGridLayout(video_group); + video_layout->addWidget(new QLabel(tr("Width:")), row, 0); + width_slider_ = new IntegerSlider(); + width_slider_->SetMinimum(0); + video_layout->addWidget(width_slider_, row, 1); + row++; + video_layout->addWidget(new QLabel(tr("Height:")), row, 0); + height_slider_ = new IntegerSlider(); + height_slider_->SetMinimum(0); + video_layout->addWidget(height_slider_, row, 1); + row++; + video_layout->addWidget(new QLabel(tr("Frame Rate:")), row, 0); + framerate_combo_ = new FrameRateComboBox(); + video_layout->addWidget(framerate_combo_, row, 1); + row++; + video_layout->addWidget(new QLabel(tr("Pixel Aspect Ratio:")), row, 0); + pixelaspect_combo_ = new PixelAspectRatioComboBox(); + video_layout->addWidget(pixelaspect_combo_, row, 1); + row++; + video_layout->addWidget(new QLabel(tr("Interlacing:")), row, 0); + interlacing_combo_ = new InterlacedComboBox(); + video_layout->addWidget(interlacing_combo_, row, 1); + layout->addWidget(video_group); - // Set up audio section - QGroupBox* audio_group = new QGroupBox(); - audio_group->setTitle(tr("Audio")); - QGridLayout* audio_layout = new QGridLayout(audio_group); - audio_layout->addWidget(new QLabel(tr("Sample Rate:")), row, 0); - audio_sample_rate_field_ = new SampleRateComboBox(); - audio_layout->addWidget(audio_sample_rate_field_, row, 1); - row++; - audio_layout->addWidget(new QLabel(tr("Channels:")), row, 0); - audio_channels_field_ = new ChannelLayoutComboBox(); - audio_layout->addWidget(audio_channels_field_, row, 1); - layout->addWidget(audio_group); + row = 0; - row = 0; + // Set up audio section + QGroupBox *audio_group = new QGroupBox(); + audio_group->setTitle(tr("Audio")); + QGridLayout *audio_layout = new QGridLayout(audio_group); + audio_layout->addWidget(new QLabel(tr("Sample Rate:")), row, 0); + audio_sample_rate_field_ = new SampleRateComboBox(); + audio_layout->addWidget(audio_sample_rate_field_, row, 1); + row++; + audio_layout->addWidget(new QLabel(tr("Channels:")), row, 0); + audio_channels_field_ = new ChannelLayoutComboBox(); + audio_layout->addWidget(audio_channels_field_, row, 1); + layout->addWidget(audio_group); - // Set up preview section - QGroupBox* preview_group = new QGroupBox(); - preview_group->setTitle(tr("Preview")); - QGridLayout* preview_layout = new QGridLayout(preview_group); - preview_layout->addWidget(new QLabel(tr("Resolution:")), row, 0); - preview_resolution_field_ = new VideoDividerComboBox(); - preview_layout->addWidget(preview_resolution_field_, row, 1); - preview_resolution_label_ = new QLabel(); - preview_layout->addWidget(preview_resolution_label_, row, 2); - row++; - preview_layout->addWidget(new QLabel(tr("Quality:")), row, 0); - preview_format_field_ = new PixelFormatComboBox(false); - preview_layout->addWidget(preview_format_field_, row, 1, 1, 2); + row = 0; - /* TEMP: Disable sequence auto-cache, wanna see if clip cache supersedes it. + // Set up preview section + QGroupBox *preview_group = new QGroupBox(); + preview_group->setTitle(tr("Preview")); + QGridLayout *preview_layout = new QGridLayout(preview_group); + preview_layout->addWidget(new QLabel(tr("Resolution:")), row, 0); + preview_resolution_field_ = new VideoDividerComboBox(); + preview_layout->addWidget(preview_resolution_field_, row, 1); + preview_resolution_label_ = new QLabel(); + preview_layout->addWidget(preview_resolution_label_, row, 2); + row++; + preview_layout->addWidget(new QLabel(tr("Quality:")), row, 0); + preview_format_field_ = new PixelFormatComboBox(false); + preview_layout->addWidget(preview_format_field_, row, 1, 1, 2); + + /* TEMP: Disable sequence auto-cache, wanna see if clip cache supersedes it. row++; preview_layout->addWidget(new QLabel(tr("Auto-Cache:")), row, 0); preview_layout->addWidget(preview_autocache_field_, row, 1);*/ - preview_autocache_field_ = new QCheckBox(); + preview_autocache_field_ = new QCheckBox(); - layout->addWidget(preview_group); + layout->addWidget(preview_group); - // Set values based on input sequence - VideoParams vp = sequence->GetVideoParams(); - AudioParams ap = sequence->GetAudioParams(); - width_slider_->SetValue(vp.width()); - height_slider_->SetValue(vp.height()); - framerate_combo_->SetFrameRate(vp.time_base().flipped()); - pixelaspect_combo_->SetPixelAspectRatio(vp.pixel_aspect_ratio()); - interlacing_combo_->SetInterlaceMode(vp.interlacing()); - preview_resolution_field_->SetDivider(vp.divider()); - preview_format_field_->SetPixelFormat(vp.format()); - preview_autocache_field_->setChecked(sequence->IsVideoAutoCacheEnabled()); - audio_sample_rate_field_->SetSampleRate(ap.sample_rate()); - audio_channels_field_->SetChannelLayout(ap.channel_layout()); + // Set values based on input sequence + VideoParams vp = sequence->GetVideoParams(); + AudioParams ap = sequence->GetAudioParams(); + width_slider_->SetValue(vp.width()); + height_slider_->SetValue(vp.height()); + framerate_combo_->SetFrameRate(vp.time_base().flipped()); + pixelaspect_combo_->SetPixelAspectRatio(vp.pixel_aspect_ratio()); + interlacing_combo_->SetInterlaceMode(vp.interlacing()); + preview_resolution_field_->SetDivider(vp.divider()); + preview_format_field_->SetPixelFormat(vp.format()); + preview_autocache_field_->setChecked(sequence->IsVideoAutoCacheEnabled()); + audio_sample_rate_field_->SetSampleRate(ap.sample_rate()); + audio_channels_field_->SetChannelLayout(ap.channel_layout()); - connect(preview_resolution_field_, static_cast(&QComboBox::currentIndexChanged), - this, &SequenceDialogParameterTab::UpdatePreviewResolutionLabel); + connect( + preview_resolution_field_, + static_cast(&QComboBox::currentIndexChanged), + this, &SequenceDialogParameterTab::UpdatePreviewResolutionLabel); - layout->addStretch(); + layout->addStretch(); - QPushButton* save_preset_btn = new QPushButton(tr("Save Preset")); - connect(save_preset_btn, &QPushButton::clicked, this, &SequenceDialogParameterTab::SavePresetClicked); - layout->addWidget(save_preset_btn); + QPushButton *save_preset_btn = new QPushButton(tr("Save Preset")); + connect(save_preset_btn, &QPushButton::clicked, this, + &SequenceDialogParameterTab::SavePresetClicked); + layout->addWidget(save_preset_btn); - UpdatePreviewResolutionLabel(); + UpdatePreviewResolutionLabel(); } void SequenceDialogParameterTab::PresetChanged(const SequencePreset &preset) { - width_slider_->SetValue(preset.width()); - height_slider_->SetValue(preset.height()); - framerate_combo_->SetFrameRate(preset.frame_rate()); - pixelaspect_combo_->SetPixelAspectRatio(preset.pixel_aspect()); - interlacing_combo_->SetInterlaceMode(preset.interlacing()); - audio_sample_rate_field_->SetSampleRate(preset.sample_rate()); - audio_channels_field_->SetChannelLayout(preset.channel_layout()); - preview_resolution_field_->SetDivider(preset.preview_divider()); - preview_format_field_->SetPixelFormat(preset.preview_format()); - preview_autocache_field_->setChecked(preset.preview_autocache()); + width_slider_->SetValue(preset.width()); + height_slider_->SetValue(preset.height()); + framerate_combo_->SetFrameRate(preset.frame_rate()); + pixelaspect_combo_->SetPixelAspectRatio(preset.pixel_aspect()); + interlacing_combo_->SetInterlaceMode(preset.interlacing()); + audio_sample_rate_field_->SetSampleRate(preset.sample_rate()); + audio_channels_field_->SetChannelLayout(preset.channel_layout()); + preview_resolution_field_->SetDivider(preset.preview_divider()); + preview_format_field_->SetPixelFormat(preset.preview_format()); + preview_autocache_field_->setChecked(preset.preview_autocache()); } void SequenceDialogParameterTab::SavePresetClicked() { - AVChannelLayout layout=GetSelectedAudioChannelLayout(); - emit SaveParametersAsPreset(SequencePreset(QString(), - GetSelectedVideoWidth(), - GetSelectedVideoHeight(), - GetSelectedVideoFrameRate(), - GetSelectedVideoPixelAspect(), - GetSelectedVideoInterlacingMode(), - GetSelectedAudioSampleRate(), - layout, - GetSelectedPreviewResolution(), - GetSelectedPreviewFormat(), - GetSelectedPreviewAutoCache())); - av_channel_layout_uninit(&layout); + AVChannelLayout layout = GetSelectedAudioChannelLayout(); + emit SaveParametersAsPreset(SequencePreset( + QString(), GetSelectedVideoWidth(), GetSelectedVideoHeight(), + GetSelectedVideoFrameRate(), GetSelectedVideoPixelAspect(), + GetSelectedVideoInterlacingMode(), GetSelectedAudioSampleRate(), layout, + GetSelectedPreviewResolution(), GetSelectedPreviewFormat(), + GetSelectedPreviewAutoCache())); + av_channel_layout_uninit(&layout); } void SequenceDialogParameterTab::UpdatePreviewResolutionLabel() { - VideoParams test_param(GetSelectedVideoWidth(), - GetSelectedVideoHeight(), - PixelFormat::INVALID, - VideoParams::kInternalChannelCount, - rational(1), - VideoParams::kInterlaceNone, - preview_resolution_field_->currentData().toInt()); + VideoParams test_param(GetSelectedVideoWidth(), GetSelectedVideoHeight(), + PixelFormat::INVALID, + VideoParams::kInternalChannelCount, rational(1), + VideoParams::kInterlaceNone, + preview_resolution_field_->currentData().toInt()); - preview_resolution_label_->setText(tr("(%1x%2)").arg(QString::number(test_param.effective_width()), - QString::number(test_param.effective_height()))); + preview_resolution_label_->setText( + tr("(%1x%2)").arg(QString::number(test_param.effective_width()), + QString::number(test_param.effective_height()))); } } diff --git a/app/dialog/sequence/sequencedialogparametertab.h b/app/dialog/sequence/sequencedialogparametertab.h index 7880344ca..dd71fba9b 100644 --- a/app/dialog/sequence/sequencedialogparametertab.h +++ b/app/dialog/sequence/sequencedialogparametertab.h @@ -11,97 +11,99 @@ #include "widget/slider/integerslider.h" #include "widget/standardcombos/standardcombos.h" -namespace olive { - -class SequenceDialogParameterTab : public QWidget +namespace olive { - Q_OBJECT + +class SequenceDialogParameterTab : public QWidget { + Q_OBJECT public: - SequenceDialogParameterTab(Sequence* sequence, QWidget* parent = nullptr); + SequenceDialogParameterTab(Sequence *sequence, QWidget *parent = nullptr); - int GetSelectedVideoWidth() const - { - return width_slider_->GetValue(); - } + int GetSelectedVideoWidth() const + { + return width_slider_->GetValue(); + } - int GetSelectedVideoHeight() const - { - return height_slider_->GetValue(); - } + int GetSelectedVideoHeight() const + { + return height_slider_->GetValue(); + } - rational GetSelectedVideoFrameRate() const - { - return framerate_combo_->GetFrameRate(); - } + rational GetSelectedVideoFrameRate() const + { + return framerate_combo_->GetFrameRate(); + } - rational GetSelectedVideoPixelAspect() const - { - return pixelaspect_combo_->GetPixelAspectRatio(); - } + rational GetSelectedVideoPixelAspect() const + { + return pixelaspect_combo_->GetPixelAspectRatio(); + } - VideoParams::Interlacing GetSelectedVideoInterlacingMode() const - { - return interlacing_combo_->GetInterlaceMode(); - } + VideoParams::Interlacing GetSelectedVideoInterlacingMode() const + { + return interlacing_combo_->GetInterlaceMode(); + } - int GetSelectedAudioSampleRate() const { return audio_sample_rate_field_->GetSampleRate(); } + int GetSelectedAudioSampleRate() const + { + return audio_sample_rate_field_->GetSampleRate(); + } - [[nodiscard]] AVChannelLayout GetSelectedAudioChannelLayout() const - { - return audio_channels_field_->GetChannelLayout(); - } + [[nodiscard]] AVChannelLayout GetSelectedAudioChannelLayout() const + { + return audio_channels_field_->GetChannelLayout(); + } - int GetSelectedPreviewResolution() const - { - return preview_resolution_field_->GetDivider(); - } + int GetSelectedPreviewResolution() const + { + return preview_resolution_field_->GetDivider(); + } - PixelFormat GetSelectedPreviewFormat() const - { - return preview_format_field_->GetPixelFormat(); - } + PixelFormat GetSelectedPreviewFormat() const + { + return preview_format_field_->GetPixelFormat(); + } - bool GetSelectedPreviewAutoCache() const - { - //return preview_autocache_field_->isChecked(); - // TEMP: Disable sequence auto-cache, wanna see if clip cache supersedes it. - return false; - } + bool GetSelectedPreviewAutoCache() const + { + //return preview_autocache_field_->isChecked(); + // TEMP: Disable sequence auto-cache, wanna see if clip cache supersedes it. + return false; + } public slots: - void PresetChanged(const SequencePreset& preset); + void PresetChanged(const SequencePreset &preset); signals: - void SaveParametersAsPreset(const SequencePreset& preset); + void SaveParametersAsPreset(const SequencePreset &preset); private: - IntegerSlider *width_slider_; + IntegerSlider *width_slider_; - IntegerSlider *height_slider_; + IntegerSlider *height_slider_; - FrameRateComboBox *framerate_combo_; + FrameRateComboBox *framerate_combo_; - PixelAspectRatioComboBox *pixelaspect_combo_; + PixelAspectRatioComboBox *pixelaspect_combo_; - InterlacedComboBox *interlacing_combo_; + InterlacedComboBox *interlacing_combo_; - SampleRateComboBox* audio_sample_rate_field_; + SampleRateComboBox *audio_sample_rate_field_; - ChannelLayoutComboBox* audio_channels_field_; + ChannelLayoutComboBox *audio_channels_field_; - VideoDividerComboBox* preview_resolution_field_; + VideoDividerComboBox *preview_resolution_field_; - QLabel* preview_resolution_label_; + QLabel *preview_resolution_label_; - PixelFormatComboBox* preview_format_field_; + PixelFormatComboBox *preview_format_field_; - QCheckBox *preview_autocache_field_; + QCheckBox *preview_autocache_field_; private slots: - void SavePresetClicked(); - - void UpdatePreviewResolutionLabel(); + void SavePresetClicked(); + void UpdatePreviewResolutionLabel(); }; } diff --git a/app/dialog/sequence/sequencedialogpresettab.cpp b/app/dialog/sequence/sequencedialogpresettab.cpp index d0fa8b80e..2510b01c0 100644 --- a/app/dialog/sequence/sequencedialogpresettab.cpp +++ b/app/dialog/sequence/sequencedialogpresettab.cpp @@ -35,279 +35,269 @@ #include "ui/icons/icons.h" #include "widget/menu/menu.h" -namespace olive { +namespace olive +{ const int kDataIsPreset = Qt::UserRole; const int kDataPresetIsCustomRole = Qt::UserRole + 1; const int kDataPresetDataRole = Qt::UserRole + 2; -SequenceDialogPresetTab::SequenceDialogPresetTab(QWidget* parent) : - QWidget(parent), - PresetManager(this, QStringLiteral("sequencepresets")) +SequenceDialogPresetTab::SequenceDialogPresetTab(QWidget *parent) + : QWidget(parent) + , PresetManager(this, QStringLiteral("sequencepresets")) { - QVBoxLayout* outer_layout = new QVBoxLayout(this); - outer_layout->setContentsMargins(0, 0, 0, 0); + QVBoxLayout *outer_layout = new QVBoxLayout(this); + outer_layout->setContentsMargins(0, 0, 0, 0); - preset_tree_ = new QTreeWidget(); - preset_tree_->setColumnCount(1); - preset_tree_->setHeaderLabel(tr("Preset")); - preset_tree_->setContextMenuPolicy(Qt::CustomContextMenu); - connect(preset_tree_, &QTreeWidget::customContextMenuRequested, this, &SequenceDialogPresetTab::ShowContextMenu); - outer_layout->addWidget(preset_tree_); - connect(preset_tree_, &QTreeWidget::currentItemChanged, this, &SequenceDialogPresetTab::SelectedItemChanged); - connect(preset_tree_, &QTreeWidget::itemDoubleClicked, this, &SequenceDialogPresetTab::ItemDoubleClicked); + preset_tree_ = new QTreeWidget(); + preset_tree_->setColumnCount(1); + preset_tree_->setHeaderLabel(tr("Preset")); + preset_tree_->setContextMenuPolicy(Qt::CustomContextMenu); + connect(preset_tree_, &QTreeWidget::customContextMenuRequested, this, + &SequenceDialogPresetTab::ShowContextMenu); + outer_layout->addWidget(preset_tree_); + connect(preset_tree_, &QTreeWidget::currentItemChanged, this, + &SequenceDialogPresetTab::SelectedItemChanged); + connect(preset_tree_, &QTreeWidget::itemDoubleClicked, this, + &SequenceDialogPresetTab::ItemDoubleClicked); - // Add "my presets" folder - my_presets_folder_ = CreateFolder(tr("My Presets")); - preset_tree_->addTopLevelItem(my_presets_folder_); + // Add "my presets" folder + my_presets_folder_ = CreateFolder(tr("My Presets")); + preset_tree_->addTopLevelItem(my_presets_folder_); - // Add presets - preset_tree_->addTopLevelItem(CreateHDPresetFolder(tr("4K UHD"), 3840, 2160, 2)); - preset_tree_->addTopLevelItem(CreateHDPresetFolder(tr("1080p"), 1920, 1080, 1)); - preset_tree_->addTopLevelItem(CreateHDPresetFolder(tr("720p"), 1280, 720, 1)); + // Add presets + preset_tree_->addTopLevelItem( + CreateHDPresetFolder(tr("4K UHD"), 3840, 2160, 2)); + preset_tree_->addTopLevelItem( + CreateHDPresetFolder(tr("1080p"), 1920, 1080, 1)); + preset_tree_->addTopLevelItem( + CreateHDPresetFolder(tr("720p"), 1280, 720, 1)); - preset_tree_->addTopLevelItem(CreateSDPresetFolder(tr("NTSC"), 720, 480, rational(30000, 1001), - VideoParams::kPixelAspectNTSCStandard, - VideoParams::kPixelAspectNTSCWidescreen, 1)); - preset_tree_->addTopLevelItem(CreateSDPresetFolder(tr("PAL"), 720, 576, rational(25, 1), - VideoParams::kPixelAspectPALStandard, - VideoParams::kPixelAspectPALWidescreen, 1)); + preset_tree_->addTopLevelItem( + CreateSDPresetFolder(tr("NTSC"), 720, 480, rational(30000, 1001), + VideoParams::kPixelAspectNTSCStandard, + VideoParams::kPixelAspectNTSCWidescreen, 1)); + preset_tree_->addTopLevelItem( + CreateSDPresetFolder(tr("PAL"), 720, 576, rational(25, 1), + VideoParams::kPixelAspectPALStandard, + VideoParams::kPixelAspectPALWidescreen, 1)); - // Load custom presets - for (int i=0;i(preset); + PresetPtr preset_ptr = std::make_shared(preset); - // If replaced, no need to make another item. If not saved, shared ptr will delete itself - if (SavePreset(preset_ptr) == kAppended) { - AddCustomItem(my_presets_folder_, preset_ptr, GetNumberOfPresets() - 1); - } + // If replaced, no need to make another item. If not saved, shared ptr will delete itself + if (SavePreset(preset_ptr) == kAppended) { + AddCustomItem(my_presets_folder_, preset_ptr, GetNumberOfPresets() - 1); + } } -QTreeWidgetItem* SequenceDialogPresetTab::CreateFolder(const QString &name) +QTreeWidgetItem *SequenceDialogPresetTab::CreateFolder(const QString &name) { - QTreeWidgetItem* folder = new QTreeWidgetItem(); - folder->setText(0, name); - folder->setIcon(0, icon::Folder); - return folder; + QTreeWidgetItem *folder = new QTreeWidgetItem(); + folder->setText(0, name); + folder->setIcon(0, icon::Folder); + return folder; } -QTreeWidgetItem *SequenceDialogPresetTab::CreateHDPresetFolder(const QString &name, int width, int height, int divider) +QTreeWidgetItem * +SequenceDialogPresetTab::CreateHDPresetFolder(const QString &name, int width, + int height, int divider) { - const PixelFormat default_format = static_cast(OLIVE_CONFIG("OfflinePixelFormat").toInt()); - const bool default_autocache = false; - QTreeWidgetItem* parent = CreateFolder(name); - AVChannelLayout layout; - av_channel_layout_from_mask(&layout, AV_CH_LAYOUT_STEREO); - AddStandardItem(parent, std::make_shared(tr("%1 23.976 FPS").arg(name), - width, - height, - rational(24000, 1001), - VideoParams::kPixelAspectSquare, - VideoParams::kInterlaceNone, - 48000, - layout, - divider, - default_format, - default_autocache)); - AddStandardItem(parent, std::make_shared(tr("%1 25 FPS").arg(name), - width, - height, - rational(25, 1), - VideoParams::kPixelAspectSquare, - VideoParams::kInterlaceNone, - 48000, - layout, - divider, - default_format, - default_autocache)); - AddStandardItem(parent, std::make_shared(tr("%1 29.97 FPS").arg(name), - width, - height, - rational(30000, 1001), - VideoParams::kPixelAspectSquare, - VideoParams::kInterlaceNone, - 48000, - layout, - divider, - default_format, - default_autocache)); - AddStandardItem(parent, std::make_shared(tr("%1 50 FPS").arg(name), - width, - height, - rational(50, 1), - VideoParams::kPixelAspectSquare, - VideoParams::kInterlaceNone, - 48000, - layout, - divider, - default_format, - default_autocache)); - AddStandardItem(parent, std::make_shared(tr("%1 59.94 FPS").arg(name), - width, - height, - rational(60000, 1001), - VideoParams::kPixelAspectSquare, - VideoParams::kInterlaceNone, - 48000, - layout, - divider, - default_format, - default_autocache)); - av_channel_layout_uninit(&layout); - return parent; + const PixelFormat default_format = static_cast( + OLIVE_CONFIG("OfflinePixelFormat").toInt()); + const bool default_autocache = false; + QTreeWidgetItem *parent = CreateFolder(name); + AVChannelLayout layout; + av_channel_layout_from_mask(&layout, AV_CH_LAYOUT_STEREO); + AddStandardItem(parent, + std::make_shared( + tr("%1 23.976 FPS").arg(name), width, height, + rational(24000, 1001), VideoParams::kPixelAspectSquare, + VideoParams::kInterlaceNone, 48000, layout, divider, + default_format, default_autocache)); + AddStandardItem(parent, + std::make_shared( + tr("%1 25 FPS").arg(name), width, height, + rational(25, 1), VideoParams::kPixelAspectSquare, + VideoParams::kInterlaceNone, 48000, layout, divider, + default_format, default_autocache)); + AddStandardItem(parent, + std::make_shared( + tr("%1 29.97 FPS").arg(name), width, height, + rational(30000, 1001), VideoParams::kPixelAspectSquare, + VideoParams::kInterlaceNone, 48000, layout, divider, + default_format, default_autocache)); + AddStandardItem(parent, + std::make_shared( + tr("%1 50 FPS").arg(name), width, height, + rational(50, 1), VideoParams::kPixelAspectSquare, + VideoParams::kInterlaceNone, 48000, layout, divider, + default_format, default_autocache)); + AddStandardItem(parent, + std::make_shared( + tr("%1 59.94 FPS").arg(name), width, height, + rational(60000, 1001), VideoParams::kPixelAspectSquare, + VideoParams::kInterlaceNone, 48000, layout, divider, + default_format, default_autocache)); + av_channel_layout_uninit(&layout); + return parent; } -QTreeWidgetItem *SequenceDialogPresetTab::CreateSDPresetFolder(const QString &name, int width, int height, const rational& frame_rate, const rational &standard_par, const rational &wide_par, int divider) +QTreeWidgetItem *SequenceDialogPresetTab::CreateSDPresetFolder( + const QString &name, int width, int height, const rational &frame_rate, + const rational &standard_par, const rational &wide_par, int divider) { - const PixelFormat default_format = static_cast(OLIVE_CONFIG("OfflinePixelFormat").toInt()); - const bool default_autocache = false; - QTreeWidgetItem* parent = CreateFolder(name); - preset_tree_->addTopLevelItem(parent); - AVChannelLayout layout; - av_channel_layout_from_mask(&layout,AV_CH_LAYOUT_STEREO); - AddStandardItem(parent, std::make_shared(tr("%1 Standard").arg(name), - width, - height, - frame_rate, - standard_par, - VideoParams::kInterlacedBottomFirst, - 48000, - layout, - divider, - default_format, - default_autocache)); - AddStandardItem(parent, std::make_shared(tr("%1 Widescreen").arg(name), - width, - height, - frame_rate, - wide_par, - VideoParams::kInterlacedBottomFirst, - 48000, - layout, - divider, - default_format, - default_autocache)); - av_channel_layout_uninit(&layout); - return parent; + const PixelFormat default_format = static_cast( + OLIVE_CONFIG("OfflinePixelFormat").toInt()); + const bool default_autocache = false; + QTreeWidgetItem *parent = CreateFolder(name); + preset_tree_->addTopLevelItem(parent); + AVChannelLayout layout; + av_channel_layout_from_mask(&layout, AV_CH_LAYOUT_STEREO); + AddStandardItem( + parent, std::make_shared( + tr("%1 Standard").arg(name), width, height, frame_rate, + standard_par, VideoParams::kInterlacedBottomFirst, 48000, + layout, divider, default_format, default_autocache)); + AddStandardItem( + parent, std::make_shared( + tr("%1 Widescreen").arg(name), width, height, frame_rate, + wide_par, VideoParams::kInterlacedBottomFirst, 48000, + layout, divider, default_format, default_autocache)); + av_channel_layout_uninit(&layout); + return parent; } QTreeWidgetItem *SequenceDialogPresetTab::GetSelectedItem() { - QList selected_items = preset_tree_->selectedItems(); + QList selected_items = preset_tree_->selectedItems(); - if (selected_items.isEmpty()) { - return nullptr; - } else { - return selected_items.first(); - } + if (selected_items.isEmpty()) { + return nullptr; + } else { + return selected_items.first(); + } } QTreeWidgetItem *SequenceDialogPresetTab::GetSelectedCustomPreset() { - QTreeWidgetItem* sel = GetSelectedItem(); + QTreeWidgetItem *sel = GetSelectedItem(); - if (sel - && sel->data(0, kDataIsPreset).toBool() - && sel->data(0, kDataPresetIsCustomRole).toBool()) { - return sel; - } + if (sel && sel->data(0, kDataIsPreset).toBool() && + sel->data(0, kDataPresetIsCustomRole).toBool()) { + return sel; + } - return nullptr; + return nullptr; } -void SequenceDialogPresetTab::AddStandardItem(QTreeWidgetItem *folder, PresetPtr preset, const QString& description) +void SequenceDialogPresetTab::AddStandardItem(QTreeWidgetItem *folder, + PresetPtr preset, + const QString &description) { - int index = default_preset_data_.size(); - default_preset_data_.append(preset); - AddItemInternal(folder, preset, false, index, description); + int index = default_preset_data_.size(); + default_preset_data_.append(preset); + AddItemInternal(folder, preset, false, index, description); } -void SequenceDialogPresetTab::AddCustomItem(QTreeWidgetItem *folder, PresetPtr preset, int index, const QString &description) +void SequenceDialogPresetTab::AddCustomItem(QTreeWidgetItem *folder, + PresetPtr preset, int index, + const QString &description) { - AddItemInternal(folder, preset, true, index, description); + AddItemInternal(folder, preset, true, index, description); } -void SequenceDialogPresetTab::AddItemInternal(QTreeWidgetItem *folder, PresetPtr preset, bool is_custom, int index, const QString &description) +void SequenceDialogPresetTab::AddItemInternal(QTreeWidgetItem *folder, + PresetPtr preset, bool is_custom, + int index, + const QString &description) { - QTreeWidgetItem* item = new QTreeWidgetItem(); + QTreeWidgetItem *item = new QTreeWidgetItem(); - item->setText(0, preset->GetName()); - item->setIcon(0, icon::Video); - item->setToolTip(0, description); - item->setData(0, kDataIsPreset, true); - item->setData(0, kDataPresetIsCustomRole, is_custom); - item->setData(0, kDataPresetDataRole, index); + item->setText(0, preset->GetName()); + item->setIcon(0, icon::Video); + item->setToolTip(0, description); + item->setData(0, kDataIsPreset, true); + item->setData(0, kDataPresetIsCustomRole, is_custom); + item->setData(0, kDataPresetDataRole, index); - folder->addChild(item); + folder->addChild(item); } -void SequenceDialogPresetTab::SelectedItemChanged(QTreeWidgetItem* current, QTreeWidgetItem* previous) +void SequenceDialogPresetTab::SelectedItemChanged(QTreeWidgetItem *current, + QTreeWidgetItem *previous) { - Q_UNUSED(previous) + Q_UNUSED(previous) - if (current->data(0, kDataIsPreset).toBool()) { - int preset_index = current->data(0, kDataPresetDataRole).toInt(); + if (current->data(0, kDataIsPreset).toBool()) { + int preset_index = current->data(0, kDataPresetDataRole).toInt(); - PresetPtr preset_data = (current->data(0, kDataPresetIsCustomRole).toBool()) - ? GetPreset(preset_index) - : default_preset_data_.at(preset_index); + PresetPtr preset_data = + (current->data(0, kDataPresetIsCustomRole).toBool()) ? + GetPreset(preset_index) : + default_preset_data_.at(preset_index); - emit PresetChanged(*static_cast(preset_data.get())); - } + emit PresetChanged(*static_cast(preset_data.get())); + } } -void SequenceDialogPresetTab::ItemDoubleClicked(QTreeWidgetItem *item, int column) +void SequenceDialogPresetTab::ItemDoubleClicked(QTreeWidgetItem *item, + int column) { - Q_UNUSED(column) + Q_UNUSED(column) - if (item->data(0, kDataIsPreset).toBool()) { - emit PresetAccepted(); - } + if (item->data(0, kDataIsPreset).toBool()) { + emit PresetAccepted(); + } } void SequenceDialogPresetTab::ShowContextMenu() { - QTreeWidgetItem* sel = GetSelectedCustomPreset(); + QTreeWidgetItem *sel = GetSelectedCustomPreset(); - if (sel) { - Menu m(this); + if (sel) { + Menu m(this); - QAction* delete_action = m.addAction(tr("Delete Preset")); - connect(delete_action, &QAction::triggered, this, &SequenceDialogPresetTab::DeleteSelectedPreset); + QAction *delete_action = m.addAction(tr("Delete Preset")); + connect(delete_action, &QAction::triggered, this, + &SequenceDialogPresetTab::DeleteSelectedPreset); - m.exec(QCursor::pos()); - } + m.exec(QCursor::pos()); + } } void SequenceDialogPresetTab::DeleteSelectedPreset() { - QTreeWidgetItem* sel = GetSelectedCustomPreset(); + QTreeWidgetItem *sel = GetSelectedCustomPreset(); - if (sel) { - int preset_index = sel->data(0, kDataPresetDataRole).toInt(); + if (sel) { + int preset_index = sel->data(0, kDataPresetDataRole).toInt(); - // Shift all items whose index was after this preset forward - for (int i=0; ichildCount(); i++) { - QTreeWidgetItem* custom_item = my_presets_folder_->child(i); - int this_item_index = custom_item->data(0, kDataPresetDataRole).toInt(); + // Shift all items whose index was after this preset forward + for (int i = 0; i < my_presets_folder_->childCount(); i++) { + QTreeWidgetItem *custom_item = my_presets_folder_->child(i); + int this_item_index = + custom_item->data(0, kDataPresetDataRole).toInt(); - if (this_item_index > preset_index) { - custom_item->setData(0, kDataPresetDataRole, this_item_index - 1); - } - } + if (this_item_index > preset_index) { + custom_item->setData(0, kDataPresetDataRole, + this_item_index - 1); + } + } - // Remove the preset - DeletePreset(preset_index); + // Remove the preset + DeletePreset(preset_index); - // Delete the item - delete sel; - } + // Delete the item + delete sel; + } } } diff --git a/app/dialog/sequence/sequencedialogpresettab.h b/app/dialog/sequence/sequencedialogpresettab.h index 3a860e542..2ca5a02f2 100644 --- a/app/dialog/sequence/sequencedialogpresettab.h +++ b/app/dialog/sequence/sequencedialogpresettab.h @@ -28,53 +28,61 @@ #include "presetmanager.h" #include "sequencepreset.h" -namespace olive { - -class SequenceDialogPresetTab : public QWidget, public PresetManager +namespace olive { - Q_OBJECT + +class SequenceDialogPresetTab : public QWidget, + public PresetManager { + Q_OBJECT public: - SequenceDialogPresetTab(QWidget* parent = nullptr); + SequenceDialogPresetTab(QWidget *parent = nullptr); public slots: - void SaveParametersAsPreset(SequencePreset preset); + void SaveParametersAsPreset(SequencePreset preset); signals: - void PresetChanged(const SequencePreset& preset); + void PresetChanged(const SequencePreset &preset); - void PresetAccepted(); + void PresetAccepted(); private: - QTreeWidgetItem *CreateFolder(const QString& name); + QTreeWidgetItem *CreateFolder(const QString &name); - QTreeWidgetItem *CreateHDPresetFolder(const QString& name, int width, int height, int divider); + QTreeWidgetItem *CreateHDPresetFolder(const QString &name, int width, + int height, int divider); - QTreeWidgetItem *CreateSDPresetFolder(const QString& name, int width, int height, const rational &frame_rate, const rational& standard_par, const rational& wide_par, int divider); + QTreeWidgetItem *CreateSDPresetFolder( + const QString &name, int width, int height, const rational &frame_rate, + const rational &standard_par, const rational &wide_par, int divider); - QTreeWidgetItem* GetSelectedItem(); - QTreeWidgetItem* GetSelectedCustomPreset(); + QTreeWidgetItem *GetSelectedItem(); + QTreeWidgetItem *GetSelectedCustomPreset(); - void AddStandardItem(QTreeWidgetItem* folder, PresetPtr preset, const QString &description = QString()); + void AddStandardItem(QTreeWidgetItem *folder, PresetPtr preset, + const QString &description = QString()); - void AddCustomItem(QTreeWidgetItem* folder, PresetPtr preset, int index, const QString& description = QString()); + void AddCustomItem(QTreeWidgetItem *folder, PresetPtr preset, int index, + const QString &description = QString()); - void AddItemInternal(QTreeWidgetItem* folder, PresetPtr preset, bool is_custom, int index, const QString& description = QString()); + void AddItemInternal(QTreeWidgetItem *folder, PresetPtr preset, + bool is_custom, int index, + const QString &description = QString()); - QTreeWidget* preset_tree_; + QTreeWidget *preset_tree_; - QTreeWidgetItem* my_presets_folder_; + QTreeWidgetItem *my_presets_folder_; - QVector default_preset_data_; + QVector default_preset_data_; private slots: - void SelectedItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous); + void SelectedItemChanged(QTreeWidgetItem *current, + QTreeWidgetItem *previous); - void ItemDoubleClicked(QTreeWidgetItem *item, int column); + void ItemDoubleClicked(QTreeWidgetItem *item, int column); - void ShowContextMenu(); - - void DeleteSelectedPreset(); + void ShowContextMenu(); + void DeleteSelectedPreset(); }; } diff --git a/app/dialog/sequence/sequencepreset.h b/app/dialog/sequence/sequencepreset.h index 84c0cbab5..ab1f77860 100644 --- a/app/dialog/sequence/sequencepreset.h +++ b/app/dialog/sequence/sequencepreset.h @@ -28,145 +28,156 @@ #include "dialog/sequence/presetmanager.h" #include "render/videoparams.h" -namespace olive { +namespace olive +{ class SequencePreset : public Preset { public: - SequencePreset() = default; + SequencePreset() = default; - SequencePreset(const QString& name, - int width, - int height, - const rational& frame_rate, - const rational& pixel_aspect, - VideoParams::Interlacing interlacing, - int sample_rate, - AVChannelLayout &channel_layout, - int preview_divider, - PixelFormat preview_format, - bool preview_autocache) : - width_(width), - height_(height), - frame_rate_(frame_rate), - pixel_aspect_(pixel_aspect), - interlacing_(interlacing), - sample_rate_(sample_rate), - channel_layout_(channel_layout), - preview_divider_(preview_divider), - preview_format_(preview_format), - preview_autocache_(preview_autocache) - { - SetName(name); - } + SequencePreset(const QString &name, int width, int height, + const rational &frame_rate, const rational &pixel_aspect, + VideoParams::Interlacing interlacing, int sample_rate, + AVChannelLayout &channel_layout, int preview_divider, + PixelFormat preview_format, bool preview_autocache) + : width_(width) + , height_(height) + , frame_rate_(frame_rate) + , pixel_aspect_(pixel_aspect) + , interlacing_(interlacing) + , sample_rate_(sample_rate) + , channel_layout_(channel_layout) + , preview_divider_(preview_divider) + , preview_format_(preview_format) + , preview_autocache_(preview_autocache) + { + SetName(name); + } - virtual void Load(QXmlStreamReader* reader) override - { - while (XMLReadNextStartElement(reader)) { - if (reader->name() == QStringLiteral("name")) { - SetName(reader->readElementText()); - } else if (reader->name() == QStringLiteral("width")) { - width_ = reader->readElementText().toInt(); - } else if (reader->name() == QStringLiteral("height")) { - height_ = reader->readElementText().toInt(); - } else if (reader->name() == QStringLiteral("framerate")) { - frame_rate_ = rational::fromString(reader->readElementText().toStdString()); - } else if (reader->name() == QStringLiteral("pixelaspect")) { - pixel_aspect_ = rational::fromString(reader->readElementText().toStdString()); - } else if (reader->name() == QStringLiteral("interlacing")) { - interlacing_ = static_cast(reader->readElementText().toInt()); - } else if (reader->name() == QStringLiteral("samplerate")) { - sample_rate_ = reader->readElementText().toInt(); - } else if (reader->name() == QStringLiteral("chlayout")) { - channel_layout_.u.mask = reader->readElementText().toULongLong(); - } else if (reader->name() == QStringLiteral("divider")) { - preview_divider_ = reader->readElementText().toInt(); - } else if (reader->name() == QStringLiteral("format")) { - preview_format_ = static_cast(reader->readElementText().toInt()); - } else if (reader->name() == QStringLiteral("autocache")) { - preview_autocache_ = reader->readElementText().toInt(); - } else { - reader->skipCurrentElement(); - } - } - } + virtual void Load(QXmlStreamReader *reader) override + { + while (XMLReadNextStartElement(reader)) { + if (reader->name() == QStringLiteral("name")) { + SetName(reader->readElementText()); + } else if (reader->name() == QStringLiteral("width")) { + width_ = reader->readElementText().toInt(); + } else if (reader->name() == QStringLiteral("height")) { + height_ = reader->readElementText().toInt(); + } else if (reader->name() == QStringLiteral("framerate")) { + frame_rate_ = rational::fromString( + reader->readElementText().toStdString()); + } else if (reader->name() == QStringLiteral("pixelaspect")) { + pixel_aspect_ = rational::fromString( + reader->readElementText().toStdString()); + } else if (reader->name() == QStringLiteral("interlacing")) { + interlacing_ = static_cast( + reader->readElementText().toInt()); + } else if (reader->name() == QStringLiteral("samplerate")) { + sample_rate_ = reader->readElementText().toInt(); + } else if (reader->name() == QStringLiteral("chlayout")) { + channel_layout_.u.mask = + reader->readElementText().toULongLong(); + } else if (reader->name() == QStringLiteral("divider")) { + preview_divider_ = reader->readElementText().toInt(); + } else if (reader->name() == QStringLiteral("format")) { + preview_format_ = static_cast( + reader->readElementText().toInt()); + } else if (reader->name() == QStringLiteral("autocache")) { + preview_autocache_ = reader->readElementText().toInt(); + } else { + reader->skipCurrentElement(); + } + } + } - virtual void Save(QXmlStreamWriter* writer) const override - { - writer->writeTextElement(QStringLiteral("name"), GetName()); - writer->writeTextElement(QStringLiteral("width"), QString::number(width_)); - writer->writeTextElement(QStringLiteral("height"), QString::number(height_)); - writer->writeTextElement(QStringLiteral("framerate"), QString::fromStdString(frame_rate_.toString())); - writer->writeTextElement(QStringLiteral("pixelaspect"), QString::fromStdString(pixel_aspect_.toString())); - writer->writeTextElement(QStringLiteral("interlacing_"), QString::number(interlacing_)); - writer->writeTextElement(QStringLiteral("samplerate"), QString::number(sample_rate_)); - writer->writeTextElement(QStringLiteral("chlayout"), QString::number(channel_layout_.u.mask)); - writer->writeTextElement(QStringLiteral("divider"), QString::number(preview_divider_)); - writer->writeTextElement(QStringLiteral("format"), QString::number(preview_format_)); - writer->writeTextElement(QStringLiteral("autocache"), QString::number(preview_autocache_)); - } + virtual void Save(QXmlStreamWriter *writer) const override + { + writer->writeTextElement(QStringLiteral("name"), GetName()); + writer->writeTextElement(QStringLiteral("width"), + QString::number(width_)); + writer->writeTextElement(QStringLiteral("height"), + QString::number(height_)); + writer->writeTextElement( + QStringLiteral("framerate"), + QString::fromStdString(frame_rate_.toString())); + writer->writeTextElement( + QStringLiteral("pixelaspect"), + QString::fromStdString(pixel_aspect_.toString())); + writer->writeTextElement(QStringLiteral("interlacing_"), + QString::number(interlacing_)); + writer->writeTextElement(QStringLiteral("samplerate"), + QString::number(sample_rate_)); + writer->writeTextElement(QStringLiteral("chlayout"), + QString::number(channel_layout_.u.mask)); + writer->writeTextElement(QStringLiteral("divider"), + QString::number(preview_divider_)); + writer->writeTextElement(QStringLiteral("format"), + QString::number(preview_format_)); + writer->writeTextElement(QStringLiteral("autocache"), + QString::number(preview_autocache_)); + } - int width() const - { - return width_; - } + int width() const + { + return width_; + } - int height() const - { - return height_; - } + int height() const + { + return height_; + } - const rational& frame_rate() const - { - return frame_rate_; - } + const rational &frame_rate() const + { + return frame_rate_; + } - const rational& pixel_aspect() const - { - return pixel_aspect_; - } + const rational &pixel_aspect() const + { + return pixel_aspect_; + } - VideoParams::Interlacing interlacing() const - { - return interlacing_; - } + VideoParams::Interlacing interlacing() const + { + return interlacing_; + } - int sample_rate() const - { - return sample_rate_; - } + int sample_rate() const + { + return sample_rate_; + } - AVChannelLayout channel_layout() const - { - return channel_layout_; - } + AVChannelLayout channel_layout() const + { + return channel_layout_; + } - int preview_divider() const - { - return preview_divider_; - } + int preview_divider() const + { + return preview_divider_; + } - PixelFormat preview_format() const - { - return preview_format_; - } + PixelFormat preview_format() const + { + return preview_format_; + } - bool preview_autocache() const - { - return preview_autocache_; - } + bool preview_autocache() const + { + return preview_autocache_; + } private: - int width_; - int height_; - rational frame_rate_; - rational pixel_aspect_; - VideoParams::Interlacing interlacing_; - int sample_rate_; - AVChannelLayout channel_layout_; - int preview_divider_; - PixelFormat preview_format_; - bool preview_autocache_; - + int width_; + int height_; + rational frame_rate_; + rational pixel_aspect_; + VideoParams::Interlacing interlacing_; + int sample_rate_; + AVChannelLayout channel_layout_; + int preview_divider_; + PixelFormat preview_format_; + bool preview_autocache_; }; } diff --git a/app/dialog/speedduration/speeddurationdialog.cpp b/app/dialog/speedduration/speeddurationdialog.cpp index 367fae059..03cdb3a2b 100644 --- a/app/dialog/speedduration/speeddurationdialog.cpp +++ b/app/dialog/speedduration/speeddurationdialog.cpp @@ -29,268 +29,311 @@ #include "node/nodeundo.h" #include "timeline/timelineundopointer.h" -namespace olive { +namespace olive +{ #define super QDialog -SpeedDurationDialog::SpeedDurationDialog(const QVector &clips, const rational &timebase, QWidget *parent) : - super(parent), - clips_(clips), - timebase_(timebase) +SpeedDurationDialog::SpeedDurationDialog(const QVector &clips, + const rational &timebase, + QWidget *parent) + : super(parent) + , clips_(clips) + , timebase_(timebase) { - setWindowTitle(tr("Clip Properties")); + setWindowTitle(tr("Clip Properties")); - QVBoxLayout *layout = new QVBoxLayout(this); + QVBoxLayout *layout = new QVBoxLayout(this); - { - QGroupBox *speed_group = new QGroupBox(tr("Speed/Duration")); - layout->addWidget(speed_group); + { + QGroupBox *speed_group = new QGroupBox(tr("Speed/Duration")); + layout->addWidget(speed_group); - QGridLayout *speed_layout = new QGridLayout(speed_group); + QGridLayout *speed_layout = new QGridLayout(speed_group); - int row = 0; + int row = 0; - speed_layout->addWidget(new QLabel(tr("Speed:")), row, 0); + speed_layout->addWidget(new QLabel(tr("Speed:")), row, 0); - speed_slider_ = new FloatSlider(); - speed_slider_->SetDisplayType(FloatSlider::kPercentage); - connect(speed_slider_, &FloatSlider::ValueChanged, this, &SpeedDurationDialog::SpeedChanged); - speed_layout->addWidget(speed_slider_, row, 1); + speed_slider_ = new FloatSlider(); + speed_slider_->SetDisplayType(FloatSlider::kPercentage); + connect(speed_slider_, &FloatSlider::ValueChanged, this, + &SpeedDurationDialog::SpeedChanged); + speed_layout->addWidget(speed_slider_, row, 1); - row++; + row++; - speed_layout->addWidget(new QLabel(tr("Duration:")), row, 0); + speed_layout->addWidget(new QLabel(tr("Duration:")), row, 0); - dur_slider_ = new RationalSlider(); - dur_slider_->SetTimebase(timebase); - dur_slider_->SetDisplayType(RationalSlider::kTime); - connect(dur_slider_, &RationalSlider::ValueChanged, this, &SpeedDurationDialog::DurationChanged); - speed_layout->addWidget(dur_slider_, row, 1); + dur_slider_ = new RationalSlider(); + dur_slider_->SetTimebase(timebase); + dur_slider_->SetDisplayType(RationalSlider::kTime); + connect(dur_slider_, &RationalSlider::ValueChanged, this, + &SpeedDurationDialog::DurationChanged); + speed_layout->addWidget(dur_slider_, row, 1); - row++; + row++; - link_box_ = new QCheckBox(tr("Link Speed and Duration")); - link_box_->setChecked(true); - speed_layout->addWidget(link_box_, row, 0, 1, 2); + link_box_ = new QCheckBox(tr("Link Speed and Duration")); + link_box_->setChecked(true); + speed_layout->addWidget(link_box_, row, 0, 1, 2); - row++; + row++; - reverse_box_ = new QCheckBox(tr("Reverse")); - speed_layout->addWidget(reverse_box_, row, 0, 1, 2); + reverse_box_ = new QCheckBox(tr("Reverse")); + speed_layout->addWidget(reverse_box_, row, 0, 1, 2); - row++; + row++; - maintain_audio_pitch_box_ = new QCheckBox(tr("Maintain Audio Pitch")); - speed_layout->addWidget(maintain_audio_pitch_box_, row, 0, 1, 2); + maintain_audio_pitch_box_ = new QCheckBox(tr("Maintain Audio Pitch")); + speed_layout->addWidget(maintain_audio_pitch_box_, row, 0, 1, 2); - row++; + row++; - ripple_box_ = new QCheckBox(tr("Ripple Trailing Clips")); - speed_layout->addWidget(ripple_box_, row, 0, 1, 2); - } + ripple_box_ = new QCheckBox(tr("Ripple Trailing Clips")); + speed_layout->addWidget(ripple_box_, row, 0, 1, 2); + } - { - auto loop_box = new QGroupBox(tr("Loop")); - layout->addWidget(loop_box); + { + auto loop_box = new QGroupBox(tr("Loop")); + layout->addWidget(loop_box); - auto loop_layout = new QGridLayout(loop_box); + auto loop_layout = new QGridLayout(loop_box); - int row = 0; + int row = 0; - loop_layout->addWidget(new QLabel(tr("Loop:")), row, 0); + loop_layout->addWidget(new QLabel(tr("Loop:")), row, 0); - loop_combo_ = new QComboBox(); - loop_combo_->addItem(tr("None"), int(LoopMode::kLoopModeOff)); - loop_combo_->addItem(tr("Loop"), int(LoopMode::kLoopModeLoop)); - loop_combo_->addItem(tr("Clamp"), int(LoopMode::kLoopModeClamp)); - loop_layout->addWidget(loop_combo_, row, 1); - } + loop_combo_ = new QComboBox(); + loop_combo_->addItem(tr("None"), int(LoopMode::kLoopModeOff)); + loop_combo_->addItem(tr("Loop"), int(LoopMode::kLoopModeLoop)); + loop_combo_->addItem(tr("Clamp"), int(LoopMode::kLoopModeClamp)); + loop_layout->addWidget(loop_combo_, row, 1); + } - QDialogButtonBox *btns = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); - btns->setCenterButtons(true); - connect(btns, &QDialogButtonBox::accepted, this, &SpeedDurationDialog::accept); - connect(btns, &QDialogButtonBox::rejected, this, &SpeedDurationDialog::reject); - layout->addWidget(btns); + QDialogButtonBox *btns = + new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); + btns->setCenterButtons(true); + connect(btns, &QDialogButtonBox::accepted, this, + &SpeedDurationDialog::accept); + connect(btns, &QDialogButtonBox::rejected, this, + &SpeedDurationDialog::reject); + layout->addWidget(btns); - // Determine which speed value to use - start_speed_ = clips.first()->speed(); - start_duration_ = clips.first()->length(); - start_reverse_ = clips.first()->reverse(); - start_maintain_audio_pitch_ = clips.first()->maintain_audio_pitch(); - start_loop_ = int(clips.first()->loop_mode()); - for (int i=1; ispeed(); + start_duration_ = clips.first()->length(); + start_reverse_ = clips.first()->reverse(); + start_maintain_audio_pitch_ = clips.first()->maintain_audio_pitch(); + start_loop_ = int(clips.first()->loop_mode()); + for (int i = 1; i < clips.size(); i++) { + ClipBlock *c = clips.at(i); - if (!qIsNaN(start_speed_) && !qFuzzyCompare(start_speed_, c->speed())) { - // Speed differs per clip - start_speed_ = qSNaN(); - } + if (!qIsNaN(start_speed_) && !qFuzzyCompare(start_speed_, c->speed())) { + // Speed differs per clip + start_speed_ = qSNaN(); + } - if (start_duration_ != -1 && c->length() != start_duration_) { - start_duration_ = -1; - } + if (start_duration_ != -1 && c->length() != start_duration_) { + start_duration_ = -1; + } - // Yes, in theory a bool should only ever be 0 or 1 anyway, but MSVC complained and it is - // *possible* that a bool could be something else, so this code is safer - int clip_reverse = c->reverse() ? 1 : 0; - int clip_maintain_pitch = c->maintain_audio_pitch() ? 1 : 0; - if (start_reverse_ != -1 && clip_reverse != start_reverse_) { - start_reverse_ = -1; - } - if (start_maintain_audio_pitch_ != -1 && clip_maintain_pitch != start_maintain_audio_pitch_) { - start_maintain_audio_pitch_ = -1; - } + // Yes, in theory a bool should only ever be 0 or 1 anyway, but MSVC complained and it is + // *possible* that a bool could be something else, so this code is safer + int clip_reverse = c->reverse() ? 1 : 0; + int clip_maintain_pitch = c->maintain_audio_pitch() ? 1 : 0; + if (start_reverse_ != -1 && clip_reverse != start_reverse_) { + start_reverse_ = -1; + } + if (start_maintain_audio_pitch_ != -1 && + clip_maintain_pitch != start_maintain_audio_pitch_) { + start_maintain_audio_pitch_ = -1; + } - if (start_loop_ != -1 && int(c->loop_mode()) != start_loop_) { - start_loop_ = -1; - } - } + if (start_loop_ != -1 && int(c->loop_mode()) != start_loop_) { + start_loop_ = -1; + } + } - if (qIsNaN(start_speed_)) { - speed_slider_->SetTristate(); - } else { - speed_slider_->SetValue(start_speed_); - } + if (qIsNaN(start_speed_)) { + speed_slider_->SetTristate(); + } else { + speed_slider_->SetValue(start_speed_); + } - if (start_duration_ == -1) { - dur_slider_->SetTristate(); - } else { - dur_slider_->SetValue(start_duration_); - } + if (start_duration_ == -1) { + dur_slider_->SetTristate(); + } else { + dur_slider_->SetValue(start_duration_); + } - if (start_reverse_ == -1) { - reverse_box_->setTristate(); - } else { - reverse_box_->setChecked(start_reverse_); - } + if (start_reverse_ == -1) { + reverse_box_->setTristate(); + } else { + reverse_box_->setChecked(start_reverse_); + } - if (start_maintain_audio_pitch_ == -1) { - maintain_audio_pitch_box_->setTristate(); - } else { - maintain_audio_pitch_box_->setChecked(start_maintain_audio_pitch_); - } + if (start_maintain_audio_pitch_ == -1) { + maintain_audio_pitch_box_->setTristate(); + } else { + maintain_audio_pitch_box_->setChecked(start_maintain_audio_pitch_); + } - if (start_loop_ == -1) { - loop_combo_->setCurrentIndex(-1); - } else { - loop_combo_->setCurrentIndex(start_loop_); - } + if (start_loop_ == -1) { + loop_combo_->setCurrentIndex(-1); + } else { + loop_combo_->setCurrentIndex(start_loop_); + } } void SpeedDurationDialog::accept() { - MultiUndoCommand *command = new MultiUndoCommand(); + MultiUndoCommand *command = new MultiUndoCommand(); - // Set duration values - TimelineRippleDeleteGapsAtRegionsCommand::RangeList ripple_ranges; + // Set duration values + TimelineRippleDeleteGapsAtRegionsCommand::RangeList ripple_ranges; - foreach (ClipBlock *c, clips_) { - rational proposed_length = c->length(); + foreach (ClipBlock *c, clips_) { + rational proposed_length = c->length(); - if (dur_slider_->IsTristate()) { - if (link_box_->isChecked() && !speed_slider_->IsTristate()) { - proposed_length = GetLengthAdjustment(c->length(), c->speed(), speed_slider_->GetValue(), timebase_); - } - } else { - proposed_length = dur_slider_->GetValue(); - } + if (dur_slider_->IsTristate()) { + if (link_box_->isChecked() && !speed_slider_->IsTristate()) { + proposed_length = GetLengthAdjustment(c->length(), c->speed(), + speed_slider_->GetValue(), + timebase_); + } + } else { + proposed_length = dur_slider_->GetValue(); + } - if (proposed_length != c->length()) { - // Clip length should ideally change, but check if there's "room" to do so - if (proposed_length > c->length() && c->next()) { - if (GapBlock *gap = dynamic_cast(c->next())) { - proposed_length = qMin(proposed_length, gap->out() - c->in()); - } else { - proposed_length = c->length(); - } - } + if (proposed_length != c->length()) { + // Clip length should ideally change, but check if there's "room" to do so + if (proposed_length > c->length() && c->next()) { + if (GapBlock *gap = dynamic_cast(c->next())) { + proposed_length = + qMin(proposed_length, gap->out() - c->in()); + } else { + proposed_length = c->length(); + } + } - if (proposed_length != c->length()) { - command->add_child(new BlockTrimCommand(c->track(), c, proposed_length, Timeline::kTrimOut)); - ripple_ranges.append({c->track(), TimeRange(c->in() + proposed_length, c->out())}); - } - } - } + if (proposed_length != c->length()) { + command->add_child(new BlockTrimCommand( + c->track(), c, proposed_length, Timeline::kTrimOut)); + ripple_ranges.append( + { c->track(), + TimeRange(c->in() + proposed_length, c->out()) }); + } + } + } - if (ripple_box_->isChecked()) { - command->add_child(new TimelineRippleDeleteGapsAtRegionsCommand(clips_.first()->track()->sequence(), ripple_ranges)); - } + if (ripple_box_->isChecked()) { + command->add_child(new TimelineRippleDeleteGapsAtRegionsCommand( + clips_.first()->track()->sequence(), ripple_ranges)); + } - // Set speed values - if (speed_slider_->IsTristate()) { - if (link_box_->isChecked() && !dur_slider_->IsTristate()) { - // Automatically determine speed from duration - foreach (ClipBlock *c, clips_) { - command->add_child(new NodeParamSetStandardValueCommand(NodeKeyframeTrackReference(NodeInput(c, ClipBlock::kSpeedInput)), GetSpeedAdjustment(c->speed(), c->length(), dur_slider_->GetValue()))); - } - } - } else { - // Set speeds to value of slider - foreach (ClipBlock *c, clips_) { - command->add_child(new NodeParamSetStandardValueCommand(NodeKeyframeTrackReference(NodeInput(c, ClipBlock::kSpeedInput)), speed_slider_->GetValue())); - } - } + // Set speed values + if (speed_slider_->IsTristate()) { + if (link_box_->isChecked() && !dur_slider_->IsTristate()) { + // Automatically determine speed from duration + foreach (ClipBlock *c, clips_) { + command->add_child(new NodeParamSetStandardValueCommand( + NodeKeyframeTrackReference( + NodeInput(c, ClipBlock::kSpeedInput)), + GetSpeedAdjustment(c->speed(), c->length(), + dur_slider_->GetValue()))); + } + } + } else { + // Set speeds to value of slider + foreach (ClipBlock *c, clips_) { + command->add_child(new NodeParamSetStandardValueCommand( + NodeKeyframeTrackReference(NodeInput(c, ClipBlock::kSpeedInput)), + speed_slider_->GetValue())); + } + } - // Set reverse values - if (!reverse_box_->isTristate()) { - foreach (ClipBlock *c, clips_) { - command->add_child(new NodeParamSetStandardValueCommand(NodeKeyframeTrackReference(NodeInput(c, ClipBlock::kReverseInput)), reverse_box_->isChecked())); - } - } + // Set reverse values + if (!reverse_box_->isTristate()) { + foreach (ClipBlock *c, clips_) { + command->add_child(new NodeParamSetStandardValueCommand( + NodeKeyframeTrackReference( + NodeInput(c, ClipBlock::kReverseInput)), + reverse_box_->isChecked())); + } + } - // Set reverse values - if (!maintain_audio_pitch_box_->isTristate()) { - foreach (ClipBlock *c, clips_) { - command->add_child(new NodeParamSetStandardValueCommand(NodeKeyframeTrackReference(NodeInput(c, ClipBlock::kMaintainAudioPitchInput)), maintain_audio_pitch_box_->isChecked())); - } - } + // Set reverse values + if (!maintain_audio_pitch_box_->isTristate()) { + foreach (ClipBlock *c, clips_) { + command->add_child(new NodeParamSetStandardValueCommand( + NodeKeyframeTrackReference( + NodeInput(c, ClipBlock::kMaintainAudioPitchInput)), + maintain_audio_pitch_box_->isChecked())); + } + } - if (loop_combo_->currentIndex() != -1) { - foreach (ClipBlock *c, clips_) { - command->add_child(new NodeParamSetStandardValueCommand(NodeKeyframeTrackReference(NodeInput(c, ClipBlock::kLoopModeInput)), loop_combo_->currentData())); - } - } + if (loop_combo_->currentIndex() != -1) { + foreach (ClipBlock *c, clips_) { + command->add_child(new NodeParamSetStandardValueCommand( + NodeKeyframeTrackReference( + NodeInput(c, ClipBlock::kLoopModeInput)), + loop_combo_->currentData())); + } + } - QString name = (clips_.size() > 1) ? tr("Set %1 Clip Properties").arg(clips_.size()) : tr("Set Clip \"%1\" Properties").arg(clips_.first()->GetLabelOrName()); - Core::instance()->undo_stack()->push(command, name); + QString name = (clips_.size() > 1) ? + tr("Set %1 Clip Properties").arg(clips_.size()) : + tr("Set Clip \"%1\" Properties") + .arg(clips_.first()->GetLabelOrName()); + Core::instance()->undo_stack()->push(command, name); - super::accept(); + super::accept(); } -rational SpeedDurationDialog::GetLengthAdjustment(const rational &original_length, double original_speed, double new_speed, const rational &timebase) +rational SpeedDurationDialog::GetLengthAdjustment( + const rational &original_length, double original_speed, double new_speed, + const rational &timebase) { - return Timecode::snap_time_to_timebase(rational::fromDouble(original_length.toDouble() / new_speed * original_speed), timebase); + return Timecode::snap_time_to_timebase( + rational::fromDouble(original_length.toDouble() / new_speed * + original_speed), + timebase); } -double SpeedDurationDialog::GetSpeedAdjustment(double original_speed, const rational &original_length, const rational &new_length) +double SpeedDurationDialog::GetSpeedAdjustment(double original_speed, + const rational &original_length, + const rational &new_length) { - return original_speed / new_length.toDouble() * original_length.toDouble(); + return original_speed / new_length.toDouble() * original_length.toDouble(); } void SpeedDurationDialog::SpeedChanged(double s) { - if (!link_box_->isChecked()) { - return; - } + if (!link_box_->isChecked()) { + return; + } - if (start_duration_ == -1) { - dur_slider_->SetTristate(); - } else { - dur_slider_->SetValue(GetLengthAdjustment(start_duration_, start_speed_, s, timebase_)); - } + if (start_duration_ == -1) { + dur_slider_->SetTristate(); + } else { + dur_slider_->SetValue( + GetLengthAdjustment(start_duration_, start_speed_, s, timebase_)); + } } void SpeedDurationDialog::DurationChanged(const rational &r) { - if (!link_box_->isChecked()) { - return; - } + if (!link_box_->isChecked()) { + return; + } - if (qIsNaN(start_speed_)) { - speed_slider_->SetTristate(); - } else { - speed_slider_->SetValue(GetSpeedAdjustment(start_speed_, start_duration_, r)); - } + if (qIsNaN(start_speed_)) { + speed_slider_->SetTristate(); + } else { + speed_slider_->SetValue( + GetSpeedAdjustment(start_speed_, start_duration_, r)); + } } } diff --git a/app/dialog/speedduration/speeddurationdialog.h b/app/dialog/speedduration/speeddurationdialog.h index 3e97d718d..8d4f90a03 100644 --- a/app/dialog/speedduration/speeddurationdialog.h +++ b/app/dialog/speedduration/speeddurationdialog.h @@ -31,57 +31,62 @@ #include "widget/slider/floatslider.h" #include "widget/slider/rationalslider.h" -namespace olive { - -class SpeedDurationDialog : public QDialog +namespace olive { - Q_OBJECT + +class SpeedDurationDialog : public QDialog { + Q_OBJECT public: - explicit SpeedDurationDialog(const QVector &clips, const rational &timebase, QWidget *parent = nullptr); + explicit SpeedDurationDialog(const QVector &clips, + const rational &timebase, + QWidget *parent = nullptr); public slots: - virtual void accept() override; + virtual void accept() override; signals: private: - static rational GetLengthAdjustment(const rational &original_length, double original_speed, double new_speed, const rational &timebase); + static rational GetLengthAdjustment(const rational &original_length, + double original_speed, double new_speed, + const rational &timebase); - static double GetSpeedAdjustment(double original_speed, const rational &original_length, const rational &new_length); + static double GetSpeedAdjustment(double original_speed, + const rational &original_length, + const rational &new_length); - QVector clips_; + QVector clips_; - FloatSlider *speed_slider_; + FloatSlider *speed_slider_; - RationalSlider *dur_slider_; + RationalSlider *dur_slider_; - QCheckBox *link_box_; + QCheckBox *link_box_; - QCheckBox *reverse_box_; + QCheckBox *reverse_box_; - QCheckBox *maintain_audio_pitch_box_; + QCheckBox *maintain_audio_pitch_box_; - QCheckBox *ripple_box_; + QCheckBox *ripple_box_; - QComboBox *loop_combo_; + QComboBox *loop_combo_; - int start_reverse_; + int start_reverse_; - int start_maintain_audio_pitch_; + int start_maintain_audio_pitch_; - double start_speed_; + double start_speed_; - rational start_duration_; + rational start_duration_; - int start_loop_; + int start_loop_; - rational timebase_; + rational timebase_; private slots: - void SpeedChanged(double s); - - void DurationChanged(const rational &r); + void SpeedChanged(double s); + void DurationChanged(const rational &r); }; } diff --git a/app/dialog/task/task.cpp b/app/dialog/task/task.cpp index aab2b2979..dac71a87c 100644 --- a/app/dialog/task/task.cpp +++ b/app/dialog/task/task.cpp @@ -22,83 +22,87 @@ #include -namespace olive { +namespace olive +{ #define super ProgressDialog -TaskDialog::TaskDialog(Task* task, const QString& title, QWidget *parent) : - super(task->GetTitle(), title, parent), - task_(task), - destroy_on_close_(true), - already_shown_(false) +TaskDialog::TaskDialog(Task *task, const QString &title, QWidget *parent) + : super(task->GetTitle(), title, parent) + , task_(task) + , destroy_on_close_(true) + , already_shown_(false) { - // Clear task when this dialog is destroyed - task_->setParent(this); + // Clear task when this dialog is destroyed + task_->setParent(this); - // Connect the save manager progress signal to the progress bar update on the dialog - connect(task_, &Task::ProgressChanged, this, &TaskDialog::SetProgress, Qt::QueuedConnection); + // Connect the save manager progress signal to the progress bar update on the dialog + connect(task_, &Task::ProgressChanged, this, &TaskDialog::SetProgress, + Qt::QueuedConnection); - // Connect cancel signal (must be a direct connection or it'll be queued after the task has - // already finished) - connect(this, &TaskDialog::Cancelled, task_, &Task::Cancel, Qt::DirectConnection); + // Connect cancel signal (must be a direct connection or it'll be queued after the task has + // already finished) + connect(this, &TaskDialog::Cancelled, task_, &Task::Cancel, + Qt::DirectConnection); } void TaskDialog::showEvent(QShowEvent *e) { - super::showEvent(e); + super::showEvent(e); - if (!already_shown_) { - // Create watcher for when the task finishes - QFutureWatcher* task_watcher = new QFutureWatcher(); + if (!already_shown_) { + // Create watcher for when the task finishes + QFutureWatcher *task_watcher = new QFutureWatcher(); - // Listen for when the task finishes - connect(task_watcher, &QFutureWatcher::finished, - this, &TaskDialog::TaskFinished, Qt::QueuedConnection); + // Listen for when the task finishes + connect(task_watcher, &QFutureWatcher::finished, this, + &TaskDialog::TaskFinished, Qt::QueuedConnection); - // Run task in another thread with QtConcurrent - task_watcher->setFuture( + // Run task in another thread with QtConcurrent + task_watcher->setFuture( #if QT_VERSION_MAJOR >= 6 - QtConcurrent::run(&Task::Start, task_) + QtConcurrent::run(&Task::Start, task_) #else - QtConcurrent::run(task_, &Task::Start) + QtConcurrent::run(task_, &Task::Start) #endif - ); + ); - already_shown_ = true; - } + already_shown_ = true; + } } void TaskDialog::closeEvent(QCloseEvent *e) { - // Cancel task if it is running - task_->Cancel(); + // Cancel task if it is running + task_->Cancel(); - // Standard close function - super::closeEvent(e); + // Standard close function + super::closeEvent(e); - // Reset shown - already_shown_ = false; + // Reset shown + already_shown_ = false; - // Clean up this task and dialog - if (destroy_on_close_) { - deleteLater(); - } + // Clean up this task and dialog + if (destroy_on_close_) { + deleteLater(); + } } void TaskDialog::TaskFinished() { - QFutureWatcher* task_watcher = static_cast*>(sender()); + QFutureWatcher *task_watcher = + static_cast *>(sender()); - if (task_watcher->result()) { - emit TaskSucceeded(task_); - } else { - ShowErrorMessage(tr("Task Failed"), task_->GetError()); - emit TaskFailed(task_); - } + if (task_watcher->result()) { + emit TaskSucceeded(task_); + } else { + ShowErrorMessage(tr("Task Failed"), task_->GetError()); + emit TaskFailed(task_); + } - task_watcher->deleteLater(); + task_watcher->deleteLater(); - close(); + close(); } } diff --git a/app/dialog/task/task.h b/app/dialog/task/task.h index f4aef1afa..7375634ea 100644 --- a/app/dialog/task/task.h +++ b/app/dialog/task/task.h @@ -24,59 +24,58 @@ #include "dialog/progress/progress.h" #include "task/task.h" -namespace olive { - -class TaskDialog : public ProgressDialog +namespace olive { - Q_OBJECT + +class TaskDialog : public ProgressDialog { + Q_OBJECT public: - /** + /** * @brief TaskDialog Constructor * * Creates a TaskDialog. The TaskDialog takes ownership of the Task and will destroy it on close. * Connect to the Task::Succeeded() if you want to retrieve information from the task before it * gets destroyed. */ - TaskDialog(Task *task, const QString &title, QWidget* parent = nullptr); + TaskDialog(Task *task, const QString &title, QWidget *parent = nullptr); - /** + /** * @brief Set whether TaskDialog should destroy itself (and the task) when it's closed * * This is TRUE by default. */ - void SetDestroyOnClose(bool e) - { - destroy_on_close_ = e; - } + void SetDestroyOnClose(bool e) + { + destroy_on_close_ = e; + } - /** + /** * @brief Returns this dialog's task */ - Task* GetTask() const - { - return task_; - } + Task *GetTask() const + { + return task_; + } protected: - virtual void showEvent(QShowEvent* e) override; + virtual void showEvent(QShowEvent *e) override; - virtual void closeEvent(QCloseEvent* e) override; + virtual void closeEvent(QCloseEvent *e) override; signals: - void TaskSucceeded(Task* task); + void TaskSucceeded(Task *task); - void TaskFailed(Task* task); + void TaskFailed(Task *task); private: - Task* task_; + Task *task_; - bool destroy_on_close_; + bool destroy_on_close_; - bool already_shown_; + bool already_shown_; private slots: - void TaskFinished(); - + void TaskFinished(); }; } diff --git a/app/dialog/text/text.cpp b/app/dialog/text/text.cpp index f764bdee6..7f56d12fe 100644 --- a/app/dialog/text/text.cpp +++ b/app/dialog/text/text.cpp @@ -28,23 +28,25 @@ #include "ui/icons/icons.h" -namespace olive { - -TextDialog::TextDialog(const QString &start, QWidget* parent) : - QDialog(parent) +namespace olive { - QVBoxLayout* layout = new QVBoxLayout(this); - // Create text edit widget - text_edit_ = new QPlainTextEdit(); - text_edit_->document()->setPlainText(start); - layout->addWidget(text_edit_); +TextDialog::TextDialog(const QString &start, QWidget *parent) + : QDialog(parent) +{ + QVBoxLayout *layout = new QVBoxLayout(this); - // Create buttons - QDialogButtonBox* buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); - layout->addWidget(buttons); - connect(buttons, &QDialogButtonBox::accepted, this, &TextDialog::accept); - connect(buttons, &QDialogButtonBox::rejected, this, &TextDialog::reject); + // Create text edit widget + text_edit_ = new QPlainTextEdit(); + text_edit_->document()->setPlainText(start); + layout->addWidget(text_edit_); + + // Create buttons + QDialogButtonBox *buttons = + new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); + layout->addWidget(buttons); + connect(buttons, &QDialogButtonBox::accepted, this, &TextDialog::accept); + connect(buttons, &QDialogButtonBox::rejected, this, &TextDialog::reject); } } diff --git a/app/dialog/text/text.h b/app/dialog/text/text.h index e6542ceb4..b14971324 100644 --- a/app/dialog/text/text.h +++ b/app/dialog/text/text.h @@ -28,22 +28,21 @@ #include "common/define.h" #include "widget/slider/floatslider.h" -namespace olive { - -class TextDialog : public QDialog +namespace olive { - Q_OBJECT -public: - TextDialog(const QString &start, QWidget* parent = nullptr); - QString text() const - { - return text_edit_->toPlainText(); - } +class TextDialog : public QDialog { + Q_OBJECT +public: + TextDialog(const QString &start, QWidget *parent = nullptr); + + QString text() const + { + return text_edit_->toPlainText(); + } private: - QPlainTextEdit* text_edit_; - + QPlainTextEdit *text_edit_; }; } diff --git a/app/main.cpp b/app/main.cpp index a04bf77e2..6e351735c 100644 --- a/app/main.cpp +++ b/app/main.cpp @@ -57,292 +57,344 @@ extern "C" { int decompress_project(const QString &project) { - if (project.isEmpty()) { - printf("%s\n", QCoreApplication::translate("main", "No project filename set to decompress").toUtf8().constData()); - return 1; - } + if (project.isEmpty()) { + printf("%s\n", QCoreApplication::translate( + "main", "No project filename set to decompress") + .toUtf8() + .constData()); + return 1; + } - QFile project_file(project); - if (!project_file.open(QFile::ReadOnly)) { - printf("%s\n", QCoreApplication::translate("main", "Failed to open file \"%1\"").arg(project).toUtf8().constData()); - return 1; - } + QFile project_file(project); + if (!project_file.open(QFile::ReadOnly)) { + printf("%s\n", + QCoreApplication::translate("main", "Failed to open file \"%1\"") + .arg(project) + .toUtf8() + .constData()); + return 1; + } - printf("%s\n", QCoreApplication::translate("main", "Decompressing project...").toUtf8().constData()); + printf("%s\n", + QCoreApplication::translate("main", "Decompressing project...") + .toUtf8() + .constData()); - if (!olive::ProjectSerializer::CheckCompressedID(&project_file)) { - printf("%s\n", QCoreApplication::translate("main", "Failed to decompress, project may be corrupt").toUtf8().constData()); - return 1; - } + if (!olive::ProjectSerializer::CheckCompressedID(&project_file)) { + printf("%s\n", + QCoreApplication::translate( + "main", "Failed to decompress, project may be corrupt") + .toUtf8() + .constData()); + return 1; + } - QByteArray b = project_file.readAll(); + QByteArray b = project_file.readAll(); - project_file.close(); + project_file.close(); - QByteArray decompressed = qUncompress(b); + QByteArray decompressed = qUncompress(b); - if (decompressed.isEmpty()) { - printf("%s\n", QCoreApplication::translate("main", "Failed to decompress, project may be corrupt").toUtf8().constData()); - return 1; - } + if (decompressed.isEmpty()) { + printf("%s\n", + QCoreApplication::translate( + "main", "Failed to decompress, project may be corrupt") + .toUtf8() + .constData()); + return 1; + } - QFileInfo info(project); + QFileInfo info(project); - QString filename; - QString append; - int append_num = 0; - do { - filename = info.dir().filePath(info.completeBaseName().append(append).append(QStringLiteral(".ovexml"))); - append_num++; - append = QStringLiteral("-%1").arg(append_num); - } while(QFileInfo::exists(filename)); + QString filename; + QString append; + int append_num = 0; + do { + filename = + info.dir().filePath(info.completeBaseName().append(append).append( + QStringLiteral(".ovexml"))); + append_num++; + append = QStringLiteral("-%1").arg(append_num); + } while (QFileInfo::exists(filename)); - printf("%s\n", QCoreApplication::translate("main", "Outputting to file \"%1\"").arg(filename).toUtf8().constData()); + printf("%s\n", + QCoreApplication::translate("main", "Outputting to file \"%1\"") + .arg(filename) + .toUtf8() + .constData()); - QFile out(filename); - if (!out.open(QFile::WriteOnly)) { - printf("%s\n", QCoreApplication::translate("main", "Failed to open output file \"%1\"").arg(filename).toUtf8().constData()); - return 1; - } + QFile out(filename); + if (!out.open(QFile::WriteOnly)) { + printf("%s\n", QCoreApplication::translate( + "main", "Failed to open output file \"%1\"") + .arg(filename) + .toUtf8() + .constData()); + return 1; + } - out.write(decompressed); - out.close(); + out.write(decompressed); + out.close(); - printf("%s\n", QCoreApplication::translate("main", "Decompressed successfully").toUtf8().constData()); - return 0; + printf("%s\n", + QCoreApplication::translate("main", "Decompressed successfully") + .toUtf8() + .constData()); + return 0; } int main(int argc, char *argv[]) { - // Set up debug handler - qInstallMessageHandler(olive::DebugHandler); + // Set up debug handler + qInstallMessageHandler(olive::DebugHandler); - // Set application metadata - QCoreApplication::setOrganizationName("olivevideoeditor.org"); - QCoreApplication::setOrganizationDomain("olivevideoeditor.org"); - QCoreApplication::setApplicationName("Olive"); - QGuiApplication::setDesktopFileName("org.olivevideoeditor.Olive"); - QCoreApplication::setApplicationVersion(olive::kAppVersionLong); + // Set application metadata + QCoreApplication::setOrganizationName("olivevideoeditor.org"); + QCoreApplication::setOrganizationDomain("olivevideoeditor.org"); + QCoreApplication::setApplicationName("Olive"); + QGuiApplication::setDesktopFileName("org.olivevideoeditor.Olive"); + QCoreApplication::setApplicationVersion(olive::kAppVersionLong); + // + // Parse command line arguments + // - // - // Parse command line arguments - // - - QVector args; + QVector args; #if defined(_WIN32) && defined(UNICODE) - int wargc; - LPWSTR *wargv = CommandLineToArgvW(GetCommandLineW(), &wargc); - args.resize(wargc); - for (int i=0; i