diff --git a/automation/v4-docs/gui.txt b/automation/v4-docs/gui.txt index f913e7040..83c145535 100644 --- a/automation/v4-docs/gui.txt +++ b/automation/v4-docs/gui.txt @@ -23,7 +23,7 @@ Returns: 1 number --- -function aegisub.get_selection() +function aegisub.gui.get_selection() Returns: 2 values, all numbers. 1. Starting position of the selection. diff --git a/meson.build b/meson.build index 616c86053..7ef4edb52 100644 --- a/meson.build +++ b/meson.build @@ -224,9 +224,9 @@ foreach dep: [ endif endforeach -if host_machine.system() == 'windows' and get_option('avisynth').enabled() +if get_option('avisynth').enabled() conf.set('WITH_AVISYNTH', 1) # bundled separately with installer - deps += cc.find_library('avifil32', required: true) + dep_avail += 'AviSynth' avs_opt = cmake.subproject_options() avs_opt.add_cmake_defines({ @@ -235,6 +235,10 @@ if host_machine.system() == 'windows' and get_option('avisynth').enabled() avs = cmake.subproject('avisynth', options: avs_opt) deps_inc += avs.include_directories('AviSynth-Headers') + + if host_machine.system() == 'windows' + deps += cc.find_library('avifil32', required: true) + endif endif if host_machine.system() == 'windows' and not get_option('directsound').disabled() diff --git a/src/ass_parser.cpp b/src/ass_parser.cpp index e9e3c7899..33e878b71 100644 --- a/src/ass_parser.cpp +++ b/src/ass_parser.cpp @@ -100,7 +100,7 @@ public: try_parse(parsed[2], &collapsed); fold.collapsed = !!collapsed; - if (fold.start > 0 && fold.end > fold.start) { + if (fold.start >= 0 && fold.end > fold.start) { folds.push_back(fold); } } diff --git a/src/audio_provider_avs.cpp b/src/audio_provider_avs.cpp index b94cb4df4..0daa77e8e 100644 --- a/src/audio_provider_avs.cpp +++ b/src/audio_provider_avs.cpp @@ -63,7 +63,7 @@ public: bool NeedsCache() const override { return true; } }; -AvisynthAudioProvider::AvisynthAudioProvider(agi::fs::path const& filename) { +AvisynthAudioProvider::AvisynthAudioProvider(agi::fs::path const& filename) try { agi::acs::CheckFileRead(filename); std::lock_guard lock(avs_wrapper.GetMutex()); @@ -100,6 +100,9 @@ AvisynthAudioProvider::AvisynthAudioProvider(agi::fs::path const& filename) { throw agi::AudioProviderError("Avisynth error: " + errmsg); } } +catch (AvisynthError& err) { + throw agi::AudioProviderError("Avisynth error: " + std::string(err.msg)); +} void AvisynthAudioProvider::LoadFromClip(AVSValue clip) { // Check if it has audio @@ -107,12 +110,15 @@ void AvisynthAudioProvider::LoadFromClip(AVSValue clip) { if (!vi.HasAudio()) throw agi::AudioDataNotFound("No audio found."); IScriptEnvironment *env = avs_wrapper.GetEnv(); + AVSValue script; // Convert to one channel - AVSValue script = env->Invoke(OPT_GET("Audio/Downmixer")->GetString().c_str(), clip); + std::string downmixtype = OPT_GET("Audio/Downmixer")->GetString(); + if (downmixtype == "ConvertToMono" || downmixtype == "GetLeftChannel" || downmixtype == "GetRightChannel") + script = env->Invoke(downmixtype.c_str(), clip); + else + script = clip; - // Convert to 16 bits per sample - script = env->Invoke("ConvertAudioTo16bit", script); vi = script.AsClip()->GetVideoInfo(); // Convert sample rate @@ -132,8 +138,8 @@ void AvisynthAudioProvider::LoadFromClip(AVSValue clip) { channels = vi.AudioChannels(); decoded_samples = num_samples = vi.num_audio_samples; sample_rate = vi.SamplesPerSecond(); - bytes_per_sample = vi.BytesPerAudioSample(); - float_samples = false; + bytes_per_sample = vi.BytesPerChannelSample(); + float_samples = vi.IsSampleType(SAMPLE_FLOAT); this->clip = tempclip; } diff --git a/src/avisynth_wrap.cpp b/src/avisynth_wrap.cpp index fd2246f77..eb957fa3c 100644 --- a/src/avisynth_wrap.cpp +++ b/src/avisynth_wrap.cpp @@ -40,10 +40,24 @@ #include +#ifndef _WIN32 +#include +#endif + +#ifdef _WIN32 +#define AVISYNTH_SO "avisynth.dll" +#else +#define AVISYNTH_SO "libavisynth.so" +#endif + // Allocate storage for and initialise static members namespace { int avs_refcount = 0; +#ifdef _WIN32 HINSTANCE hLib = nullptr; +#else + void* hLib = nullptr; +#endif IScriptEnvironment *env = nullptr; std::mutex AviSynthMutex; } @@ -54,14 +68,26 @@ typedef IScriptEnvironment* __stdcall FUNC(int); AviSynthWrapper::AviSynthWrapper() { if (!avs_refcount++) { - hLib = LoadLibrary(L"avisynth.dll"); +#ifdef _WIN32 +#define CONCATENATE(x, y) x ## y +#define _Lstr(x) CONCATENATE(L, x) + hLib = LoadLibraryW(_Lstr(AVISYNTH_SO)); +#undef _Lstr +#undef CONCATENATE +#else + hLib = dlopen(AVISYNTH_SO, RTLD_LAZY | RTLD_LOCAL | RTLD_DEEPBIND); +#endif if (!hLib) - throw AvisynthError("Could not load avisynth.dll"); + throw AvisynthError("Could not load " AVISYNTH_SO); - FUNC *CreateScriptEnv = (FUNC*)GetProcAddress(hLib, "CreateScriptEnvironment"); +#ifdef _WIN32 + FUNC* CreateScriptEnv = (FUNC*)GetProcAddress(hLib, "CreateScriptEnvironment"); +#else + FUNC* CreateScriptEnv = (FUNC*)dlsym(hLib, "CreateScriptEnvironment"); +#endif if (!CreateScriptEnv) - throw AvisynthError("Failed to get address of CreateScriptEnv from avisynth.dll"); + throw AvisynthError("Failed to get address of CreateScriptEnv from " AVISYNTH_SO); env = CreateScriptEnv(AVISYNTH_INTERFACE_VERSION); @@ -79,9 +105,13 @@ AviSynthWrapper::AviSynthWrapper() { AviSynthWrapper::~AviSynthWrapper() { if (!--avs_refcount) { - delete env; - AVS_linkage = nullptr; + env->DeleteScriptEnvironment(); +#ifdef _WIN32 FreeLibrary(hLib); +#else + dlclose(hLib); +#endif + AVS_linkage = nullptr; } } diff --git a/src/fold_controller.cpp b/src/fold_controller.cpp index 56de5aaf4..ac1cd2084 100644 --- a/src/fold_controller.cpp +++ b/src/fold_controller.cpp @@ -104,7 +104,7 @@ void FoldController::MakeFoldsFromFile() { int numlines = context->ass->Events.size(); for (LineFold fold : context->ass->Properties.folds) { - if (fold.start > 0 && fold.start < fold.end && fold.end <= numlines) { + if (fold.start >= 0 && fold.start < fold.end && fold.end <= numlines) { auto opener = std::next(context->ass->Events.begin(), fold.start); RawAddFold(*opener, *std::next(opener, fold.end - fold.start), fold.collapsed); } diff --git a/src/libresrc/default_config.json b/src/libresrc/default_config.json index 7989b0fb1..fb6ea30b8 100644 --- a/src/libresrc/default_config.json +++ b/src/libresrc/default_config.json @@ -339,7 +339,7 @@ } }, "Avisynth" : { - "Memory Max" : 128 + "Memory Max" : 1024 }, "FFmpegSource" : { "Cache" : { diff --git a/src/libresrc/osx/default_config.json b/src/libresrc/osx/default_config.json index ceee6db4e..05ae560ba 100644 --- a/src/libresrc/osx/default_config.json +++ b/src/libresrc/osx/default_config.json @@ -338,7 +338,7 @@ } }, "Avisynth" : { - "Memory Max" : 128 + "Memory Max" : 1024 }, "FFmpegSource" : { "Cache" : { diff --git a/src/meson.build b/src/meson.build index 5287fb198..8e7e562c7 100644 --- a/src/meson.build +++ b/src/meson.build @@ -174,11 +174,8 @@ if host_machine.system() == 'darwin' ) elif host_machine.system() == 'windows' aegisub_src += files( - 'avisynth_wrap.cpp', 'font_file_lister_gdi.cpp', # 'libass_gdi_fontselect.cpp', - 'audio_provider_avs.cpp', - 'video_provider_avs.cpp', ) if cc.has_header('wingdi.h') @@ -241,6 +238,10 @@ opt_src = [ 'video_provider_ffmpegsource.cpp', 'ffmpegsource_common.cpp']], + ['AviSynth', ['avisynth_wrap.cpp', + 'audio_provider_avs.cpp', + 'video_provider_avs.cpp']], + ['Hunspell', 'spellchecker_hunspell.cpp'], ] diff --git a/src/preferences.cpp b/src/preferences.cpp index 2a212cf69..6b445dc0a 100644 --- a/src/preferences.cpp +++ b/src/preferences.cpp @@ -399,8 +399,8 @@ void Advanced_Audio(wxTreebook *book, Preferences *parent) { #ifdef WITH_AVISYNTH auto avisynth = p->PageSizer("Avisynth"); - const wxString adm_arr[3] = { "ConvertToMono", "GetLeftChannel", "GetRightChannel" }; - wxArrayString adm_choice(3, adm_arr); + const wxString adm_arr[4] = { "None", "ConvertToMono", "GetLeftChannel", "GetRightChannel" }; + wxArrayString adm_choice(4, adm_arr); p->OptionChoice(avisynth, _("Avisynth down-mixer"), adm_choice, "Audio/Downmixer"); p->OptionAdd(avisynth, _("Force sample rate"), "Provider/Audio/AVS/Sample Rate"); #endif diff --git a/src/video_provider_avs.cpp b/src/video_provider_avs.cpp index dabcdaa68..7c779e800 100644 --- a/src/video_provider_avs.cpp +++ b/src/video_provider_avs.cpp @@ -93,7 +93,7 @@ public: bool HasAudio() const override { return has_audio; } }; -AvisynthVideoProvider::AvisynthVideoProvider(agi::fs::path const& filename, std::string const& colormatrix) { +AvisynthVideoProvider::AvisynthVideoProvider(agi::fs::path const& filename, std::string const& colormatrix) try { agi::acs::CheckFileRead(filename); std::lock_guard lock(avs.GetMutex()); @@ -182,6 +182,9 @@ file_exit: throw VideoOpenError("Avisynth error: " + std::string(err.msg)); } } +catch (AvisynthError const& err) { + throw VideoProviderError("Avisynth error: " + std::string(err.msg)); +} void AvisynthVideoProvider::Init(std::string const& colormatrix) { auto script = source_clip;