CI-Build 2022-09-27
This commit is contained in:
commit
2f31bfc565
65 changed files with 175 additions and 48 deletions
2
.github/workflows/ci.yml
vendored
2
.github/workflows/ci.yml
vendored
|
@ -73,7 +73,7 @@ jobs:
|
|||
- name: Setup Meson
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install meson==0.62.2
|
||||
pip install meson
|
||||
|
||||
- name: Setup MSVC
|
||||
if: matrix.config.os == 'windows-latest' && matrix.config.msvc == true
|
||||
|
|
10
README.md
10
README.md
|
@ -2,7 +2,7 @@
|
|||
Go [here](#branchfeature-list) for the new features.
|
||||
|
||||
### Don't we have enough Aegisub forks already??
|
||||
We absolutely do, and I'm aware that adding another one [doesn't sound like a good idea on paper](https://xkcd.com/927/). However,
|
||||
We absolutely do, and I'm aware that adding another one [doesn't sound like](https://xkcd.com/927/) a [good idea on paper](https://cdn.discordapp.com/attachments/425357202963038208/1007103606421459004/unknown.png). However,
|
||||
|
||||
- None of the existing forks are completely satisfying at the moment:
|
||||
- [wangqr's fork](https://github.com/wangqr/Aegisub) is actively maintained, but focussing more on stability. It's missing most of the modern features.
|
||||
|
@ -28,10 +28,11 @@ This list is for navigating the repository. Go to the [release page](https://git
|
|||
- [`bestsource`](https://github.com/arch1t3cht/Aegisub/tree/bestsource): Add BestSource audio and video source. This source is slower than others by multiple orders of magnitude, but in exchange it can guarantee exact seeking.
|
||||
- [`vapoursynth`](https://github.com/arch1t3cht/Aegisub/tree/vapoursynth): Add Vapoursynth audio and video source
|
||||
- [`bugfixes`](https://github.com/arch1t3cht/Aegisub/tree/bugfixes): Various fixes necessary for compilation. Most branches are based on this.
|
||||
- [`workarounds`](https://github.com/arch1t3cht/Aegisub/tree/workarounds): Same as `bugfixes`, but these are hacky fixes that probably shouldn't be pulled without more work.
|
||||
- [`fixes`](https://github.com/arch1t3cht/Aegisub/tree/fixes): Miscellaneous bugfixes
|
||||
- [`misc`](https://github.com/arch1t3cht/Aegisub/tree/misc): Other miscellaneous additions
|
||||
- [`misc_dc`](https://github.com/arch1t3cht/Aegisub/tree/misc_dc): Miscellaneous changes taken from AegisubDC
|
||||
- [`xa-ds2`](https://github.com/arch1t3cht/Aegisub/tree/xa-ds2): Add XAudio2 backend and allow stereo playback for some other backends, by wangqr and Shinon.
|
||||
- [`xa2-ds`](https://github.com/arch1t3cht/Aegisub/tree/xa2-ds): Add XAudio2 backend and allow stereo playback for some other backends, by wangqr and Shinon.
|
||||
- [`stereo`](https://github.com/arch1t3cht/Aegisub/tree/stereo): Add multi-channel support for the other audio backends where possible.
|
||||
- [`video_panning_feature`](https://github.com/arch1t3cht/Aegisub/tree/video_panning_feature): Merge [moex3's video zoom and panning](https://github.com/TypesettingTools/Aegisub/pull/150), with an OSX fix and more options to control zoom behavior
|
||||
- [`spectrum-frequency-mapping`](https://github.com/arch1t3cht/Aegisub/tree/spectrum-frequency-mapping): Merge EleonoreMizo's [spectrum display improvements](https://github.com/TypesettingTools/Aegisub/pull/94), and also make Shift+Scroll vertically zoom the audio display
|
||||
|
@ -43,13 +44,10 @@ If it wasn't introduced by my fork, I can still take a look, but I can't promise
|
|||
|
||||
You can find me for support on various servers, including the cave and the TSTools server linked below.
|
||||
|
||||
#### Building fails with a "CMake sandbox violation"
|
||||
This is an upstream bug in meson. For now, you need to downgrade meson using `pip install meson==0.62.2`.
|
||||
|
||||
#### Aegisub on Linux doesn't recognize my GTK theme
|
||||
This is probably because you're building with wxgtk2. Building with wxgtk3 fixes this, but causes some problems of its own (notably the broken color picker, occasional crashes when opening file dialogs from automation scripts, and general layouting issues).
|
||||
|
||||
The exact way of switching depends on your Linux distribution, but essentially you need to ensure that `wx-config` or the next best variant of it points to wxgtk3. If it points to wxgtk2 by default and deinstalling wxgtk2 isn't an option, you can also temporarily move it out of the path. Then, fully reconfigure meson using `meson configure --clearcache` and `meson setup --reconfigure`.
|
||||
The exact way of switching depends on your Linux distribution, but essentially you need to ensure that `wx-config` or the next best variant of it points to wxgtk3. If it points to wxgtk2 by default and deinstalling wxgtk2 isn't an option, you can also temporarily move it out of the path or use a `native-file` in your meson project. Then, fully reconfigure meson using `meson configure --clearcache` and `meson setup --reconfigure`.
|
||||
|
||||
#### I get errors like "Option not found" after merging one of these branches
|
||||
The changes to `default_config.json` or similar files weren't detected by meson due to missing regen dependencies. You can either merge the `bugfixes` branch or rebuild from scratch.
|
||||
|
|
|
@ -360,7 +360,7 @@ if not deps.contains(luajit)
|
|||
else
|
||||
luajit_inc = include_directories(luajit.get_variable('includedir'))
|
||||
endif
|
||||
subdir('subprojects/luabins/src')
|
||||
subdir('vendor/luabins/src')
|
||||
|
||||
dep_gl = dependency('gl', required: false)
|
||||
if not dep_gl.found()
|
||||
|
|
|
@ -53,9 +53,9 @@ Write-Output 'Copying - translations'
|
|||
Copy-New-Items "$InstallerDir\share\locale\*" "$PortableOutputDir\locale" -Recurse
|
||||
Write-Output 'Copying - codecs'
|
||||
Write-Output 'Copying - codecs\Avisynth'
|
||||
Copy-New-Item $InstallerDepsDir\AvisynthPlus64\x86-64\DevIL.dll $PortableOutputDir
|
||||
Copy-New-Item $InstallerDepsDir\AvisynthPlus64\x86-64\AviSynth.dll $PortableOutputDir
|
||||
Copy-New-Item $InstallerDepsDir\AvisynthPlus64\x86-64\plugins\DirectShowSource.dll $PortableOutputDir
|
||||
Copy-New-Item $InstallerDepsDir\AvisynthPlus64\x64\system\DevIL.dll $PortableOutputDir
|
||||
Copy-New-Item $InstallerDepsDir\AvisynthPlus64\x64\AviSynth.dll $PortableOutputDir
|
||||
Copy-New-Item $InstallerDepsDir\AvisynthPlus64\x64\plugins\DirectShowSource.dll $PortableOutputDir
|
||||
Write-Output 'Copying - codecs\VSFilter'
|
||||
Copy-New-Item $InstallerDepsDir\VSFilter\x64\VSFilter.dll $PortableOutputDir\csri
|
||||
Write-Output 'Copying - runtimes\MS-CRT'
|
||||
|
|
|
@ -64,8 +64,6 @@ public:
|
|||
};
|
||||
|
||||
AvisynthAudioProvider::AvisynthAudioProvider(agi::fs::path const& filename) try {
|
||||
agi::acs::CheckFileRead(filename);
|
||||
|
||||
std::lock_guard<std::mutex> lock(avs_wrapper.GetMutex());
|
||||
|
||||
try {
|
||||
|
@ -150,6 +148,7 @@ void AvisynthAudioProvider::FillBuffer(void *buf, int64_t start, int64_t count)
|
|||
}
|
||||
|
||||
std::unique_ptr<agi::AudioProvider> CreateAvisynthAudioProvider(agi::fs::path const& file, agi::BackgroundRunner *) {
|
||||
agi::acs::CheckFileRead(file);
|
||||
return agi::make_unique<AvisynthAudioProvider>(file);
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -28,13 +28,13 @@
|
|||
|
||||
#include <libaegisub/access.h>
|
||||
#include <libaegisub/format.h>
|
||||
#include <libaegisub/fs.h>
|
||||
#include <libaegisub/path.h>
|
||||
#include <libaegisub/make_unique.h>
|
||||
|
||||
#include <mutex>
|
||||
|
||||
#include "vapoursynth_wrap.h"
|
||||
#include "vapoursynth_common.h"
|
||||
#include "VSScript4.h"
|
||||
|
||||
namespace {
|
||||
|
@ -54,7 +54,6 @@ public:
|
|||
};
|
||||
|
||||
VapoursynthAudioProvider::VapoursynthAudioProvider(agi::fs::path const& filename) try {
|
||||
agi::acs::CheckFileRead(filename);
|
||||
std::lock_guard<std::mutex> lock(vs.GetMutex());
|
||||
|
||||
script = vs.GetScriptAPI()->createScript(nullptr);
|
||||
|
@ -62,7 +61,7 @@ VapoursynthAudioProvider::VapoursynthAudioProvider(agi::fs::path const& filename
|
|||
throw VapoursynthError("Error creating script API");
|
||||
}
|
||||
vs.GetScriptAPI()->evalSetWorkingDir(script, 1);
|
||||
if (vs.GetScriptAPI()->evaluateFile(script, filename.string().c_str())) {
|
||||
if (OpenScriptOrVideo(vs.GetScriptAPI(), script, filename, OPT_GET("Provider/Audio/VapourSynth/Default Script")->GetString())) {
|
||||
std::string msg = agi::format("Error executing VapourSynth script: %s", vs.GetScriptAPI()->getError(script));
|
||||
vs.GetScriptAPI()->freeScript(script);
|
||||
throw VapoursynthError(msg);
|
||||
|
@ -162,6 +161,7 @@ VapoursynthAudioProvider::~VapoursynthAudioProvider() {
|
|||
}
|
||||
|
||||
std::unique_ptr<agi::AudioProvider> CreateVapoursynthAudioProvider(agi::fs::path const& file, agi::BackgroundRunner *) {
|
||||
agi::acs::CheckFileRead(file);
|
||||
return agi::make_unique<VapoursynthAudioProvider>(file);
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -783,27 +783,33 @@ namespace {
|
|||
{
|
||||
bool failed = false;
|
||||
BackgroundScriptRunner bsr(parent, title);
|
||||
bsr.Run([&](ProgressSink *ps) {
|
||||
LuaProgressSink lps(L, ps, can_open_config);
|
||||
try {
|
||||
bsr.Run([&](ProgressSink *ps) {
|
||||
LuaProgressSink lps(L, ps, can_open_config);
|
||||
|
||||
// Insert our error handler under the function to call
|
||||
lua_pushcclosure(L, add_stack_trace, 0);
|
||||
lua_insert(L, -nargs - 2);
|
||||
// Insert our error handler under the function to call
|
||||
lua_pushcclosure(L, add_stack_trace, 0);
|
||||
lua_insert(L, -nargs - 2);
|
||||
|
||||
if (lua_pcall(L, nargs, nresults, -nargs - 2)) {
|
||||
if (!lua_isnil(L, -1)) {
|
||||
// if the call failed, log the error here
|
||||
ps->Log("\n\nLua reported a runtime error:\n");
|
||||
ps->Log(get_string_or_default(L, -1));
|
||||
if (lua_pcall(L, nargs, nresults, -nargs - 2)) {
|
||||
if (!lua_isnil(L, -1)) {
|
||||
// if the call failed, log the error here
|
||||
ps->Log("\n\nLua reported a runtime error:\n");
|
||||
ps->Log(get_string_or_default(L, -1));
|
||||
}
|
||||
lua_pop(L, 2);
|
||||
failed = true;
|
||||
}
|
||||
lua_pop(L, 2);
|
||||
failed = true;
|
||||
}
|
||||
else
|
||||
lua_remove(L, -nresults - 1);
|
||||
else
|
||||
lua_remove(L, -nresults - 1);
|
||||
|
||||
lua_gc(L, LUA_GCCOLLECT, 0);
|
||||
});
|
||||
lua_gc(L, LUA_GCCOLLECT, 0);
|
||||
});
|
||||
} catch (agi::UserCancelException const&) {
|
||||
if (!failed)
|
||||
lua_pop(L, 2);
|
||||
throw;
|
||||
}
|
||||
if (failed)
|
||||
throw agi::UserCancelException("Script threw an error");
|
||||
}
|
||||
|
|
|
@ -483,13 +483,13 @@ void BaseGrid::OnMouseEvent(wxMouseEvent &event) {
|
|||
else {
|
||||
// Only scroll if the mouse has moved to a different row to avoid
|
||||
// scrolling on sloppy clicks
|
||||
if (row != extendRow) {
|
||||
if (VisRowToRow(row) != extendRow) {
|
||||
if (row <= yPos)
|
||||
ScrollTo(yPos - 3);
|
||||
// When dragging down we give a 3 row margin to make it easier
|
||||
// to see what's going on, but we don't want to scroll down if
|
||||
// the user clicks on the bottom row and drags up
|
||||
else if (row > yPos + h / lineHeight - (row > extendRow ? 3 : 1))
|
||||
else if (row > yPos + h / lineHeight - (VisRowToRow(row) > extendRow ? 3 : 1))
|
||||
ScrollTo(yPos + 3);
|
||||
}
|
||||
}
|
||||
|
@ -512,7 +512,7 @@ void BaseGrid::OnMouseEvent(wxMouseEvent &event) {
|
|||
int old_y_pos = yPos;
|
||||
context->selectionController->SetActiveLine(dlg);
|
||||
ScrollTo(old_y_pos);
|
||||
extendRow = row;
|
||||
extendRow = VisRowToRow(row);
|
||||
|
||||
auto const& selection = context->selectionController->GetSelectedSet();
|
||||
|
||||
|
@ -541,7 +541,7 @@ void BaseGrid::OnMouseEvent(wxMouseEvent &event) {
|
|||
// Block select
|
||||
if ((click && shift && !alt) || holding) {
|
||||
extendRow = old_extend;
|
||||
int i1 = row;
|
||||
int i1 = VisRowToRow(row);
|
||||
int i2 = extendRow;
|
||||
|
||||
if (i1 > i2)
|
||||
|
@ -550,7 +550,7 @@ void BaseGrid::OnMouseEvent(wxMouseEvent &event) {
|
|||
// Toggle each
|
||||
Selection newsel;
|
||||
if (ctrl) newsel = selection;
|
||||
for (int i = VisRowToRow(i1); i <= VisRowToRow(i2); i++)
|
||||
for (int i = i1; i <= i2; i++)
|
||||
newsel.insert(GetDialogue(i));
|
||||
context->selectionController->SetSelectedSet(std::move(newsel));
|
||||
return;
|
||||
|
@ -739,14 +739,14 @@ void BaseGrid::OnKeyDown(wxKeyEvent &event) {
|
|||
if (shift && !ctrl && !alt) {
|
||||
extendRow = old_extend;
|
||||
// Set range
|
||||
int begin = next;
|
||||
int begin = VisRowToRow(next);
|
||||
int end = extendRow;
|
||||
if (end < begin)
|
||||
std::swap(begin, end);
|
||||
|
||||
// Select range
|
||||
Selection newsel;
|
||||
for (int i = VisRowToRow(begin); i <= VisRowToRow(end); i++)
|
||||
for (int i = begin; i <= end; i++)
|
||||
newsel.insert(GetDialogue(i));
|
||||
|
||||
context->selectionController->SetSelectedSet(std::move(newsel));
|
||||
|
|
|
@ -340,6 +340,9 @@
|
|||
"BestSource": {
|
||||
"Max Cache Size" : 100,
|
||||
"Aegisub Cache" : true
|
||||
},
|
||||
"VapourSynth" : {
|
||||
"Default Script" : "import vapoursynth as vs\nvs.core.bas.Source(source=filename).set_output()"
|
||||
}
|
||||
},
|
||||
"Avisynth" : {
|
||||
|
@ -365,6 +368,9 @@
|
|||
"Max Cache Size" : 1024,
|
||||
"Threads" : 0,
|
||||
"Seek Preroll" : 12
|
||||
},
|
||||
"VapourSynth" : {
|
||||
"Default Script" : "import vapoursynth as vs\nvs.core.lsmas.LWLibavSource(source=filename).set_output()"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -340,6 +340,9 @@
|
|||
"BestSource": {
|
||||
"Max Cache Size" : 100,
|
||||
"Aegisub Cache" : true
|
||||
},
|
||||
"VapourSynth" : {
|
||||
"Default Script" : "import vapoursynth as vs\nvs.core.bas.Source(source=filename).set_output()"
|
||||
}
|
||||
},
|
||||
"Avisynth" : {
|
||||
|
@ -365,6 +368,9 @@
|
|||
"Max Cache Size" : 1024,
|
||||
"Threads" : 0,
|
||||
"Seek Preroll" : 12
|
||||
},
|
||||
"VapourSynth" : {
|
||||
"Default Script" : "import vapoursynth as vs\nvs.core.lsmas.LWLibavSource(source=filename).set_output()"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -215,6 +215,7 @@ elif host_machine.system() == 'windows'
|
|||
depends: version_h,
|
||||
include_directories: [res_inc, version_inc, wx_inc])
|
||||
endif
|
||||
aegisub_src += windows.compile_resources('res/strings.rc')
|
||||
endif
|
||||
|
||||
if conf.has('WITH_FONTCONFIG')
|
||||
|
@ -241,6 +242,7 @@ opt_src = [
|
|||
'video_provider_bestsource.cpp',
|
||||
'bestsource_common.cpp']],
|
||||
['VapourSynth', ['vapoursynth_wrap.cpp',
|
||||
'vapoursynth_common.cpp',
|
||||
'audio_provider_vs.cpp',
|
||||
'video_provider_vs.cpp']],
|
||||
|
||||
|
|
|
@ -486,6 +486,32 @@ void Advanced_Video(wxTreebook *book, Preferences *parent) {
|
|||
p->SetSizerAndFit(p->sizer);
|
||||
}
|
||||
|
||||
void VapourSynth(wxTreebook *book, Preferences *parent) {
|
||||
#ifdef WITH_VAPOURSYNTH
|
||||
auto p = new OptionPage(book, parent, _("VapourSynth"), OptionPage::PAGE_SUB);
|
||||
auto video = p->PageSizer(_("Default Video Script"));
|
||||
|
||||
auto vhint = new wxStaticText(p, wxID_ANY, _("This script will be executed to load video files that aren't\nVapourSynth scripts (i.e. end in .py or .vpy).\nThe filename variable stores the path to the file."));
|
||||
p->sizer->Fit(p);
|
||||
vhint->Wrap(400);
|
||||
video->Add(vhint, 0, wxALL, 5);
|
||||
video->AddSpacer(16);
|
||||
|
||||
p->OptionAddMultiline(video, "Provider/Video/VapourSynth/Default Script");
|
||||
|
||||
auto audio = p->PageSizer(_("Default Audio Script"));
|
||||
auto ahint = new wxStaticText(p, wxID_ANY, _("This script will be executed to load audio files that aren't\nVapourSynth scripts (i.e. end in .py or .vpy).\nThe filename variable stores the path to the file."));
|
||||
p->sizer->Fit(p);
|
||||
ahint->Wrap(400);
|
||||
audio->Add(ahint, 0, wxALL, 5);
|
||||
audio->AddSpacer(16);
|
||||
|
||||
p->OptionAddMultiline(audio, "Provider/Audio/VapourSynth/Default Script");
|
||||
|
||||
p->SetSizerAndFit(p->sizer);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// wxDataViewIconTextRenderer with command name autocompletion
|
||||
class CommandRenderer final : public wxDataViewCustomRenderer {
|
||||
wxArrayString autocomplete;
|
||||
|
@ -741,6 +767,7 @@ Preferences::Preferences(wxWindow *parent): wxDialog(parent, -1, _("Preferences"
|
|||
Advanced(book, this);
|
||||
Advanced_Audio(book, this);
|
||||
Advanced_Video(book, this);
|
||||
VapourSynth(book, this);
|
||||
|
||||
book->Fit();
|
||||
|
||||
|
|
|
@ -156,6 +156,20 @@ wxControl *OptionPage::OptionAdd(wxFlexGridSizer *flex, const wxString &name, co
|
|||
}
|
||||
}
|
||||
|
||||
wxControl *OptionPage::OptionAddMultiline(wxSizer *sizer, const char *opt_name) {
|
||||
parent->AddChangeableOption(opt_name);
|
||||
const auto opt = OPT_GET(opt_name);
|
||||
|
||||
if (opt->GetType() != agi::OptionType::String) {
|
||||
throw agi::InternalError("Unsupported type for multiline option");
|
||||
}
|
||||
|
||||
auto text = new wxTextCtrl(this, -1, to_wx(opt->GetString()), wxDefaultPosition, wxSize(-1, 200), wxTE_MULTILINE);
|
||||
text->Bind(wxEVT_TEXT, StringUpdater(opt_name, parent));
|
||||
sizer->Add(text, wxSizerFlags().Expand());
|
||||
return text;
|
||||
}
|
||||
|
||||
void OptionPage::OptionChoice(wxFlexGridSizer *flex, const wxString &name, const wxArrayString &choices, const char *opt_name) {
|
||||
parent->AddChangeableOption(opt_name);
|
||||
const auto opt = OPT_GET(opt_name);
|
||||
|
|
|
@ -43,6 +43,7 @@ public:
|
|||
|
||||
void CellSkip(wxFlexGridSizer *flex);
|
||||
wxControl *OptionAdd(wxFlexGridSizer *flex, const wxString &name, const char *opt_name, double min=0, double max=INT_MAX, double inc=1);
|
||||
wxControl *OptionAddMultiline(wxSizer *flex, const char *opt_name);
|
||||
void OptionChoice(wxFlexGridSizer *flex, const wxString &name, const wxArrayString &choices, const char *opt_name);
|
||||
void OptionBrowse(wxFlexGridSizer *flex, const wxString &name, const char *opt_name, wxControl *enabler = nullptr, bool do_enable = false);
|
||||
void OptionFont(wxSizer *sizer, std::string opt_prefix);
|
||||
|
|
37
src/vapoursynth_common.cpp
Normal file
37
src/vapoursynth_common.cpp
Normal file
|
@ -0,0 +1,37 @@
|
|||
// Copyright (c) 2022, arch1t3cht <arch1t3cht@gmail.com>
|
||||
//
|
||||
// Permission to use, copy, modify, and distribute this software for any
|
||||
// purpose with or without fee is hereby granted, provided that the above
|
||||
// copyright notice and this permission notice appear in all copies.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
//
|
||||
// Aegisub Project http://www.aegisub.org/
|
||||
|
||||
#ifdef WITH_VAPOURSYNTH
|
||||
#include "vapoursynth_common.h"
|
||||
|
||||
#include "options.h"
|
||||
#include <libaegisub/fs.h>
|
||||
|
||||
#include <boost/algorithm/string/replace.hpp>
|
||||
|
||||
int OpenScriptOrVideo(const VSSCRIPTAPI *api, VSScript *script, agi::fs::path const& filename, std::string default_script) {
|
||||
if (agi::fs::HasExtension(filename, "py") || agi::fs::HasExtension(filename, "vpy")) {
|
||||
return api->evaluateFile(script, filename.string().c_str());
|
||||
} else {
|
||||
std::string fname = filename.string();
|
||||
boost::replace_all(fname, "\\", "\\\\");
|
||||
boost::replace_all(fname, "'", "\\'");
|
||||
std::string vscript = "filename = '" + fname + "'\n" + default_script;
|
||||
return api->evaluateBuffer(script, vscript.c_str(), "aegisub");
|
||||
}
|
||||
}
|
||||
|
||||
#endif // WITH_VAPOURSYNTH
|
24
src/vapoursynth_common.h
Normal file
24
src/vapoursynth_common.h
Normal file
|
@ -0,0 +1,24 @@
|
|||
// Copyright (c) 2022, arch1t3cht <arch1t3cht@gmail.com>
|
||||
//
|
||||
// Permission to use, copy, modify, and distribute this software for any
|
||||
// purpose with or without fee is hereby granted, provided that the above
|
||||
// copyright notice and this permission notice appear in all copies.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
//
|
||||
// Aegisub Project http://www.aegisub.org/
|
||||
|
||||
#ifdef WITH_VAPOURSYNTH
|
||||
#include "VSScript4.h"
|
||||
|
||||
#include <libaegisub/fs_fwd.h>
|
||||
|
||||
int OpenScriptOrVideo(const VSSCRIPTAPI *api, VSScript *script, agi::fs::path const& filename, std::string default_script);
|
||||
|
||||
#endif // WITH_VAPOURSYNTH
|
|
@ -94,8 +94,6 @@ public:
|
|||
};
|
||||
|
||||
AvisynthVideoProvider::AvisynthVideoProvider(agi::fs::path const& filename, std::string const& colormatrix) try {
|
||||
agi::acs::CheckFileRead(filename);
|
||||
|
||||
std::lock_guard<std::mutex> lock(avs.GetMutex());
|
||||
|
||||
#ifdef _WIN32
|
||||
|
@ -326,6 +324,7 @@ void AvisynthVideoProvider::GetFrame(int n, VideoFrame &out) {
|
|||
|
||||
namespace agi { class BackgroundRunner; }
|
||||
std::unique_ptr<VideoProvider> CreateAvisynthVideoProvider(agi::fs::path const& path, std::string const& colormatrix, agi::BackgroundRunner *) {
|
||||
agi::acs::CheckFileRead(path);
|
||||
return agi::make_unique<AvisynthVideoProvider>(path, colormatrix);
|
||||
}
|
||||
#endif // HAVE_AVISYNTH
|
||||
|
|
|
@ -147,7 +147,7 @@ BSVideoProvider::BSVideoProvider(agi::fs::path const& filename, std::string cons
|
|||
Keyframes.push_back(n);
|
||||
}
|
||||
|
||||
TimecodesVector.push_back((int) frame->GetAVFrame()->pts);
|
||||
TimecodesVector.push_back(frame->Pts * properties.TimeBase.Den / properties.TimeBase.Num);
|
||||
ps->SetProgress(n, properties.NumFrames);
|
||||
}
|
||||
|
||||
|
@ -182,6 +182,14 @@ void BSVideoProvider::GetFrame(int n, VideoFrame &out) {
|
|||
throw VideoDecodeError("Couldn't convert frame!");
|
||||
}
|
||||
|
||||
int range = frame->color_range == AVCOL_RANGE_JPEG;
|
||||
const int *coefficients = sws_getCoefficients(frame->colorspace == AVCOL_SPC_UNSPECIFIED ? AVCOL_SPC_BT709 : frame->colorspace);
|
||||
|
||||
sws_setColorspaceDetails(context,
|
||||
coefficients, range,
|
||||
coefficients, range,
|
||||
0, 1 << 16, 1 << 16);
|
||||
|
||||
out.data.resize(frame->width * frame->height * 4);
|
||||
uint8_t *data[1] = {&out.data[0]};
|
||||
int stride[1] = {frame->width * 4};
|
||||
|
|
|
@ -22,13 +22,13 @@
|
|||
|
||||
#include <libaegisub/access.h>
|
||||
#include <libaegisub/format.h>
|
||||
#include <libaegisub/fs.h>
|
||||
#include <libaegisub/path.h>
|
||||
#include <libaegisub/make_unique.h>
|
||||
|
||||
#include <mutex>
|
||||
|
||||
#include "vapoursynth_wrap.h"
|
||||
#include "vapoursynth_common.h"
|
||||
#include "VSScript4.h"
|
||||
#include "VSHelper4.h"
|
||||
#include "VSConstants4.h"
|
||||
|
@ -105,7 +105,6 @@ void VapoursynthVideoProvider::SetResizeArg(VSMap *args, const VSMap *props, con
|
|||
}
|
||||
|
||||
VapoursynthVideoProvider::VapoursynthVideoProvider(agi::fs::path const& filename, std::string const& colormatrix) try {
|
||||
agi::acs::CheckFileRead(filename);
|
||||
std::lock_guard<std::mutex> lock(vs.GetMutex());
|
||||
|
||||
script = vs.GetScriptAPI()->createScript(nullptr);
|
||||
|
@ -113,7 +112,7 @@ VapoursynthVideoProvider::VapoursynthVideoProvider(agi::fs::path const& filename
|
|||
throw VapoursynthError("Error creating script API");
|
||||
}
|
||||
vs.GetScriptAPI()->evalSetWorkingDir(script, 1);
|
||||
if (vs.GetScriptAPI()->evaluateFile(script, filename.string().c_str())) {
|
||||
if (OpenScriptOrVideo(vs.GetScriptAPI(), script, filename, OPT_GET("Provider/Video/VapourSynth/Default Script")->GetString())) {
|
||||
std::string msg = agi::format("Error executing VapourSynth script: %s", vs.GetScriptAPI()->getError(script));
|
||||
vs.GetScriptAPI()->freeScript(script);
|
||||
throw VapoursynthError(msg);
|
||||
|
@ -277,6 +276,7 @@ VapoursynthVideoProvider::~VapoursynthVideoProvider() {
|
|||
|
||||
namespace agi { class BackgroundRunner; }
|
||||
std::unique_ptr<VideoProvider> CreateVapoursynthVideoProvider(agi::fs::path const& path, std::string const& colormatrix, agi::BackgroundRunner *) {
|
||||
agi::acs::CheckFileRead(path);
|
||||
return agi::make_unique<VapoursynthVideoProvider>(path, colormatrix);
|
||||
}
|
||||
#endif // HAVE_VAPOURSYNTH
|
||||
#endif // WITH_VAPOURSYNTH
|
||||
|
|
|
@ -71,7 +71,7 @@ if (!(Test-Path ffi-experiments)) {
|
|||
# VC++ redistributable
|
||||
if (!(Test-Path VC_redist)) {
|
||||
$redistDir = New-Item -ItemType Directory VC_redist
|
||||
Invoke-WebRequest https://aka.ms/vs/16/release/VC_redist.x64.exe -OutFile "$redistDir\VC_redist.x64.exe" -UseBasicParsing
|
||||
Invoke-WebRequest https://aka.ms/vs/17/release/VC_redist.x64.exe -OutFile "$redistDir\VC_redist.x64.exe" -UseBasicParsing
|
||||
}
|
||||
|
||||
# TODO dictionaries
|
||||
|
|
Loading…
Reference in a new issue