diff --git a/build/Aegisub/Aegisub.vcxproj b/build/Aegisub/Aegisub.vcxproj
index b49eb637f..c27d76d5a 100644
--- a/build/Aegisub/Aegisub.vcxproj
+++ b/build/Aegisub/Aegisub.vcxproj
@@ -117,13 +117,6 @@
-
-
-
-
-
-
-
diff --git a/build/Aegisub/Aegisub.vcxproj.filters b/build/Aegisub/Aegisub.vcxproj.filters
index b65314ee3..74d10b631 100644
--- a/build/Aegisub/Aegisub.vcxproj.filters
+++ b/build/Aegisub/Aegisub.vcxproj.filters
@@ -177,24 +177,6 @@
ASS
-
- Audio\Providers
-
-
- Audio\Providers
-
-
- Audio\Providers
-
-
- Audio\Providers
-
-
- Audio\Providers
-
-
- Audio\Providers
-
Audio\UI
@@ -645,9 +627,6 @@
Main UI\Edit box
-
- Audio\Providers
-
Utilities\UI utilities
diff --git a/src/audio_controller.cpp b/src/audio_controller.cpp
index 5d35a6bca..011a06232 100644
--- a/src/audio_controller.cpp
+++ b/src/audio_controller.cpp
@@ -37,7 +37,6 @@
#include "audio_controller.h"
#include "ass_file.h"
-#include "audio_provider_dummy.h"
#include "audio_timing.h"
#include "compat.h"
#include "include/aegisub/audio_player.h"
diff --git a/src/audio_provider.cpp b/src/audio_provider.cpp
index 6b013c1bf..577917bb5 100644
--- a/src/audio_provider.cpp
+++ b/src/audio_provider.cpp
@@ -34,13 +34,7 @@
#include "config.h"
-#include "audio_provider_avs.h"
-#include "audio_provider_convert.h"
-#include "audio_provider_dummy.h"
-#include "audio_provider_ffmpegsource.h"
-#include "audio_provider_hd.h"
-#include "audio_provider_lock.h"
-#include "audio_provider_ram.h"
+#include "include/aegisub/audio_provider.h"
#include "audio_controller.h"
#include "dialog_progress.h"
@@ -53,9 +47,6 @@
#include
#include
-// Defined in audio_provider_pcm.cpp
-std::unique_ptr CreatePCMAudioProvider(agi::fs::path const& filename);
-
void AudioProvider::GetAudioWithVolume(void *buf, int64_t start, int64_t count, double volume) const {
GetAudio(buf, start, count);
@@ -110,68 +101,96 @@ void AudioProvider::GetAudio(void *buf, int64_t start, int64_t count) const {
}
}
+std::unique_ptr CreateDummyAudioProvider(agi::fs::path const& filename);
+std::unique_ptr CreatePCMAudioProvider(agi::fs::path const& filename);
+std::unique_ptr CreateAvisynthAudioProvider(agi::fs::path const& filename);
+std::unique_ptr CreateFFmpegSourceAudioProvider(agi::fs::path const& filename);
+
+std::unique_ptr CreateConvertAudioProvider(std::unique_ptr source_provider);
+std::unique_ptr CreateLockAudioProvider(std::unique_ptr source_provider);
+std::unique_ptr CreateHDAudioProvider(std::unique_ptr source_provider, agi::BackgroundRunner *br);
+std::unique_ptr CreateRAMAudioProvider(std::unique_ptr source_provider, agi::BackgroundRunner *br);
+
namespace {
-struct provider_creator {
+ using factory_fn = std::unique_ptr (*)(agi::fs::path const&);
+ struct factory {
+ const char *name;
+ factory_fn create;
+ bool hidden;
+ };
+
+ const factory providers[] = {
+ {"Dummy", CreateDummyAudioProvider, true},
+ {"PCM", CreatePCMAudioProvider, true},
+#ifdef WITH_FFMS2
+ {"FFmpegSource", CreateFFmpegSourceAudioProvider, false},
+#endif
+#ifdef WITH_AVISYNTH
+ {"Avisynth", CreateAvisynthAudioProvider, false},
+#endif
+ };
+}
+
+std::vector AudioProviderFactory::GetClasses() {
+ std::vector list;
+ for (auto const& provider : providers) {
+ if (!provider.hidden)
+ list.push_back(provider.name);
+ }
+ return list;
+}
+
+std::unique_ptr AudioProviderFactory::GetProvider(agi::fs::path const& filename) {
+ auto preferred = OPT_GET("Audio/Provider")->GetString();
+ std::vector sorted;
+ auto preferred_insertion_point = sorted.end();
+ for (auto const& provider : providers) {
+ if (provider.hidden)
+ sorted.push_back(&provider);
+ else if (preferred_insertion_point == sorted.end()) {
+ sorted.push_back(&provider);
+ preferred_insertion_point = prev(sorted.end());
+ }
+ else if (preferred == provider.name)
+ sorted.insert(preferred_insertion_point, &provider);
+ else
+ sorted.push_back(&provider);
+ }
+
+ std::unique_ptr provider;
bool found_file = false;
bool found_audio = false;
std::string msg;
- template
- std::unique_ptr try_create(std::string const& name, Factory&& create) {
+ for (auto const& factory : sorted) {
try {
- std::unique_ptr provider = create();
- if (provider)
- LOG_I("audio_provider") << "Using audio provider: " << name;
- return provider;
+ provider = factory->create(filename);
+ if (!provider) continue;
+ LOG_I("audio_provider") << "Using audio provider: " << factory->name;
+ break;
}
catch (agi::fs::FileNotFound const& err) {
LOG_D("audio_provider") << err.GetChainedMessage();
- msg += name + ": " + err.GetMessage() + " not found.\n";
+ msg += std::string(factory->name) + ": " + err.GetMessage() + " not found.\n";
}
catch (agi::AudioDataNotFoundError const& err) {
LOG_D("audio_provider") << err.GetChainedMessage();
found_file = true;
- msg += name + ": " + err.GetChainedMessage() + "\n";
+ msg += std::string(factory->name) + ": " + err.GetChainedMessage() + "\n";
}
catch (agi::AudioOpenError const& err) {
LOG_D("audio_provider") << err.GetChainedMessage();
found_audio = true;
found_file = true;
- msg += name + ": " + err.GetChainedMessage() + "\n";
- }
-
- return nullptr;
- }
-};
-}
-
-std::unique_ptr AudioProviderFactory::GetProvider(agi::fs::path const& filename) {
- provider_creator creator;
- std::unique_ptr provider;
-
- provider = creator.try_create("Dummy audio provider", [&]() {
- return agi::util::make_unique(filename);
- });
-
- // Try a PCM provider first
- if (!provider)
- provider = creator.try_create("PCM audio provider", [&]() { return CreatePCMAudioProvider(filename); });
-
- if (!provider) {
- std::vector list = GetClasses(OPT_GET("Audio/Provider")->GetString());
- if (list.empty()) throw agi::NoAudioProvidersError("No audio providers are available.", nullptr);
-
- for (auto const& name : list) {
- provider = creator.try_create(name, [&]() { return Create(name, filename); });
- if (provider) break;
+ msg += std::string(factory->name) + ": " + err.GetChainedMessage() + "\n";
}
}
if (!provider) {
- if (creator.found_audio)
- throw agi::AudioProviderOpenError(creator.msg, nullptr);
- if (creator.found_file)
- throw agi::AudioDataNotFoundError(creator.msg, nullptr);
+ if (found_audio)
+ throw agi::AudioProviderOpenError(msg, nullptr);
+ if (found_file)
+ throw agi::AudioDataNotFoundError(msg, nullptr);
throw agi::fs::FileNotFound(filename);
}
@@ -184,24 +203,15 @@ std::unique_ptr AudioProviderFactory::GetProvider(agi::fs::path c
// Change provider to RAM/HD cache if needed
int cache = OPT_GET("Audio/Cache/Type")->GetInt();
if (!cache || !needsCache)
- return agi::util::make_unique(std::move(provider));
+ return CreateLockAudioProvider(std::move(provider));
DialogProgress progress(wxGetApp().frame, _("Load audio"));
// Convert to RAM
- if (cache == 1) return agi::util::make_unique(std::move(provider), &progress);
+ if (cache == 1) return CreateRAMAudioProvider(std::move(provider), &progress);
// Convert to HD
- if (cache == 2) return agi::util::make_unique(std::move(provider), &progress);
+ if (cache == 2) return CreateHDAudioProvider(std::move(provider), &progress);
throw agi::AudioCacheOpenError("Unknown caching method", nullptr);
}
-
-void AudioProviderFactory::RegisterProviders() {
-#ifdef WITH_AVISYNTH
- Register("Avisynth");
-#endif
-#ifdef WITH_FFMS2
- Register("FFmpegSource");
-#endif
-}
diff --git a/src/audio_provider_avs.cpp b/src/audio_provider_avs.cpp
index 9dba5c098..a46d6d123 100644
--- a/src/audio_provider_avs.cpp
+++ b/src/audio_provider_avs.cpp
@@ -35,8 +35,10 @@
#include "config.h"
#ifdef WITH_AVISYNTH
-#include "audio_provider_avs.h"
+#include "include/aegisub/audio_provider.h"
+#include "avisynth.h"
+#include "avisynth_wrap.h"
#include "audio_controller.h"
#include "options.h"
#include "utils.h"
@@ -45,9 +47,24 @@
#include
#include
#include
+#include
#include
+namespace {
+class AvisynthAudioProvider final : public AudioProvider {
+ AviSynthWrapper avs_wrapper;
+ PClip clip;
+
+ void LoadFromClip(AVSValue clip);
+ void FillBuffer(void *buf, int64_t start, int64_t count) const;
+
+public:
+ AvisynthAudioProvider(agi::fs::path const& filename);
+
+ bool NeedsCache() const override { return true; }
+};
+
AvisynthAudioProvider::AvisynthAudioProvider(agi::fs::path const& filename) {
this->filename = filename;
@@ -128,4 +145,9 @@ void AvisynthAudioProvider::LoadFromClip(AVSValue clip) {
void AvisynthAudioProvider::FillBuffer(void *buf, int64_t start, int64_t count) const {
clip->GetAudio(buf, start, count, avs_wrapper.GetEnv());
}
+}
+
+std::unique_ptr CreateAvisynthAudioProvider(agi::fs::path const& file) {
+ return agi::util::make_unique(file);
+}
#endif
diff --git a/src/audio_provider_avs.h b/src/audio_provider_avs.h
deleted file mode 100644
index fe4e7c3a2..000000000
--- a/src/audio_provider_avs.h
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright (c) 2005-2006, Rodrigo Braz Monteiro, Fredrik Mellbin
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// * Redistributions of source code must retain the above copyright notice,
-// this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above copyright notice,
-// this list of conditions and the following disclaimer in the documentation
-// and/or other materials provided with the distribution.
-// * Neither the name of the Aegisub Group nor the names of its contributors
-// may be used to endorse or promote products derived from this software
-// without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-// POSSIBILITY OF SUCH DAMAGE.
-//
-// Aegisub Project http://www.aegisub.org/
-
-/// @file audio_provider_avs.h
-/// @see audio_provider_avs.cpp
-/// @ingroup audio_input
-///
-
-#ifdef WITH_AVISYNTH
-#include "include/aegisub/audio_provider.h"
-
-#include "avisynth.h"
-#include "avisynth_wrap.h"
-
-class AvisynthAudioProvider final : public AudioProvider {
- AviSynthWrapper avs_wrapper;
- PClip clip;
-
- void LoadFromClip(AVSValue clip);
- void FillBuffer(void *buf, int64_t start, int64_t count) const;
-
-public:
- AvisynthAudioProvider(agi::fs::path const& filename);
-
- bool NeedsCache() const { return true; }
-};
-#endif
diff --git a/src/audio_provider_convert.cpp b/src/audio_provider_convert.cpp
index 4e2c9b98e..5592db5ce 100644
--- a/src/audio_provider_convert.cpp
+++ b/src/audio_provider_convert.cpp
@@ -21,10 +21,9 @@
#include "config.h"
-#include "audio_provider_convert.h"
+#include "include/aegisub/audio_provider.h"
#include "audio_controller.h"
-#include "include/aegisub/audio_provider.h"
#include
#include
diff --git a/src/audio_provider_convert.h b/src/audio_provider_convert.h
deleted file mode 100644
index a66dc6f5a..000000000
--- a/src/audio_provider_convert.h
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright (c) 2011, Thomas Goyne
-//
-// 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/
-
-/// @file audio_provider_convert.h
-/// @see audio_provider_convert.cpp
-/// @ingroup audio_input
-///
-
-#include
-
-class AudioProvider;
-
-/// Get an audio provider which supplies audio in a format supported by Aegisub's players
-std::unique_ptr CreateConvertAudioProvider(std::unique_ptr source_provider);
diff --git a/src/audio_provider_dummy.cpp b/src/audio_provider_dummy.cpp
index d9f60d6bb..f308ece72 100644
--- a/src/audio_provider_dummy.cpp
+++ b/src/audio_provider_dummy.cpp
@@ -34,10 +34,10 @@
#include "config.h"
-#include "audio_provider_dummy.h"
-#include "utils.h"
+#include "include/aegisub/audio_provider.h"
#include
+#include
#include
@@ -61,25 +61,35 @@
* in every channel even if one would be LFE.
* "ln", length of signal in samples. ln/sr gives signal length in seconds.
*/
-DummyAudioProvider::DummyAudioProvider(agi::fs::path const& uri) {
- if (!boost::starts_with(uri.string(), "dummy-audio:"))
- throw agi::fs::FileNotFound(std::string("Not a dummy audio URI"));
- noise = boost::contains(uri.string(), ":noise?");
- channels = 1;
- sample_rate = 44100;
- bytes_per_sample = 2;
- float_samples = false;
- num_samples = (int64_t)5*30*60*1000 * sample_rate / 1000;
+namespace {
+class DummyAudioProvider final : public AudioProvider {
+ bool noise;
+ void FillBuffer(void *buf, int64_t start, int64_t count) const override {
+ if (noise) {
+ auto workbuf = static_cast(buf);
+ while (count-- > 0)
+ *workbuf++ = (rand() - RAND_MAX/2) * 10000 / RAND_MAX;
+ }
+ else {
+ memset(buf, 0, count * bytes_per_sample);
+ }
+ }
+
+public:
+ DummyAudioProvider(agi::fs::path const& uri) {
+ noise = boost::contains(uri.string(), ":noise?");
+ channels = 1;
+ sample_rate = 44100;
+ bytes_per_sample = 2;
+ float_samples = false;
+ num_samples = (int64_t)5*30*60*1000 * sample_rate / 1000;
+ }
+};
}
-void DummyAudioProvider::FillBuffer(void *buf, int64_t, int64_t count) const {
- if (noise) {
- short *workbuf = (short*)buf;
- while (count-- > 0)
- *workbuf++ = (rand() - RAND_MAX/2) * 10000 / RAND_MAX;
- }
- else {
- memset(buf, 0, count * bytes_per_sample);
- }
+std::unique_ptr CreateDummyAudioProvider(agi::fs::path const& file) {
+ if (!boost::starts_with(file.string(), "dummy-audio:"))
+ return {};
+ return agi::util::make_unique(file);
}
diff --git a/src/audio_provider_dummy.h b/src/audio_provider_dummy.h
deleted file mode 100644
index 196e43ab5..000000000
--- a/src/audio_provider_dummy.h
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright (c) 2006, Niels Martin Hansen
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// * Redistributions of source code must retain the above copyright notice,
-// this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above copyright notice,
-// this list of conditions and the following disclaimer in the documentation
-// and/or other materials provided with the distribution.
-// * Neither the name of the Aegisub Group nor the names of its contributors
-// may be used to endorse or promote products derived from this software
-// without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-// POSSIBILITY OF SUCH DAMAGE.
-//
-// Aegisub Project http://www.aegisub.org/
-
-/// @file audio_provider_dummy.h
-/// @see audio_provider_dummy.cpp
-/// @ingroup audio_input
-///
-
-#include "include/aegisub/audio_provider.h"
-
-class DummyAudioProvider final : public AudioProvider {
- bool noise;
- void FillBuffer(void *buf, int64_t start, int64_t count) const override;
-
-public:
- DummyAudioProvider(agi::fs::path const& uri);
-};
diff --git a/src/audio_provider_ffmpegsource.cpp b/src/audio_provider_ffmpegsource.cpp
index 534d49c84..1cf95f93c 100644
--- a/src/audio_provider_ffmpegsource.cpp
+++ b/src/audio_provider_ffmpegsource.cpp
@@ -35,15 +35,37 @@
#include "config.h"
#ifdef WITH_FFMS2
-#include "audio_provider_ffmpegsource.h"
+#include "include/aegisub/audio_provider.h"
#include "audio_controller.h"
+#include "ffmpegsource_common.h"
#include "options.h"
#include
+#include
#include