Move the logic for which AudioProvider to create out of AudioController

Audio providers should be responsible for determining whether or not
they can open a URI, since it's not really possible for anything else
to. As such move the (lack of) parsing of dummy audio URIs to
DummyAudioProvider, and try to create DummyAudioProviders in
AudioProvider::CreateProvider.
This commit is contained in:
Thomas Goyne 2012-12-22 09:30:47 -08:00
parent a4607ff6be
commit 6e5b53d1a9
4 changed files with 45 additions and 78 deletions

View File

@ -163,78 +163,17 @@ void AudioController::OpenAudio(const wxString &url)
if (!url) if (!url)
throw agi::InternalError("AudioController::OpenAudio() was passed an empty string. This must not happen.", 0); throw agi::InternalError("AudioController::OpenAudio() was passed an empty string. This must not happen.", 0);
wxString path_part;
AudioProvider *new_provider = 0; AudioProvider *new_provider = 0;
try {
if (url.StartsWith("dummy-audio:", &path_part)) new_provider = AudioProviderFactory::GetProvider(url);
{ StandardPaths::SetPathValue("?audio", wxFileName(url).GetPath());
/*
* scheme ::= "dummy-audio" ":" signal-specifier "?" signal-parameters
* signal-specifier ::= "silence" | "noise" | "sine" "/" frequency
* frequency ::= integer
* signal-parameters ::= signal-parameter [ "&" signal-parameters ]
* signal-parameter ::= signal-parameter-name "=" integer
* signal-parameter-name ::= "sr" | "bd" | "ch" | "ln"
*
* Signal types:
* "silence", a silent signal is generated.
* "noise", a white noise signal is generated.
* "sine", a sine wave is generated at the specified frequency.
*
* Signal parameters:
* "sr", sample rate to generate signal at.
* "bd", bit depth to generate signal at (usually 16).
* "ch", number of channels to generate, usually 1 or 2. The same signal is generated
* in every channel even if one would be LFE.
* "ln", length of signal in samples. ln/sr gives signal length in seconds.
*/
new_provider = new DummyAudioProvider(5*30*60*1000, path_part.StartsWith("noise"));
} }
else if (url.StartsWith("video-audio:", &path_part)) catch (agi::UserCancelException const&) {
{ throw;
/*
* scheme ::= "video-audio" ":" stream-type
* stream-type ::= "stream" | "cache"
*
* Stream types:
*
* "stream", the audio is streamed as required directly from the video provider,
* and cannot be used to drive an audio display. Seeking is unreliable.
*
* "cache", the entire audio is cached to memory or disk. Audio displays can be
* driven and seeking is reliable. Opening takes longer because the entire audio
* stream has to be decoded and stored.
*/
} }
else if (url.StartsWith("file:", &path_part)) catch (...) {
{ config::mru->Remove("Audio", STD_STR(url));
/* throw;
* scheme ::= "file" ":" "//" file-system-path
*
* On Unix-like systems, the file system path is regular. On Windows-systems, the
* path uses forward slashes instead of back-slashes and the drive letter is
* preceded by a slash.
*
* URL-encoding??
*/
}
else
{
/*
* Assume it's not a URI but instead a filename in the platform's native format.
*/
try {
new_provider = AudioProviderFactory::GetProvider(url);
StandardPaths::SetPathValue("?audio", wxFileName(url).GetPath());
}
catch (agi::UserCancelException const&) {
throw;
}
catch (...) {
config::mru->Remove("Audio", STD_STR(url));
throw;
}
} }
CloseAudio(); CloseAudio();

View File

