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:
parent
ff43f3d601
commit
febce3ecdc
10 changed files with 121 additions and 5 deletions
|
@ -28,13 +28,13 @@
|
||||||
|
|
||||||
#include <libaegisub/access.h>
|
#include <libaegisub/access.h>
|
||||||
#include <libaegisub/format.h>
|
#include <libaegisub/format.h>
|
||||||
#include <libaegisub/fs.h>
|
|
||||||
#include <libaegisub/path.h>
|
#include <libaegisub/path.h>
|
||||||
#include <libaegisub/make_unique.h>
|
#include <libaegisub/make_unique.h>
|
||||||
|
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
||||||
#include "vapoursynth_wrap.h"
|
#include "vapoursynth_wrap.h"
|
||||||
|
#include "vapoursynth_common.h"
|
||||||
#include "VSScript4.h"
|
#include "VSScript4.h"
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
@ -62,7 +62,7 @@ VapoursynthAudioProvider::VapoursynthAudioProvider(agi::fs::path const& filename
|
||||||
throw VapoursynthError("Error creating script API");
|
throw VapoursynthError("Error creating script API");
|
||||||
}
|
}
|
||||||
vs.GetScriptAPI()->evalSetWorkingDir(script, 1);
|
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));
|
std::string msg = agi::format("Error executing VapourSynth script: %s", vs.GetScriptAPI()->getError(script));
|
||||||
vs.GetScriptAPI()->freeScript(script);
|
vs.GetScriptAPI()->freeScript(script);
|
||||||
throw VapoursynthError(msg);
|
throw VapoursynthError(msg);
|
||||||
|
|
|
@ -336,6 +336,9 @@
|
||||||
"BestSource": {
|
"BestSource": {
|
||||||
"Max Cache Size" : 100,
|
"Max Cache Size" : 100,
|
||||||
"Aegisub Cache" : true
|
"Aegisub Cache" : true
|
||||||
|
},
|
||||||
|
"VapourSynth" : {
|
||||||
|
"Default Script" : "import vapoursynth as vs\nvs.core.bas.Source(source=filename).set_output()"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"Avisynth" : {
|
"Avisynth" : {
|
||||||
|
@ -362,6 +365,9 @@
|
||||||
"Max Cache Size" : 1024,
|
"Max Cache Size" : 1024,
|
||||||
"Threads" : 0,
|
"Threads" : 0,
|
||||||
"Seek Preroll" : 12
|
"Seek Preroll" : 12
|
||||||
|
},
|
||||||
|
"VapourSynth" : {
|
||||||
|
"Default Script" : "import vapoursynth as vs\nvs.core.lsmas.LWLibavSource(source=filename).set_output()"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -336,6 +336,9 @@
|
||||||
"BestSource": {
|
"BestSource": {
|
||||||
"Max Cache Size" : 100,
|
"Max Cache Size" : 100,
|
||||||
"Aegisub Cache" : true
|
"Aegisub Cache" : true
|
||||||
|
},
|
||||||
|
"VapourSynth" : {
|
||||||
|
"Default Script" : "import vapoursynth as vs\nvs.core.bas.Source(source=filename).set_output()"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"Avisynth" : {
|
"Avisynth" : {
|
||||||
|
@ -362,6 +365,9 @@
|
||||||
"Max Cache Size" : 1024,
|
"Max Cache Size" : 1024,
|
||||||
"Threads" : 0,
|
"Threads" : 0,
|
||||||
"Seek Preroll" : 12
|
"Seek Preroll" : 12
|
||||||
|
},
|
||||||
|
"VapourSynth" : {
|
||||||
|
"Default Script" : "import vapoursynth as vs\nvs.core.lsmas.LWLibavSource(source=filename).set_output()"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -240,6 +240,7 @@ opt_src = [
|
||||||
'video_provider_bestsource.cpp',
|
'video_provider_bestsource.cpp',
|
||||||
'bestsource_common.cpp']],
|
'bestsource_common.cpp']],
|
||||||
['VapourSynth', ['vapoursynth_wrap.cpp',
|
['VapourSynth', ['vapoursynth_wrap.cpp',
|
||||||
|
'vapoursynth_common.cpp',
|
||||||
'audio_provider_vs.cpp',
|
'audio_provider_vs.cpp',
|
||||||
'video_provider_vs.cpp']],
|
'video_provider_vs.cpp']],
|
||||||
|
|
||||||
|
|
|
@ -469,6 +469,32 @@ void Advanced_Video(wxTreebook *book, Preferences *parent) {
|
||||||
p->SetSizerAndFit(p->sizer);
|
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
|
/// wxDataViewIconTextRenderer with command name autocompletion
|
||||||
class CommandRenderer final : public wxDataViewCustomRenderer {
|
class CommandRenderer final : public wxDataViewCustomRenderer {
|
||||||
wxArrayString autocomplete;
|
wxArrayString autocomplete;
|
||||||
|
@ -724,6 +750,7 @@ Preferences::Preferences(wxWindow *parent): wxDialog(parent, -1, _("Preferences"
|
||||||
Advanced(book, this);
|
Advanced(book, this);
|
||||||
Advanced_Audio(book, this);
|
Advanced_Audio(book, this);
|
||||||
Advanced_Video(book, this);
|
Advanced_Video(book, this);
|
||||||
|
VapourSynth(book, this);
|
||||||
|
|
||||||
book->Fit();
|
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) {
|
void OptionPage::OptionChoice(wxFlexGridSizer *flex, const wxString &name, const wxArrayString &choices, const char *opt_name) {
|
||||||
parent->AddChangeableOption(opt_name);
|
parent->AddChangeableOption(opt_name);
|
||||||
const auto opt = OPT_GET(opt_name);
|
const auto opt = OPT_GET(opt_name);
|
||||||
|
|
|
@ -43,6 +43,7 @@ public:
|
||||||
|
|
||||||
void CellSkip(wxFlexGridSizer *flex);
|
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 *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 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 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);
|
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
|
|
@ -22,13 +22,13 @@
|
||||||
|
|
||||||
#include <libaegisub/access.h>
|
#include <libaegisub/access.h>
|
||||||
#include <libaegisub/format.h>
|
#include <libaegisub/format.h>
|
||||||
#include <libaegisub/fs.h>
|
|
||||||
#include <libaegisub/path.h>
|
#include <libaegisub/path.h>
|
||||||
#include <libaegisub/make_unique.h>
|
#include <libaegisub/make_unique.h>
|
||||||
|
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
||||||
#include "vapoursynth_wrap.h"
|
#include "vapoursynth_wrap.h"
|
||||||
|
#include "vapoursynth_common.h"
|
||||||
#include "VSScript4.h"
|
#include "VSScript4.h"
|
||||||
#include "VSHelper4.h"
|
#include "VSHelper4.h"
|
||||||
#include "VSConstants4.h"
|
#include "VSConstants4.h"
|
||||||
|
@ -113,7 +113,7 @@ VapoursynthVideoProvider::VapoursynthVideoProvider(agi::fs::path const& filename
|
||||||
throw VapoursynthError("Error creating script API");
|
throw VapoursynthError("Error creating script API");
|
||||||
}
|
}
|
||||||
vs.GetScriptAPI()->evalSetWorkingDir(script, 1);
|
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));
|
std::string msg = agi::format("Error executing VapourSynth script: %s", vs.GetScriptAPI()->getError(script));
|
||||||
vs.GetScriptAPI()->freeScript(script);
|
vs.GetScriptAPI()->freeScript(script);
|
||||||
throw VapoursynthError(msg);
|
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 *) {
|
std::unique_ptr<VideoProvider> CreateVapoursynthVideoProvider(agi::fs::path const& path, std::string const& colormatrix, agi::BackgroundRunner *) {
|
||||||
return agi::make_unique<VapoursynthVideoProvider>(path, colormatrix);
|
return agi::make_unique<VapoursynthVideoProvider>(path, colormatrix);
|
||||||
}
|
}
|
||||||
#endif // HAVE_VAPOURSYNTH
|
#endif // WITH_VAPOURSYNTH
|
||||||
|
|
Loading…
Reference in a new issue