vapoursynth: Add configurable default script

This default script will be executed to load any file whose file name
extension is not .py or .vpy .

The gui code for setting the default script is still a bit wonky as it
doesn't fit the rest of the preferences pages nicely, but it works for
now.
This commit is contained in:
arch1t3cht 2022-09-27 21:28:38 +02:00
parent ff43f3d601
commit febce3ecdc
10 changed files with 121 additions and 5 deletions

View file

@ -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 {
@ -62,7 +62,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);

View file

@ -336,6 +336,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" : {
@ -362,6 +365,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()"
}
}
},

View file

@ -336,6 +336,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" : {
@ -362,6 +365,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()"
}
}
},

View file

@ -240,6 +240,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']],

View file

@ -469,6 +469,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;
@ -724,6 +750,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();

View file

@ -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);

View file

@ -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);

View 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
View 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

View file

@ -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"
@ -113,7 +113,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);
@ -279,4 +279,4 @@ namespace agi { class BackgroundRunner; }
std::unique_ptr<VideoProvider> CreateVapoursynthVideoProvider(agi::fs::path const& path, std::string const& colormatrix, agi::BackgroundRunner *) {
return agi::make_unique<VapoursynthVideoProvider>(path, colormatrix);
}
#endif // HAVE_VAPOURSYNTH
#endif // WITH_VAPOURSYNTH