Merge branch 'master' into windows-ci-improvements

This commit is contained in:
itsmattkc
2020-09-20 00:37:20 +10:00
35 changed files with 515 additions and 220 deletions
+1 -1
View File
@@ -6,7 +6,7 @@ labels: "Crash, Triage"
assignees: ''
---
**Commit Hash**
**Commit Hash (8 character string of letters/numbers in title bar)**
**Platform**
+1 -1
View File
@@ -6,7 +6,7 @@ labels: "Building/Packaging, Triage"
assignees: ''
---
**Commit Hash**
**Commit Hash (8 character string of letters/numbers in title bar)**
**Platform**
+1 -1
View File
@@ -6,7 +6,7 @@ labels: "Disk Cache, Triage"
assignees: ''
---
**Commit Hash**
**Commit Hash (8 character string of letters/numbers in title bar)**
**Platform**
+1 -1
View File
@@ -6,7 +6,7 @@ labels: "Codec, Triage"
assignees: ''
---
**Commit Hash**
**Commit Hash (8 character string of letters/numbers in title bar)**
**Platform**
+1 -1
View File
@@ -6,7 +6,7 @@ labels: "Color Management, Triage"
assignees: ''
---
**Commit Hash**
**Commit Hash (8 character string of letters/numbers in title bar)**
**Platform**
+1 -1
View File
@@ -6,7 +6,7 @@ labels: "Timeline/Editing, Triage"
assignees: ''
---
**Commit Hash**
**Commit Hash (8 character string of letters/numbers in title bar)**
**Platform**
+1 -1
View File
@@ -6,7 +6,7 @@ labels: "Export, Triage"
assignees: ''
---
**Commit Hash**
**Commit Hash (8 character string of letters/numbers in title bar)**
**Platform**
+1 -1
View File
@@ -6,7 +6,7 @@ labels: "Nodes/Compositing, Triage"
assignees: ''
---
**Commit Hash**
**Commit Hash (8 character string of letters/numbers in title bar)**
**Platform**
+1 -1
View File
@@ -6,7 +6,7 @@ labels: "Playback, Triage"
assignees: ''
---
**Commit Hash**
**Commit Hash (8 character string of letters/numbers in title bar)**
**Platform**
+1 -1
View File
@@ -6,7 +6,7 @@ labels: "Project, Triage"
assignees: ''
---
**Commit Hash**
**Commit Hash (8 character string of letters/numbers in title bar)**
**Platform**
+1 -1
View File
@@ -6,7 +6,7 @@ labels: "Renderer, Triage"
assignees: ''
---
**Commit Hash**
**Commit Hash (8 character string of letters/numbers in title bar)**
**Platform**
+1 -1
View File
@@ -6,7 +6,7 @@ labels: "User Interface, Triage"
assignees: ''
---
**Commit Hash**
**Commit Hash (8 character string of letters/numbers in title bar)**
**Platform**
+199 -112
View File
@@ -15,28 +15,44 @@ jobs:
build-type: RelWithDebInfo
compiler-name: MSVC 16.x
os-name: Windows
os: windows-latest
dep-suffix: win.7z
extract-tool: 7z x
- build: 2
build-type: RelWithDebInfo
compiler-name: Clang LLVM
os-name: macOS
os: macos-latest
dep-suffix: mac.zip
extract-tool: unzip
name: |
${{ matrix.os-name }}
<${{ matrix.compiler-name }},
${{ matrix.build-type }}>
runs-on: windows-latest
runs-on: ${{ matrix.os }}
steps:
- name: Set package name
shell: bash
run: |
echo "::set-env name=PKGNAME::$(echo Olive-${GITHUB_SHA::8}-Windows-x86_64)"
- if: matrix.os == 'windows-latest'
- name: Set package name
shell: bash
run: |
echo "::set-env name=PKGNAME::$(echo Olive-${GITHUB_SHA::8}-Windows-x86_64)"
- if: matrix.os == 'macos-latest'
- name: Set package name
shell: bash
run: |
echo "::set-env name=PKGNAME::$(echo Olive-${GITHUB_SHA::8}-macOS)"
- uses: actions/checkout@v2
- name: Create Build Environment
# Some projects don't allow in-source building, so create a separate build directory
# We'll use this as our working directory for all subsequent commands
run: |
cmake -E make_directory ${{ runner.workspace }}/build
- name: Enable Developer Command Prompt
uses: ilammy/msvc-dev-cmd@v1.3.0
- if: matrix.os == 'windows-latest'
- name: Enable Developer Command Prompt
uses: ilammy/msvc-dev-cmd@v1.3.0
- name: Acquire Qt
uses: jurplel/install-qt-action@v2.8.0
@@ -44,63 +60,99 @@ jobs:
version: 5.15.1
- name: Acquire FFmpeg
shell: bash
env:
DEP_SUFFIX: ${{ matrix.dep-suffix }}
EXTRACT_TOOL: ${{ matrix.extract-tool }}
run: |
curl -fLOSs --retry 3 http://olivevideoeditor.org/deps/ffmpeg-win.7z
7z x ffmpeg-win.7z
curl -fLOSs --retry 3 http://olivevideoeditor.org/deps/ffmpeg-$DEP_SUFFIX
7z x ffmpeg-$DEP_SUFFIX
- name: Acquire OpenColorIO
shell: bash
env:
DEP_SUFFIX: ${{ matrix.dep-suffix }}
EXTRACT_TOOL: ${{ matrix.extract-tool }}
run: |
curl -fLOSs --retry 3 http://olivevideoeditor.org/deps/ocio-win.7z
7z x ocio-win.7z
curl -fLOSs --retry 3 http://olivevideoeditor.org/deps/ocio-$DEP_SUFFIX
7z x ocio-$DEP_SUFFIX
- name: Acquire OpenEXR
shell: bash
env:
DEP_SUFFIX: ${{ matrix.dep-suffix }}
EXTRACT_TOOL: ${{ matrix.extract-tool }}
run: |
curl -fLOSs --retry 3 http://olivevideoeditor.org/deps/openexr-win.7z
7z x openexr-win.7z
curl -fLOSs --retry 3 http://olivevideoeditor.org/deps/openexr-$DEP_SUFFIX
7z x openexr-$DEP_SUFFIX
- name: Acquire OpenImageIO
shell: bash
env:
DEP_SUFFIX: ${{ matrix.dep-suffix }}
EXTRACT_TOOL: ${{ matrix.extract-tool }}
run: |
curl -fLOSs --retry 3 http://olivevideoeditor.org/deps/oiio-win.7z
7z x oiio-win.7z
curl -fLOSs --retry 3 http://olivevideoeditor.org/deps/oiio-$DEP_SUFFIX
7z x oiio-$DEP_SUFFIX
- name: Acquire libpng
shell: bash
env:
DEP_SUFFIX: ${{ matrix.dep-suffix }}
EXTRACT_TOOL: ${{ matrix.extract-tool }}
run: |
curl -fLOSs --retry 3 http://olivevideoeditor.org/deps/libpng-win.7z
7z x libpng-win.7z
curl -fLOSs --retry 3 http://olivevideoeditor.org/deps/libpng-$DEP_SUFFIX
7z x libpng-$DEP_SUFFIX
- name: Acquire libtiff
shell: bash
env:
DEP_SUFFIX: ${{ matrix.dep-suffix }}
EXTRACT_TOOL: ${{ matrix.extract-tool }}
run: |
curl -fLOSs --retry 3 http://olivevideoeditor.org/deps/libtiff-win.7z
7z x libtiff-win.7z
curl -fLOSs --retry 3 http://olivevideoeditor.org/deps/libtiff-$DEP_SUFFIX
7z x libtiff-$DEP_SUFFIX
- name: Acquire turbojpeg
shell: bash
env:
DEP_SUFFIX: ${{ matrix.dep-suffix }}
EXTRACT_TOOL: ${{ matrix.extract-tool }}
run: |
curl -fLOSs --retry 3 http://olivevideoeditor.org/deps/turbojpeg-win.7z
7z x turbojpeg-win.7z
curl -fLOSs --retry 3 http://olivevideoeditor.org/deps/turbojpeg-$DEP_SUFFIX
7z x turbojpeg-$DEP_SUFFIX
- name: Acquire zlib
run: |
curl -fLOSs --retry 3 http://olivevideoeditor.org/deps/zlib-win.7z
7z x zlib-win.7z
- if: matrix.os == 'windows-latest'
- name: Acquire zlib
shell: bash
env:
DEP_SUFFIX: ${{ matrix.dep-suffix }}
EXTRACT_TOOL: ${{ matrix.extract-tool }}
run: |
curl -fLOSs --retry 3 http://olivevideoeditor.org/deps/zlib-$DEP_SUFFIX
7z x zlib-$DEP_SUFFIX
- name: Acquire Boost
shell: bash
env:
DEP_SUFFIX: ${{ matrix.dep-suffix }}
EXTRACT_TOOL: ${{ matrix.extract-tool }}
run: |
curl -fLOSs --retry 3 http://olivevideoeditor.org/deps/boost-win.7z
7z x boost-win.7z
curl -fLOSs --retry 3 http://olivevideoeditor.org/deps/boost-$DEP_SUFFIX
7z x boost-$DEP_SUFFIX
- name: Acquire Crashpad
shell: bash
env:
DEP_SUFFIX: ${{ matrix.dep-suffix }}
EXTRACT_TOOL: ${{ matrix.extract-tool }}
run: |
curl -fLOSs --retry 3 http://olivevideoeditor.org/deps/crashpad-win.7z
7z x crashpad-win.7z
curl -fLOSs --retry 3 http://olivevideoeditor.org/deps/crashpad-$DEP_SUFFIX
7z x crashpad-$DEP_SUFFIX
- name: Configure CMake
# Use a bash shell so we can use the same syntax for environment variable
# access regardless of the host operating system
shell: bash
working-directory: ${{ runner.workspace }}/build
# Note the current convention is to use the -S and -B options here to specify source
# and build directories, but this is only available with CMake 3.13 and higher.
# The CMake binaries on the Github Actions machines are (as of this writing) 3.12
run: |
PATH=$GITHUB_WORKSPACE:$PATH \
cmake $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=${{ matrix.build-type }} -G "Ninja"
@@ -108,95 +160,130 @@ jobs:
- name: Build
working-directory: ${{ runner.workspace }}/build
shell: bash
# Execute the build. You can specify a specific target with "--target <NAME>"
run: |
cmake --build .
- name: Test
working-directory: ${{ runner.workspace }}/build
shell: bash
# Execute tests defined by the CMake configuration.
# See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail
run: |
ctest -C ${{ matrix.build-type }}
- name: Create Package
working-directory: ${{ runner.workspace }}/build
shell: cmd
run: |
mkdir olive-editor
copy app\olive-editor.exe olive-editor
copy app\olive-editor.pdb olive-editor
windeployqt olive-editor\olive-editor.exe
copy %GITHUB_WORKSPACE%\bin\*.dll olive-editor
copy %GITHUB_WORKSPACE%\out\Default\crashpad_handler.exe olive-editor
- if: matrix.os == 'windows-latest'
- name: Create Package
working-directory: ${{ runner.workspace }}/build
shell: cmd
run: |
mkdir olive-editor
copy app\olive-editor.exe olive-editor
copy app\olive-editor.pdb olive-editor
windeployqt olive-editor\olive-editor.exe
copy %GITHUB_WORKSPACE%\bin\*.dll olive-editor
copy %GITHUB_WORKSPACE%\out\Default\crashpad_handler.exe olive-editor
- name: Deploy Installer
working-directory: ${{ runner.workspace }}/build
shell: cmd
run: |
copy %GITHUB_WORKSPACE%\app\packaging\windows\nsis\* .
copy %GITHUB_WORKSPACE%\LICENSE .
makensis -V4 -DX64 "-XOutFile %PKGNAME%.exe" olive.nsi
- name: Deploy Installer
working-directory: ${{ runner.workspace }}/build
shell: cmd
run: |
copy %GITHUB_WORKSPACE%\app\packaging\windows\nsis\* .
copy %GITHUB_WORKSPACE%\LICENSE .
makensis -V4 -DX64 "-XOutFile %PKGNAME%.exe" olive.nsi
- name: Deploy Portable
working-directory: ${{ runner.workspace }}/build
shell: cmd
run: |
type NUL > olive-editor\portable
7z a %PKGNAME%.zip olive-editor
- name: Deploy Portable
working-directory: ${{ runner.workspace }}/build
shell: cmd
run: |
type NUL > olive-editor\portable
7z a %PKGNAME%.zip olive-editor
- name: Export Crashpad Symbols and Upload To Server
working-directory: ${{ runner.workspace }}/build
shell: cmd
env:
GH_AUTH_KEY: ${{ secrets.GH_AUTH_KEY }}
run: |
curl -fLSs --retry 3 https://github.com/google/breakpad/blob/master/src/tools/windows/binaries/dump_syms.exe?raw=true > dump_syms.exe
dump_syms app\olive-editor.pdb > olive-editor.sym
curl -X POST ^
-F symfile=@olive-editor.sym ^
-F key="%GH_AUTH_KEY%" ^
https://olivevideoeditor.org/crashpad/symbols.php
- name: Upload Installer to Nightly Page
shell: bash
working-directory: ${{ runner.workspace }}/build
env:
GH_AUTH_KEY: ${{ secrets.GH_AUTH_KEY }}
run: |
curl -X POST \
-F file=@$PKGNAME.exe \
-F key="$GH_AUTH_KEY" \
-F hash="$GITHUB_SHA" \
-F time="$(git -C $GITHUB_WORKSPACE show -s --format=%ct)" \
-F comment="$(git -C $GITHUB_WORKSPACE show -s --format=%B)" \
https://olivevideoeditor.org/dl/push.php
if: github.event_name != 'pull_request'
- name: Upload Installer to Nightly Page
shell: bash
working-directory: ${{ runner.workspace }}/build
env:
GH_AUTH_KEY: ${{ secrets.GH_AUTH_KEY }}
run: |
curl -X POST \
-F file=@$PKGNAME.exe \
-F key="$GH_AUTH_KEY" \
-F hash="$GITHUB_SHA" \
-F time="$(git -C $GITHUB_WORKSPACE show -s --format=%ct)" \
-F comment="$(git -C $GITHUB_WORKSPACE show -s --format=%B)" \
https://olivevideoeditor.org/dl/push.php
if: github.event_name != 'pull_request'
- name: Upload Portable to Nightly Page
shell: bash
working-directory: ${{ runner.workspace }}/build
env:
GH_AUTH_KEY: ${{ secrets.GH_AUTH_KEY }}
run: |
curl -X POST \
-F file=@$PKGNAME.zip \
-F key="$GH_AUTH_KEY" \
-F hash="$GITHUB_SHA" \
-F time="$(git -C $GITHUB_WORKSPACE show -s --format=%ct)" \
-F comment="$(git -C $GITHUB_WORKSPACE show -s --format=%B)" \
https://olivevideoeditor.org/dl/push.php
if: github.event_name != 'pull_request'
- name: Upload Portable to Nightly Page
shell: bash
working-directory: ${{ runner.workspace }}/build
env:
GH_AUTH_KEY: ${{ secrets.GH_AUTH_KEY }}
run: |
curl -X POST \
-F file=@$PKGNAME.zip \
-F key="$GH_AUTH_KEY" \
-F hash="$GITHUB_SHA" \
-F time="$(git -C $GITHUB_WORKSPACE show -s --format=%ct)" \
-F comment="$(git -C $GITHUB_WORKSPACE show -s --format=%B)" \
https://olivevideoeditor.org/dl/push.php
if: github.event_name != 'pull_request'
- name: Upload Installer Artifact to GitHub
uses: actions/upload-artifact@v2
with:
name: ${{ env.PKGNAME }}.exe
path: ${{ runner.workspace }}/build/${{ env.PKGNAME }}.exe
- name: Upload Installer Artifact
uses: actions/upload-artifact@v2
with:
name: ${{ env.PKGNAME }}.exe
path: ${{ runner.workspace }}/build/${{ env.PKGNAME }}.exe
- name: Upload Portable Artifact to GitHub
uses: actions/upload-artifact@v2
with:
name: ${{ env.PKGNAME }}.zip
path: ${{ runner.workspace }}/build/${{ env.PKGNAME }}.zip
- name: Upload Portable Artifact
uses: actions/upload-artifact@v2
with:
name: ${{ env.PKGNAME }}.zip
path: ${{ runner.workspace }}/build/${{ env.PKGNAME }}.zip
- name: Export Crashpad Symbols and Upload To Server
working-directory: ${{ runner.workspace }}/build
shell: cmd
env:
GH_AUTH_KEY: ${{ secrets.GH_AUTH_KEY }}
run: |
curl -fLSs --retry 3 https://github.com/google/breakpad/blob/master/src/tools/windows/binaries/dump_syms.exe?raw=true > dump_syms.exe
dump_syms app\olive-editor.pdb > olive-editor.sym
curl -X POST ^
-F symfile=@olive-editor.sym ^
-F key="%GH_AUTH_KEY%" ^
https://olivevideoeditor.org/crashpad/symbols.php
- if: matrix.os == 'macos-latest'
- name: Create Package
working-directory: ${{ runner.workspace }}/build
env:
BUNDLE_NAME: Olive.app
run: |
mv app/$BUNDLE_NAME .
macdeployqt $BUNDLE_NAME
curl -fLOSs --retry 3 https://github.com/arl/macdeployqtfix/raw/master/macdeployqtfix.py
python2 macdeployqtfix.py $BUNDLE_NAME/Contents/MacOS/Olive /usr/local/Cellar/qt5/5.*/
- name: Deploy Package
working-directory: ${{ runner.workspace }}/build
run: |
zip -r $PKGNAME.zip $BUNDLE_NAME
- name: Upload Artifact to Nightly Page
shell: bash
working-directory: ${{ runner.workspace }}/build
env:
GH_AUTH_KEY: ${{ secrets.GH_AUTH_KEY }}
run: |
curl -X POST \
-F file=@$PKGNAME.zip \
-F key="$GH_AUTH_KEY" \
-F hash="$GITHUB_SHA" \
-F time="$(git -C $GITHUB_WORKSPACE show -s --format=%ct)" \
-F comment="$(git -C $GITHUB_WORKSPACE show -s --format=%B)" \
https://olivevideoeditor.org/dl/push.php
if: github.event_name != 'pull_request'
- name: Upload Artifact to GitHub
uses: actions/upload-artifact@v2
with:
name: ${{ env.PKGNAME }}.zip
path: ${{ runner.workspace }}/build/${{ env.PKGNAME }}.zip
+28 -6
View File
@@ -477,14 +477,19 @@ bool FFmpegDecoder::Probe(Footage *f, const QAtomicInt* cancelled)
// Retrieve metadata about the media
avformat_find_stream_info(fmt_ctx, nullptr);
QVector<StreamPtr> streams(fmt_ctx->nb_streams);
// Dump it into the Footage object
for (unsigned int i=0;i<fmt_ctx->nb_streams;i++) {
AVStream* avstream = fmt_ctx->streams[i];
// Find decoder for this stream, if it exists we can proceed
AVCodec* decoder = avcodec_find_decoder(avstream->codecpar->codec_id);
StreamPtr str;
if (avstream->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
if (avstream->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && decoder) {
bool image_is_still = false;
rational pixel_aspect_ratio;
@@ -564,7 +569,7 @@ bool FFmpegDecoder::Probe(Footage *f, const QAtomicInt* cancelled)
str = image_stream;
} else if (avstream->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
} else if (avstream->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && decoder) {
// Create an audio stream object
AudioStreamPtr audio_stream = std::make_shared<AudioStream>();
@@ -600,7 +605,7 @@ bool FFmpegDecoder::Probe(Footage *f, const QAtomicInt* cancelled)
str->set_type(Stream::kAttachment);
break;
default:
// We should never realistically get here, but we make an "invalid" stream just in case
// Fallback to an unknown stream
str->set_type(Stream::kUnknown);
break;
}
@@ -611,11 +616,27 @@ bool FFmpegDecoder::Probe(Footage *f, const QAtomicInt* cancelled)
str->set_timebase(avstream->time_base);
str->set_duration(avstream->duration);
f->add_stream(str);
streams[i] = str;
}
// As long as we can open the container and retrieve information, this was a successful probe
result = true;
// Check if we could pick up any streams in this file
bool found_valid_streams = false;
foreach (StreamPtr stream, streams) {
if (stream->type() != Stream::kUnknown) {
found_valid_streams = true;
break;
}
}
if (found_valid_streams) {
// Copy streams over
foreach (StreamPtr stream, streams) {
f->add_stream(stream);
}
result = true;
}
}
// Free all memory
@@ -1330,6 +1351,7 @@ void FFmpegDecoderInstance::RemoveFirstFrame()
FFmpegDecoderInstance::FFmpegDecoderInstance(const char *filename, int stream_index) :
fmt_ctx_(nullptr),
codec_ctx_(nullptr),
opts_(nullptr),
scale_ctx_(nullptr),
scale_divider_(0),
+48 -8
View File
@@ -25,21 +25,55 @@
#include <QCoreApplication>
#include <QDebug>
#include <QDir>
#include <QMessageBox>
#include "filefunctions.h"
#ifdef Q_OS_WINDOWS
#include <Windows.h>
#endif
// Copied from base::FilePath to match its macro
#if defined(OS_POSIX)
// On most platforms, native pathnames are char arrays, and the encoding
// may or may not be specified. On Mac OS X, native pathnames are encoded
// in UTF-8.
#define TO_BASE_STRING_TYPE(x) x.toStdString()
// On most platforms, native pathnames are char arrays, and the encoding
// may or may not be specified. On Mac OS X, native pathnames are encoded
// in UTF-8.
#define TO_BASE_STRING_TYPE(x) x.toStdString()
#elif defined(OS_WIN)
// On Windows, for Unicode-aware applications, native pathnames are wchar_t
// arrays encoded in UTF-16.
#define TO_BASE_STRING_TYPE(x) x.toStdWString()
// On Windows, for Unicode-aware applications, native pathnames are wchar_t
// arrays encoded in UTF-16.
#define TO_BASE_STRING_TYPE(x) x.toStdWString()
#endif // OS_WIN
crashpad::CrashpadClient *client;
bool ShowCrashConfirmation()
{
QString msg = QCoreApplication::translate("CrashReport",
"We're sorry, Olive has crashed. "
"Would you like to send an error report to "
"help developers fix this issue?\n\n"
"Crash reports are anonymous and only send "
"non-specific details about your computer and"
"how the crash occurred.");
return (QMessageBox::critical(nullptr,
QString(),
msg,
QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes);
}
#ifdef Q_OS_WINDOWS
LONG WINAPI Win32ExceptionHandler(_EXCEPTION_POINTERS *ExceptionInfo)
{
if (ShowCrashConfirmation()) {
client->DumpAndCrash(ExceptionInfo);
}
return EXCEPTION_CONTINUE_SEARCH;
}
#endif
bool InitializeCrashpad()
{
QString exe_dir = QCoreApplication::applicationDirPath();
@@ -73,9 +107,15 @@ bool InitializeCrashpad()
settings->SetUploadsEnabled(true);
// Start crash handler
crashpad::CrashpadClient *client = new crashpad::CrashpadClient();
client = new crashpad::CrashpadClient();
bool status = client->StartHandler(handler, reports_dir, metrics_dir,
url, annotations, arguments, true, true);
// Override Crashpad exception filter with our own
#ifdef Q_OS_WINDOWS
SetUnhandledExceptionFilter(Win32ExceptionHandler);
#endif
return status;
}
+9 -1
View File
@@ -51,6 +51,7 @@
#include "render/pixelformat.h"
#include "render/shaderinfo.h"
#include "task/project/import/import.h"
#include "task/project/import/importerrordialog.h"
#include "task/project/load/load.h"
#include "task/project/save/save.h"
#include "task/taskmanager.h"
@@ -473,7 +474,14 @@ void Core::AddOpenProjectFromTask(Task *task)
void Core::ImportTaskComplete(Task* task)
{
QUndoCommand *command = static_cast<ProjectImportTask*>(task)->GetCommand();
ProjectImportTask* import_task = static_cast<ProjectImportTask*>(task);
QUndoCommand *command = import_task->GetCommand();
if (import_task->HasInvalidFiles()) {
ProjectImportErrorDialog d(import_task->GetInvalidFiles(), main_window_);
d.exec();
}
undo_stack_.pushIfHasChildren(command);
}
+29 -29
View File
@@ -32,35 +32,35 @@ InstallDir "$PROGRAMFILES32\${APP_NAME}"
!insertmacro MUI_LANGUAGE "English"
Section "Olive (required)"
SectionIn RO
SetOutPath $INSTDIR
File /r olive-editor\*
WriteUninstaller "$INSTDIR\uninstall.exe"
Section "Olive"
SectionIn RO
SetOutPath $INSTDIR
File /r olive-editor\*
WriteUninstaller "$INSTDIR\uninstall.exe"
# Install Visual C++ 2010 Redistributable
File "vcredist_x64.exe"
ExecWait '"$INSTDIR\vcredist_x64.exe" /quiet'
Delete "$INSTDIR\vcredist_x64.exe"
SectionEnd
Section "Create Desktop shortcut"
CreateShortCut "$DESKTOP\${APP_NAME}.lnk" "$INSTDIR\${APP_TARGET}.exe"
CreateShortCut "$DESKTOP\${APP_NAME}.lnk" "$INSTDIR\${APP_TARGET}.exe"
SectionEnd
Section "Create Start Menu shortcut"
CreateDirectory "$SMPROGRAMS\${APP_NAME}"
CreateShortCut "$SMPROGRAMS\${APP_NAME}\${APP_NAME}.lnk" "$INSTDIR\${APP_TARGET}.exe"
CreateShortCut "$SMPROGRAMS\${APP_NAME}\Uninstall ${APP_NAME}.lnk" "$INSTDIR\uninstall.exe"
CreateDirectory "$SMPROGRAMS\${APP_NAME}"
CreateShortCut "$SMPROGRAMS\${APP_NAME}\${APP_NAME}.lnk" "$INSTDIR\${APP_TARGET}.exe"
CreateShortCut "$SMPROGRAMS\${APP_NAME}\Uninstall ${APP_NAME}.lnk" "$INSTDIR\uninstall.exe"
SectionEnd
Section "Associate *.ove files with Olive"
WriteRegStr HKCR ".ove" "" "OliveEditor.OVEFile"
WriteRegStr HKCR ".ove" "Content Type" "application/vnd.olive-project"
WriteRegStr HKCR "OliveEditor.OVEFile" "" "Olive project file"
WriteRegStr HKCR "OliveEditor.OVEFile\DefaultIcon" "" "$INSTDIR\olive-editor.exe,1"
WriteRegStr HKCR "OliveEditor.OVEFile\shell\open\command" "" "$\"$INSTDIR\olive-editor.exe$\" $\"%1$\""
System::Call 'shell32.dll::SHChangeNotify(i, i, i, i) v (0x08000000, 0, 0, 0)'
WriteRegStr HKCR ".ove" "" "OliveEditor.OVEFile"
WriteRegStr HKCR ".ove" "Content Type" "application/vnd.olive-project"
WriteRegStr HKCR "OliveEditor.OVEFile" "" "Olive project file"
WriteRegStr HKCR "OliveEditor.OVEFile\DefaultIcon" "" "$INSTDIR\olive-editor.exe,1"
WriteRegStr HKCR "OliveEditor.OVEFile\shell\open\command" "" "$\"$INSTDIR\olive-editor.exe$\" $\"%1$\""
System::Call 'shell32.dll::SHChangeNotify(i, i, i, i) v (0x08000000, 0, 0, 0)'
SectionEnd
UninstPage uninstConfirm
@@ -68,18 +68,18 @@ UninstPage instfiles
Section "uninstall"
rmdir /r "$INSTDIR"
rmdir /r "$INSTDIR"
Delete "$DESKTOP\${APP_NAME}.lnk"
rmdir /r "$SMPROGRAMS\${APP_NAME}"
DeleteRegKey HKCR ".ove"
DeleteRegKey HKCR "OliveEditor.OVEFile"
DeleteRegKey HKCR "OliveEditor.OVEFile\DefaultIcon" ""
DeleteRegKey HKCR "OliveEditor.OVEFile\shell\open\command" ""
System::Call 'shell32.dll::SHChangeNotify(i, i, i, i) v (0x08000000, 0, 0, 0)'
Delete "$DESKTOP\${APP_NAME}.lnk"
rmdir /r "$SMPROGRAMS\${APP_NAME}"
DeleteRegKey HKCR ".ove"
DeleteRegKey HKCR "OliveEditor.OVEFile"
DeleteRegKey HKCR "OliveEditor.OVEFile\DefaultIcon" ""
DeleteRegKey HKCR "OliveEditor.OVEFile\shell\open\command" ""
System::Call 'shell32.dll::SHChangeNotify(i, i, i, i) v (0x08000000, 0, 0, 0)'
SectionEnd
Function LaunchOlive
ExecShell "" "$INSTDIR\${APP_TARGET}.exe"
ExecShell "" "$INSTDIR\${APP_TARGET}.exe"
FunctionEnd
+4
View File
@@ -268,6 +268,10 @@ void Sequence::set_parameters_from_footage(const QList<Footage *> footage)
foreach (Footage* f, footage) {
foreach (StreamPtr s, f->streams()) {
if (!s->enabled()) {
continue;
}
switch (s->type()) {
case Stream::kVideo:
{
+6 -7
View File
@@ -375,13 +375,6 @@ void RenderBackend::RunNextJob()
return;
}
// Check if params are valid
if (!video_params_.is_valid()
|| !audio_params_.is_valid()) {
qDebug() << "Failed to run job, parameters are invalid";
return;
}
// If we have a value update queued, check if all workers are available and proceed from there
if (autocache_enabled_ && !graph_update_queue_.isEmpty()) {
bool all_workers_available = true;
@@ -449,6 +442,8 @@ void RenderBackend::RunNextJob()
switch (ticket->GetType()) {
case RenderTicket::kTypeHash:
Q_ASSERT(video_params_.is_valid());
QtConcurrent::run(&thread_pool_,
worker,
&RenderWorker::Hash,
@@ -458,6 +453,8 @@ void RenderBackend::RunNextJob()
break;
case RenderTicket::kTypeVideo:
{
Q_ASSERT(video_params_.is_valid());
rational frame = ticket->GetTime().value<rational>();
QtConcurrent::run(&thread_pool_,
@@ -474,6 +471,8 @@ void RenderBackend::RunNextJob()
break;
}
case RenderTicket::kTypeAudio:
Q_ASSERT(audio_params_.is_valid());
QtConcurrent::run(&thread_pool_,
worker,
&RenderWorker::RenderAudio,
+1 -1
View File
@@ -126,7 +126,7 @@ void RenderWorker::RenderFrame(RenderTicketPtr ticket, ViewerOutput* viewer, con
FramePtr frame = Frame::Create();
frame->set_timestamp(time);
if (video_force_download_resolution_ || texture.isNull()) {
if (video_force_download_resolution_) {
// If we're setting the resolution ourselves or we're zeroing it out, allocate the frame now
frame->set_video_params(VideoParams(video_params_.width(),
video_params_.height(),
+2
View File
@@ -18,5 +18,7 @@ set(OLIVE_SOURCES
${OLIVE_SOURCES}
task/project/import/import.h
task/project/import/import.cpp
task/project/import/importerrordialog.h
task/project/import/importerrordialog.cpp
PARENT_SCOPE
)
+5 -2
View File
@@ -122,7 +122,10 @@ void ProjectImportTask::Import(Folder *folder, const QFileInfoList &import, int
f->set_project(nullptr);
if (f->status() != Footage::kInvalid) {
if (f->status() == Footage::kInvalid) {
// Add to list so we can tell the user about it later
invalid_files_.append(file_info.absoluteFilePath());
} else {
// Create undoable command that adds the items to the model
new ProjectViewModel::AddItemCommand(model_,
folder,
@@ -132,7 +135,7 @@ void ProjectImportTask::Import(Folder *folder, const QFileInfoList &import, int
counter++;
emit ProgressChanged((counter * 100) / file_count_);
emit ProgressChanged(static_cast<double>(counter) / static_cast<double>(file_count_));
}
}
+12
View File
@@ -42,6 +42,16 @@ public:
return command_;
}
const QStringList& GetInvalidFiles() const
{
return invalid_files_;
}
bool HasInvalidFiles() const
{
return !invalid_files_.isEmpty();
}
protected:
virtual bool Run() override;
@@ -58,6 +68,8 @@ private:
int file_count_;
QStringList invalid_files_;
};
OLIVE_NAMESPACE_EXIT
@@ -0,0 +1,53 @@
/***
Olive - Non-Linear Video Editor
Copyright (C) 2019 Olive Team
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
***/
#include "importerrordialog.h"
#include <QDialogButtonBox>
#include <QLabel>
#include <QListWidget>
#include <QVBoxLayout>
OLIVE_NAMESPACE_ENTER
ProjectImportErrorDialog::ProjectImportErrorDialog(const QStringList& filenames, QWidget* parent) :
QDialog(parent)
{
QVBoxLayout* layout = new QVBoxLayout(this);
setWindowTitle(tr("Import Error"));
layout->addWidget(new QLabel(tr("The following files failed to import. Olive likely does not "
"support their formats.")));
QListWidget* list_widget = new QListWidget();
foreach (const QString& s, filenames) {
list_widget->addItem(s);
}
layout->addWidget(list_widget);
QDialogButtonBox* buttons = new QDialogButtonBox();
buttons->setStandardButtons(QDialogButtonBox::Ok);
buttons->setCenterButtons(true);
connect(buttons, &QDialogButtonBox::accepted, this, &ProjectImportErrorDialog::accept);
layout->addWidget(buttons);
}
OLIVE_NAMESPACE_EXIT
@@ -0,0 +1,40 @@
/***
Olive - Non-Linear Video Editor
Copyright (C) 2019 Olive Team
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
***/
#ifndef PROJECTIMPORTERRORDIALOG_H
#define PROJECTIMPORTERRORDIALOG_H
#include <QDialog>
#include "common/define.h"
OLIVE_NAMESPACE_ENTER
class ProjectImportErrorDialog : public QDialog
{
Q_OBJECT
public:
ProjectImportErrorDialog(const QStringList& filenames, QWidget* parent = nullptr);
};
OLIVE_NAMESPACE_EXIT
#endif // PROJECTIMPORTERRORDIALOG_H
+2
View File
@@ -39,6 +39,7 @@ QMap<QString, QString> StyleManager::available_themes_;
void StyleManager::UseOSNativeStyling(QWidget *widget)
{
#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) || QT_VERSION > QT_VERSION_CHECK(5, 15, 1)
#if defined(Q_OS_WINDOWS)
QStyle* s = QStyleFactory::create(QStringLiteral("windowsvista"));
widget->setStyle(s);
@@ -48,6 +49,7 @@ void StyleManager::UseOSNativeStyling(QWidget *widget)
widget->setStyle(s);
widget->setPalette(s->standardPalette());
#endif
#endif
}
QPalette StyleManager::ParsePalette(const QString& ini_path)
+6 -4
View File
@@ -51,10 +51,12 @@ SliderLabel::SliderLabel(QWidget *parent) :
void SliderLabel::mousePressEvent(QMouseEvent *e)
{
if (e->modifiers() & Qt::AltModifier) {
emit RequestReset();
} else {
emit LabelPressed();
if (e->button() == Qt::LeftButton) {
if (e->modifiers() & Qt::AltModifier) {
emit RequestReset();
} else {
emit LabelPressed();
}
}
}
+10 -3
View File
@@ -103,9 +103,7 @@ void SliderLadder::mouseReleaseEvent(QMouseEvent *event)
{
Q_UNUSED(event)
drag_timer_.stop();
emit Released();
this->close();
}
void SliderLadder::showEvent(QShowEvent *event)
@@ -115,6 +113,15 @@ void SliderLadder::showEvent(QShowEvent *event)
drag_timer_.start();
}
void SliderLadder::closeEvent(QCloseEvent *event)
{
Q_UNUSED(event)
drag_timer_.stop();
emit Released();
}
void SliderLadder::TimerUpdate()
{
int32_t x_mvmt, y_mvmt;
+2
View File
@@ -75,6 +75,8 @@ protected:
virtual void showEvent(QShowEvent *event) override;
virtual void closeEvent(QCloseEvent* event) override;
signals:
void DraggedByValue(int value, double multiplier);
@@ -46,6 +46,7 @@ TimelineView::TimelineView(Qt::Alignment vertical_alignment, QWidget *parent) :
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
setBackgroundRole(QPalette::Window);
setContextMenuPolicy(Qt::CustomContextMenu);
setViewportUpdateMode(QGraphicsView::FullViewportUpdate);
viewport()->setMouseTracking(true);
}
+20 -31
View File
@@ -33,8 +33,10 @@ FootageViewerWidget::FootageViewerWidget(QWidget *parent) :
footage_(nullptr)
{
video_node_ = new VideoInput();
sequence_.AddNode(video_node_);
audio_node_ = new AudioInput();
viewer_node_ = new ViewerOutput();
sequence_.AddNode(audio_node_);
connect(display_widget(), &ViewerDisplayWidget::DragStarted, this, &FootageViewerWidget::StartFootageDrag);
@@ -55,17 +57,29 @@ void FootageViewerWidget::SetFootage(Footage *footage)
ConnectViewerNode(nullptr);
NodeParam::DisconnectEdge(video_node_->output(), viewer_node_->texture_input());
NodeParam::DisconnectEdge(audio_node_->output(), viewer_node_->samples_input());
NodeParam::DisconnectEdge(video_node_->output(), sequence_.viewer_output()->texture_input());
NodeParam::DisconnectEdge(audio_node_->output(), sequence_.viewer_output()->samples_input());
}
footage_ = footage;
if (footage_) {
// Update sequence media name
sequence_.viewer_output()->set_media_name(footage_->name());
// Reset parameters and then attempt to set from footage
sequence_.set_default_parameters();
sequence_.set_parameters_from_footage({footage_});
// Use first of each stream
VideoStreamPtr video_stream = nullptr;
AudioStreamPtr audio_stream = nullptr;
foreach (StreamPtr s, footage_->streams()) {
if (!s->enabled()) {
continue;
}
if (!audio_stream && s->type() == Stream::kAudio) {
audio_stream = std::static_pointer_cast<AudioStream>(s);
}
@@ -80,42 +94,17 @@ void FootageViewerWidget::SetFootage(Footage *footage)
}
}
viewer_node_->set_media_name(footage_->name());
if (video_stream) {
video_node_->SetFootage(video_stream);
viewer_node_->set_video_params(VideoParams(video_stream->width(),
video_stream->height(),
video_stream->frame_rate().flipped(),
static_cast<PixelFormat::Format>(Config::Current()["DefaultSequencePreviewFormat"].toInt()),
video_stream->pixel_aspect_ratio(),
video_stream->interlacing(),
VideoParams::generate_auto_divider(video_stream->width(), video_stream->height())));
NodeParam::ConnectEdge(video_node_->output(), viewer_node_->texture_input());
} else {
int width = Config::Current()["DefaultSequenceWidth"].toInt();
int height = Config::Current()["DefaultSequenceHeight"].toInt();
viewer_node_->set_video_params(VideoParams(width,
height,
Config::Current()["DefaultSequenceFrameRate"].value<rational>(),
static_cast<PixelFormat::Format>(Config::Current()["DefaultSequencePreviewFormat"].toInt()),
Config::Current()["DefaultSequencePixelAspect"].value<rational>(),
Config::Current()["DefaultSequenceInterlacing"].value<VideoParams::Interlacing>(),
VideoParams::generate_auto_divider(width, height)));
NodeParam::ConnectEdge(video_node_->output(), sequence_.viewer_output()->texture_input());
}
if (audio_stream) {
audio_node_->SetFootage(audio_stream);
viewer_node_->set_audio_params(AudioParams(audio_stream->sample_rate(), audio_stream->channel_layout(), SampleFormat::kInternalFormat));
NodeParam::ConnectEdge(audio_node_->output(), viewer_node_->samples_input());
} else {
viewer_node_->set_audio_params(AudioParams(Config::Current()["DefaultSequenceAudioFrequency"].toInt(),
Config::Current()["DefaultSequenceAudioLayout"].toULongLong(),
SampleFormat::kInternalFormat));
NodeParam::ConnectEdge(audio_node_->output(), sequence_.viewer_output()->samples_input());
}
ConnectViewerNode(viewer_node_, footage_->project()->color_manager());
ConnectViewerNode(sequence_.viewer_output(), footage_->project()->color_manager());
SetTimestamp(cached_timestamps_.value(footage_, 0));
}
+2 -2
View File
@@ -47,12 +47,12 @@ private:
Footage* footage_;
Sequence sequence_;
VideoInput* video_node_;
AudioInput* audio_node_;
ViewerOutput* viewer_node_;
QHash<Footage*, int64_t> cached_timestamps_;
private slots:
+3 -1
View File
@@ -566,7 +566,9 @@ QString ViewerWidget::GetCachedFilenameFromTime(const rational &time)
bool ViewerWidget::FrameExistsAtTime(const rational &time)
{
return GetConnectedNode() && time >= 0 && time < GetConnectedNode()->video_frame_cache()->GetLength();
return GetConnectedNode()
&& ((time >= 0 && time < GetConnectedNode()->video_frame_cache()->GetLength())
|| GetConnectedNode()->video_frame_cache()->GetLength().isNull());
}
void ViewerWidget::SetDisplayImage(FramePtr frame, bool main_only)
+5 -1
View File
@@ -99,7 +99,11 @@ void ViewerDisplayWidget::SetSignalCursorColorEnabled(bool e)
void ViewerDisplayWidget::SetImage(FramePtr in_buffer)
{
last_loaded_buffer_ = in_buffer;
if (in_buffer && in_buffer->is_allocated()) {
last_loaded_buffer_ = in_buffer;
} else {
last_loaded_buffer_ = nullptr;
}
if (last_loaded_buffer_) {
makeCurrent();
+16
View File
@@ -349,6 +349,22 @@ void MainWindow::ProjectClose(Project *p)
CloseSequence(seq);
}
}
// Close any open footage in footage viewer
QList<ItemPtr> footage = p->get_items_of_type(Item::kFootage);
QList<Footage*> footage_in_viewer = footage_viewer_panel_->GetSelectedFootage();
if (!footage_in_viewer.isEmpty()) {
// FootageViewer only has the one footage item
Footage* f = footage_in_viewer.first();
foreach (ItemPtr i, footage) {
if (f == i.get()) {
footage_viewer_panel_->SetFootage(nullptr);
break;
}
}
}
}
void MainWindow::SetApplicationProgressStatus(ProgressStatus status)