@ -39,6 +39,7 @@
#include "audio_provider_avs.h" #include "audio_provider_avs.h"
#include "audio_provider_convert.h" #include "audio_provider_convert.h"
#include "audio_provider_dummy.h"
#include "audio_provider_ffmpegsource.h" #include "audio_provider_ffmpegsource.h"
#include "audio_provider_hd.h" #include "audio_provider_hd.h"
#include "audio_provider_lock.h" #include "audio_provider_lock.h"
@ -146,8 +147,10 @@ AudioProvider *AudioProviderFactory::GetProvider(wxString const& filename) {
provider_creator creator; provider_creator creator;
AudioProvider *provider = nullptr; AudioProvider *provider = nullptr;
provider = creator.try_create("Dummy audio provider", [&]() { return new DummyAudioProvider(filename); });
// Try a PCM provider first // Try a PCM provider first
if (!OPT_GET("Provider/Audio/PCM/Disable")->GetBool()) if (!provider && !OPT_GET("Provider/Audio/PCM/Disable")->GetBool())
provider = creator.try_create("PCM audio provider", [&]() { return CreatePCMAudioProvider(filename); }); provider = creator.try_create("PCM audio provider", [&]() { return CreatePCMAudioProvider(filename); });
if (!provider) { if (!provider) {

View File

@ -37,24 +37,49 @@
#include "audio_provider_dummy.h" #include "audio_provider_dummy.h"
#include "utils.h" #include "utils.h"
DummyAudioProvider::DummyAudioProvider(unsigned long dur_ms, bool _noise) { #include <wx/uri.h>
noise = _noise;
/*
* scheme ::= "dummy-audio" ":" signal-specifier "?" signal-parameters
* signal-specifier ::= "silence" | "noise" | "sine" "/" frequency
* frequency ::= integer
* signal-parameters ::= signal-parameter [ "&" signal-parameters ]
* signal-parameter ::= signal-parameter-name "=" integer
* signal-parameter-name ::= "sr" | "bd" | "ch" | "ln"
*
* Signal types:
* "silence", a silent signal is generated.
* "noise", a white noise signal is generated.
* "sine", a sine wave is generated at the specified frequency.
*
* Signal parameters:
* "sr", sample rate to generate signal at.
* "bd", bit depth to generate signal at (usually 16).
* "ch", number of channels to generate, usually 1 or 2. The same signal is generated
* in every channel even if one would be LFE.
* "ln", length of signal in samples. ln/sr gives signal length in seconds.
*/
DummyAudioProvider::DummyAudioProvider(wxString uri)
{
wxURI parsed(uri);
if (parsed.GetScheme() != "dummy-audio")
throw agi::FileNotFoundError("Not a dummy audio URI");
noise = parsed.GetPath() == "noise";
channels = 1; channels = 1;
sample_rate = 44100; sample_rate = 44100;
bytes_per_sample = 2; bytes_per_sample = 2;
float_samples = false; float_samples = false;
num_samples = (int64_t)dur_ms * sample_rate / 1000; num_samples = (int64_t)5*30*60*1000 * sample_rate / 1000;
} }
void DummyAudioProvider::FillBuffer(void *buf, int64_t, int64_t count) const { void DummyAudioProvider::FillBuffer(void *buf, int64_t, int64_t count) const {
short *workbuf = (short*)buf;
if (noise) { if (noise) {
short *workbuf = (short*)buf;
while (count-- > 0) while (count-- > 0)
*workbuf++ = (rand() - RAND_MAX/2) * 10000 / RAND_MAX; *workbuf++ = (rand() - RAND_MAX/2) * 10000 / RAND_MAX;
} }
else { else {
while (count-- > 0) memset(buf, 0, count * bytes_per_sample);
*workbuf++ = 0;
} }
} }

View File

@ -39,7 +39,7 @@ class DummyAudioProvider : public AudioProvider {
void FillBuffer(void *buf, int64_t start, int64_t count) const; void FillBuffer(void *buf, int64_t start, int64_t count) const;
public: public:
DummyAudioProvider(unsigned long dur_ms, bool _noise); DummyAudioProvider(wxString uri);
bool AreSamplesNativeEndian() const { return true; } bool AreSamplesNativeEndian() const { return true; }
}; };