diff --git a/aegisub/src/audio_controller.cpp b/aegisub/src/audio_controller.cpp index 2e49dd0c3..8c567100d 100644 --- a/aegisub/src/audio_controller.cpp +++ b/aegisub/src/audio_controller.cpp @@ -292,18 +292,14 @@ void AudioController::OpenAudio(const wxString &url) /* * Assume it's not a URI but instead a filename in the platform's native format. */ - wxFileName fn(url); - if (!fn.FileExists()) - { - config::mru->Remove("Audio", STD_STR(url)); - agi::FileNotFoundError fnf(STD_STR(url)); - throw agi::AudioOpenError( - "Failed opening audio file (parsing as plain filename)", - &fnf); + try { + provider = AudioProviderFactory::GetProvider(url); + StandardPaths::SetPathValue("?audio", wxFileName(url).GetPath()); + } + catch (...) { + config::mru->Remove("Audio", STD_STR(url)); + throw; } - provider = AudioProviderFactory::GetProvider(url); - - StandardPaths::SetPathValue("?audio", fn.GetPath()); } try diff --git a/aegisub/src/audio_controller.h b/aegisub/src/audio_controller.h index 98e8ca758..ba3af635e 100644 --- a/aegisub/src/audio_controller.h +++ b/aegisub/src/audio_controller.h @@ -445,6 +445,27 @@ public: }; namespace agi { - DEFINE_BASE_EXCEPTION(AudioControllerError, Exception) - DEFINE_SIMPLE_EXCEPTION(AudioOpenError, AudioControllerError, "audio_controller/open_failed") + /// Base class for all audio-related errors + DEFINE_BASE_EXCEPTION(AudioError, Exception) + + /// Opening the audio failed for any reason + DEFINE_SIMPLE_EXCEPTION(AudioOpenError, AudioError, "audio/open") + + /// There are no audio providers available to open audio files + DEFINE_SIMPLE_EXCEPTION(NoAudioProvidersError, AudioOpenError, "audio/open/no_providers") + + /// The file exists, but no providers could find any audio tracks in it + DEFINE_SIMPLE_EXCEPTION(AudioDataNotFoundError, AudioOpenError, "audio/open/no_tracks") + + /// There are audio tracks, but no provider could actually read them + DEFINE_SIMPLE_EXCEPTION(AudioProviderOpenError, AudioOpenError, "audio/open/provider") + + /// The audio cache failed to initialize + DEFINE_SIMPLE_EXCEPTION(AudioCacheOpenError, AudioOpenError, "audio/open/cache") + + /// There are no audio players available + DEFINE_SIMPLE_EXCEPTION(NoAudioPlayersError, AudioOpenError, "audio/open/no_players") + + /// The audio player failed to initialize + DEFINE_SIMPLE_EXCEPTION(AudioPlayerOpenError, AudioOpenError, "audio/open/player") } diff --git a/aegisub/src/audio_player.cpp b/aegisub/src/audio_player.cpp index 49634efeb..c7975c8df 100644 --- a/aegisub/src/audio_player.cpp +++ b/aegisub/src/audio_player.cpp @@ -55,6 +55,8 @@ #ifdef WITH_LIBPULSE #include "audio_player_pulse.h" #endif + +#include "audio_controller.h" #include "compat.h" #include "main.h" @@ -70,38 +72,20 @@ AudioPlayer::~AudioPlayer() { CloseStream(); } -/// @brief Ask to stop later -void AudioPlayer::RequestStop() { - wxCommandEvent event(wxEVT_STOP_AUDIO, 1000); - event.SetEventObject(this); - AddPendingEvent(event); // thread safe -} - -DEFINE_EVENT_TYPE(wxEVT_STOP_AUDIO) - -BEGIN_EVENT_TABLE(AudioPlayer, wxEvtHandler) - EVT_COMMAND (1000, wxEVT_STOP_AUDIO, AudioPlayer::OnStopAudio) -END_EVENT_TABLE() - -void AudioPlayer::OnStopAudio(wxCommandEvent &) { - Stop(false); -} - AudioPlayer* AudioPlayerFactory::GetAudioPlayer() { std::vector list = GetClasses(OPT_GET("Audio/Player")->GetString()); - if (list.empty()) throw "No audio players are available."; + if (list.empty()) throw agi::NoAudioPlayersError("No audio players are available.", 0); - wxString error; - for (unsigned int i=0;i #include "audio_player_alsa.h" + +#include "audio_controller.h" #include "include/aegisub/audio_provider.h" #include "compat.h" #include "frame_main.h" @@ -365,7 +367,7 @@ void AlsaPlayer::OpenStream() } else { - throw 1; // FIXME + throw agi::AudioPlayerOpenError("AlsaPlayer: Creating the playback thread failed", 0); } } diff --git a/aegisub/src/audio_player_alsa.h b/aegisub/src/audio_player_alsa.h index 167ec9746..8de886cc8 100644 --- a/aegisub/src/audio_player_alsa.h +++ b/aegisub/src/audio_player_alsa.h @@ -71,4 +71,3 @@ public: }; #endif - diff --git a/aegisub/src/audio_player_dsound.cpp b/aegisub/src/audio_player_dsound.cpp index f6bf33b00..aa67765e0 100644 --- a/aegisub/src/audio_player_dsound.cpp +++ b/aegisub/src/audio_player_dsound.cpp @@ -40,6 +40,7 @@ #include +#include "audio_controller.h" #include "audio_player_dsound.h" #include "frame_main.h" #include "main.h" @@ -75,7 +76,7 @@ void DirectSoundPlayer::OpenStream() { // Initialize the DirectSound object HRESULT res; res = DirectSoundCreate8(&DSDEVID_DefaultPlayback,&directSound,NULL); // TODO: support selecting audio device - if (FAILED(res)) throw "Failed initializing DirectSound"; + if (FAILED(res)) throw agi::AudioPlayerOpenError("Failed initializing DirectSound", 0); // Set DirectSound parameters directSound->SetCooperativeLevel((HWND)wxGetApp().frame->GetHandle(),DSSCL_PRIORITY); @@ -106,11 +107,11 @@ void DirectSoundPlayer::OpenStream() { // Create the buffer IDirectSoundBuffer *buf; res = directSound->CreateSoundBuffer(&desc,&buf,NULL); - if (res != DS_OK) throw "Failed creating DirectSound buffer"; + if (res != DS_OK) throw agi::AudioPlayerOpenError("Failed creating DirectSound buffer", 0); // Copy interface to buffer res = buf->QueryInterface(IID_IDirectSoundBuffer8,(LPVOID*) &buffer); - if (res != S_OK) throw "Failed casting interface to IDirectSoundBuffer8"; + if (res != S_OK) throw agi::AudioPlayerOpenError("Failed casting interface to IDirectSoundBuffer8", 0); // Set data offset = 0; diff --git a/aegisub/src/audio_player_dsound2.cpp b/aegisub/src/audio_player_dsound2.cpp index 2ee4014a4..970a68d36 100644 --- a/aegisub/src/audio_player_dsound2.cpp +++ b/aegisub/src/audio_player_dsound2.cpp @@ -48,6 +48,7 @@ #include "audio_player_dsound2.h" +#include "audio_controller.h" #include "include/aegisub/audio_provider.h" #include "frame_main.h" #include "main.h" @@ -669,7 +670,7 @@ DirectSoundPlayer2Thread::DirectSoundPlayer2Thread(AudioProvider *provider, int thread_handle.handle = (HANDLE)_beginthreadex(0, 0, ThreadProc, this, 0, 0); if (!thread_handle) - throw "Failed creating playback thread in DirectSoundPlayer2. This is bad."; + throw agi::AudioPlayerOpenError("Failed creating playback thread in DirectSoundPlayer2. This is bad.", 0); HANDLE running_or_error[] = { thread_running, error_happened }; switch (WaitForMultipleObjects(2, running_or_error, FALSE, INFINITE)) @@ -680,10 +681,10 @@ DirectSoundPlayer2Thread::DirectSoundPlayer2Thread(AudioProvider *provider, int case WAIT_OBJECT_0 + 1: // error happened, we fail - throw error_message; + throw agi::AudioPlayerOpenError(error_message, 0); default: - throw "Failed wait for thread start or thread error in DirectSoundPlayer2. This is bad."; + throw agi::AudioPlayerOpenError("Failed wait for thread start or thread error in DirectSoundPlayer2. This is bad.", 0); } } @@ -714,7 +715,7 @@ void DirectSoundPlayer2Thread::Play(int64_t start, int64_t count) case WAIT_OBJECT_0+1: // Error throw error_message; default: - throw "Unexpected result from WaitForMultipleObjects in DirectSoundPlayer2Thread::Play"; + throw agi::InternalError("Unexpected result from WaitForMultipleObjects in DirectSoundPlayer2Thread::Play", 0); } } diff --git a/aegisub/src/audio_player_openal.cpp b/aegisub/src/audio_player_openal.cpp index 99f222ece..6b6660d9e 100644 --- a/aegisub/src/audio_player_openal.cpp +++ b/aegisub/src/audio_player_openal.cpp @@ -42,6 +42,7 @@ #include "audio_player_openal.h" +#include "audio_controller.h" #include "utils.h" // Auto-link to OpenAL lib for MSVC @@ -49,6 +50,8 @@ #pragma comment(lib, "openal32.lib") #endif +DEFINE_SIMPLE_EXCEPTION(OpenALException, agi::AudioPlayerOpenError, "audio/open/player/openal") + OpenALPlayer::OpenALPlayer() : open(false) , playing(false) @@ -76,25 +79,25 @@ void OpenALPlayer::OpenStream() try { // Open device device = alcOpenDevice(0); - if (!device) throw OpenALException("Failed opening default OpenAL device"); + if (!device) throw OpenALException("Failed opening default OpenAL device", 0); // Create context context = alcCreateContext(device, 0); - if (!context) throw OpenALException("Failed creating OpenAL context"); - if (!alcMakeContextCurrent(context)) throw OpenALException("Failed selecting OpenAL context"); + if (!context) throw OpenALException("Failed creating OpenAL context", 0); + if (!alcMakeContextCurrent(context)) throw OpenALException("Failed selecting OpenAL context", 0); // Clear error code alGetError(); // Generate buffers alGenBuffers(num_buffers, buffers); - if (alGetError() != AL_NO_ERROR) throw OpenALException("Error generating OpenAL buffers"); + if (alGetError() != AL_NO_ERROR) throw OpenALException("Error generating OpenAL buffers", 0); // Generate source alGenSources(1, &source); if (alGetError() != AL_NO_ERROR) { alDeleteBuffers(num_buffers, buffers); - throw OpenALException("Error generating OpenAL source"); + throw OpenALException("Error generating OpenAL source", 0); } } catch (...) diff --git a/aegisub/src/audio_player_openal.h b/aegisub/src/audio_player_openal.h index 07b054552..daa5c5574 100644 --- a/aegisub/src/audio_player_openal.h +++ b/aegisub/src/audio_player_openal.h @@ -53,10 +53,6 @@ #include #endif -#include - -DEFINE_SIMPLE_EXCEPTION_NOINNER(OpenALException, agi::Exception, "audio/player/openal/generic") - /// DOCME /// @class OpenALPlayer /// @brief DOCME diff --git a/aegisub/src/audio_player_oss.cpp b/aegisub/src/audio_player_oss.cpp index c2f6e59d2..e02b7fd60 100644 --- a/aegisub/src/audio_player_oss.cpp +++ b/aegisub/src/audio_player_oss.cpp @@ -43,11 +43,16 @@ #include #include "audio_player_oss.h" -#include "frame_main.h" + +#include "audio_controller.h" #include "compat.h" +#include "include/aegisub/audio_provider.h" #include "main.h" #include "utils.h" +DEFINE_SIMPLE_EXCEPTION(OSSError, agi::AudioPlayerOpenError, "audio/player/open/oss") + + /// @brief Constructor /// OSSPlayer::OSSPlayer() @@ -81,7 +86,7 @@ void OSSPlayer::OpenStream() wxString device = lagi_wxString(OPT_GET("Audio/OSS/Device")->GetString()); dspdev = ::open(device.mb_str(wxConvUTF8), O_WRONLY, 0); if (dspdev < 0) { - throw OSSError("OSS player: opening device failed"); + throw OSSError("OSS player: opening device failed", 0); } // Use a reasonable buffer policy for low latency (OSS4) @@ -93,7 +98,7 @@ void OSSPlayer::OpenStream() // Set number of channels int channels = provider->GetChannels(); if (ioctl(dspdev, SNDCTL_DSP_CHANNELS, &channels) < 0) { - throw OSSError("OSS player: setting channels failed"); + throw OSSError("OSS player: setting channels failed", 0); } // Set sample format @@ -106,17 +111,17 @@ void OSSPlayer::OpenStream() sample_format = AFMT_S16_LE; break; default: - throw OSSError("OSS player: can only handle 8 and 16 bit sound"); + throw OSSError("OSS player: can only handle 8 and 16 bit sound", 0); } if (ioctl(dspdev, SNDCTL_DSP_SETFMT, &sample_format) < 0) { - throw OSSError("OSS player: setting sample format failed"); + throw OSSError("OSS player: setting sample format failed", 0); } // Set sample rate rate = provider->GetSampleRate(); if (ioctl(dspdev, SNDCTL_DSP_SPEED, &rate) < 0) { - throw OSSError("OSS player: setting samplerate failed"); + throw OSSError("OSS player: setting samplerate failed", 0); } // Now ready diff --git a/aegisub/src/audio_player_oss.h b/aegisub/src/audio_player_oss.h index 8217232cb..6d54de3ee 100644 --- a/aegisub/src/audio_player_oss.h +++ b/aegisub/src/audio_player_oss.h @@ -49,12 +49,8 @@ #endif #include "include/aegisub/audio_player.h" -#include "include/aegisub/audio_provider.h" - -#include - -DEFINE_SIMPLE_EXCEPTION_NOINNER(OSSError, agi::Exception, "audio/player/oss") +class AudioProvider; class OSSPlayer; /// DOCME diff --git a/aegisub/src/audio_player_portaudio.cpp b/aegisub/src/audio_player_portaudio.cpp index 4ce66e736..910b55ec8 100644 --- a/aegisub/src/audio_player_portaudio.cpp +++ b/aegisub/src/audio_player_portaudio.cpp @@ -42,11 +42,15 @@ #include #include "audio_player_portaudio.h" -#include "charset_conv.h" + +#include "audio_controller.h" +#include "compat.h" #include "include/aegisub/audio_provider.h" #include "main.h" #include "utils.h" +DEFINE_SIMPLE_EXCEPTION(PortAudioError, agi::AudioPlayerOpenError, "audio/player/open/portaudio") + // Uncomment to enable extremely spammy debug logging //#define PORTAUDIO_DEBUG @@ -54,7 +58,7 @@ PortAudioPlayer::PortAudioPlayer() { PaError err = Pa_Initialize(); if (err != paNoError) - throw PortAudioError(std::string("Failed opening PortAudio:") + Pa_GetErrorText(err)); + throw PortAudioError(std::string("Failed opening PortAudio:") + Pa_GetErrorText(err), 0); volume = 1.0f; pa_start = 0.0; @@ -109,7 +113,7 @@ void PortAudioPlayer::OpenStream() { const PaHostErrorInfo *pa_err = Pa_GetLastHostErrorInfo(); LOG_D_IF(pa_err->errorCode != 0, "audio/player/portaudio") << "HostError: API: " << pa_err->hostApiType << ", " << pa_err->errorText << ", " << pa_err->errorCode; LOG_D("audio/player/portaudio") << "Failed initializing PortAudio stream with error: " << Pa_GetErrorText(err); - throw PortAudioError("Failed initializing PortAudio stream with error: " + std::string(Pa_GetErrorText(err))); + throw PortAudioError("Failed initializing PortAudio stream with error: " + std::string(Pa_GetErrorText(err)), 0); } } diff --git a/aegisub/src/audio_player_portaudio.h b/aegisub/src/audio_player_portaudio.h index 7bac865ec..cd96d97c9 100644 --- a/aegisub/src/audio_player_portaudio.h +++ b/aegisub/src/audio_player_portaudio.h @@ -37,15 +37,15 @@ #ifdef WITH_PORTAUDIO #include "include/aegisub/audio_player.h" -#include "include/aegisub/audio_provider.h" - -#include extern "C" { #include } -DEFINE_SIMPLE_EXCEPTION_NOINNER(PortAudioError, agi::Exception, "audio/player/portaudio") +#ifndef AGI_PRE +#include +#include +#endif /// @class PortAudioPlayer /// @brief PortAudio Player diff --git a/aegisub/src/audio_player_pulse.cpp b/aegisub/src/audio_player_pulse.cpp index 4ee58e7cd..ad8f491be 100644 --- a/aegisub/src/audio_player_pulse.cpp +++ b/aegisub/src/audio_player_pulse.cpp @@ -43,11 +43,11 @@ #endif #include "audio_player_pulse.h" + +#include "audio_controller.h" +#include "include/aegisub/audio_provider.h" #include "utils.h" - -/// @brief Constructor -/// PulseAudioPlayer::PulseAudioPlayer() : context_notify(0, 1) , context_success(0, 1) @@ -60,32 +60,20 @@ PulseAudioPlayer::PulseAudioPlayer() is_playing = false; } - - -/// @brief Destructor -/// PulseAudioPlayer::~PulseAudioPlayer() { - if (open) CloseStream(); + CloseStream(); } - - -/// @brief Open stream -/// void PulseAudioPlayer::OpenStream() { - //printf("Opening PulseAudio stream\n"); if (open) CloseStream(); - // Get provider - AudioProvider *provider = GetProvider(); - // Initialise a mainloop //printf("Initialising threaded main loop\n"); mainloop = pa_threaded_mainloop_new(); if (!mainloop) { - throw "Failed to initialise PulseAudio threaded mainloop object"; + throw agi::AudioPlayerOpenError("Failed to initialise PulseAudio threaded mainloop object", 0); } //printf("Starting main loop\n"); pa_threaded_mainloop_start(mainloop); @@ -95,7 +83,7 @@ void PulseAudioPlayer::OpenStream() context = pa_context_new(pa_threaded_mainloop_get_api(mainloop), "Aegisub"); if (!context) { pa_threaded_mainloop_free(mainloop); - throw "Failed to create PulseAudio context"; + throw agi::AudioPlayerOpenError("Failed to create PulseAudio context", 0); } pa_context_set_state_callback(context, (pa_context_notify_cb_t)pa_context_notify, this); @@ -113,9 +101,7 @@ void PulseAudioPlayer::OpenStream() pa_context_unref(context); pa_threaded_mainloop_stop(mainloop); pa_threaded_mainloop_free(mainloop); - wxString s(pa_strerror(paerror), wxConvUTF8); - s.Prepend("PulseAudio reported error: "); - throw s.c_str(); + throw agi::AudioPlayerOpenError(std::string("PulseAudio reported error: ") + pa_strerror(paerror), 0); } // otherwise loop once more } @@ -137,7 +123,7 @@ void PulseAudioPlayer::OpenStream() pa_context_unref(context); pa_threaded_mainloop_stop(mainloop); pa_threaded_mainloop_free(mainloop); - throw "PulseAudio could not create stream"; + throw agi::AudioPlayerOpenError("PulseAudio could not create stream", 0); } pa_stream_set_state_callback(stream, (pa_stream_notify_cb_t)pa_stream_notify, this); pa_stream_set_write_callback(stream, (pa_stream_request_cb_t)pa_stream_write, this); @@ -147,9 +133,7 @@ void PulseAudioPlayer::OpenStream() paerror = pa_stream_connect_playback(stream, NULL, NULL, (pa_stream_flags_t)(PA_STREAM_INTERPOLATE_TIMING|PA_STREAM_NOT_MONOTONOUS|PA_STREAM_AUTO_TIMING_UPDATE), NULL, NULL); if (paerror) { printf("PulseAudio reported error: %s (%d)\n", pa_strerror(paerror), paerror); - wxString s(pa_strerror(paerror), wxConvUTF8); - s.Prepend("PulseAudio reported error: "); - throw s.c_str(); + throw agi::AudioPlayerOpenError(std::string("PulseAudio reported error: ") + pa_strerror(paerror), 0); } while (true) { stream_notify.Wait(); @@ -158,7 +142,7 @@ void PulseAudioPlayer::OpenStream() } else if (sstate == PA_STREAM_FAILED) { paerror = pa_context_errno(context); printf("PulseAudio player: Stream connection failed: %s (%d)\n", pa_strerror(paerror), paerror); - throw "PulseAudio player: Something went wrong connecting the stream"; + throw agi::AudioPlayerOpenError("PulseAudio player: Something went wrong connecting the stream", 0); } } //printf("Connected playback stream, now playing\n\n"); @@ -168,11 +152,6 @@ void PulseAudioPlayer::OpenStream() open = true; } - - -/// @brief Close stream -/// @return -/// void PulseAudioPlayer::CloseStream() { if (!open) return; @@ -192,12 +171,6 @@ void PulseAudioPlayer::CloseStream() open = false; } - - -/// @brief Play -/// @param start -/// @param count -/// void PulseAudioPlayer::Play(int64_t start,int64_t count) { //printf("Starting PulseAudio playback\n"); @@ -249,12 +222,6 @@ void PulseAudioPlayer::Play(int64_t start,int64_t count) if (displayTimer && !displayTimer->IsRunning()) displayTimer->Start(15); } - - -/// @brief Stop -/// @param timerToo -/// @return -/// void PulseAudioPlayer::Stop(bool timerToo) { if (!is_playing) return; @@ -286,61 +253,31 @@ void PulseAudioPlayer::Stop(bool timerToo) } } - - -/// @brief DOCME -/// @return -/// bool PulseAudioPlayer::IsPlaying() { return is_playing; } - - -/// @brief Set end -/// @param pos -/// void PulseAudioPlayer::SetEndPosition(int64_t pos) { end_frame = pos; } - - -/// @brief Set current position -/// @param pos -/// void PulseAudioPlayer::SetCurrentPosition(int64_t pos) { cur_frame = pos; } - - -/// @brief DOCME -/// @return -/// int64_t PulseAudioPlayer::GetStartPosition() { return start_frame; } - - -/// @brief DOCME -/// @return -/// int64_t PulseAudioPlayer::GetEndPosition() { return end_frame; } - - -/// @brief Get current position -/// @return -/// int64_t PulseAudioPlayer::GetCurrentPosition() { if (!is_playing) return 0; @@ -356,52 +293,28 @@ int64_t PulseAudioPlayer::GetCurrentPosition() return start_frame + playtime * provider->GetSampleRate() / (1000*1000); } - - /// @brief Called by PA to notify about contetxt operation completion -/// @param c -/// @param success -/// @param thread -/// void PulseAudioPlayer::pa_context_success(pa_context *c, int success, PulseAudioPlayer *thread) { thread->context_success_val = success; thread->context_success.Post(); } - - /// @brief Called by PA to notify about other context-related stuff -/// @param c -/// @param thread -/// void PulseAudioPlayer::pa_context_notify(pa_context *c, PulseAudioPlayer *thread) { thread->cstate = pa_context_get_state(thread->context); thread->context_notify.Post(); } - - /// @brief Called by PA when an operation completes -/// @param p -/// @param success -/// @param thread -/// void PulseAudioPlayer::pa_stream_success(pa_stream *p, int success, PulseAudioPlayer *thread) { thread->stream_success_val = success; thread->stream_success.Post(); } - - /// @brief Called by PA to request more data (and other things?) -/// @param p -/// @param length -/// @param thread -/// @return -/// void PulseAudioPlayer::pa_stream_write(pa_stream *p, size_t length, PulseAudioPlayer *thread) { if (!thread->is_playing) return; @@ -434,12 +347,7 @@ void PulseAudioPlayer::pa_stream_write(pa_stream *p, size_t length, PulseAudioPl thread->cur_frame += frames; } - - /// @brief Called by PA to notify about other stuff -/// @param p -/// @param thread -/// void PulseAudioPlayer::pa_stream_notify(pa_stream *p, PulseAudioPlayer *thread) { thread->sstate = pa_stream_get_state(thread->stream); diff --git a/aegisub/src/audio_player_pulse.h b/aegisub/src/audio_player_pulse.h index 2d26df865..440e99ad1 100644 --- a/aegisub/src/audio_player_pulse.h +++ b/aegisub/src/audio_player_pulse.h @@ -38,7 +38,6 @@ #include #include "include/aegisub/audio_player.h" -#include "include/aegisub/audio_provider.h" class PulseAudioPlayer; @@ -141,16 +140,7 @@ public: void SetEndPosition(int64_t pos); void SetCurrentPosition(int64_t pos); - - /// @brief DOCME - /// @param vol - /// @return - /// void SetVolume(double vol) { volume = vol; } - - /// @brief DOCME - /// @return - /// double GetVolume() { return volume; } }; diff --git a/aegisub/src/audio_provider.cpp b/aegisub/src/audio_provider.cpp index 0d8ce5518..4905b7ba1 100644 --- a/aegisub/src/audio_provider.cpp +++ b/aegisub/src/audio_provider.cpp @@ -41,6 +41,7 @@ #include #endif +#include "audio_controller.h" #ifdef WITH_AVISYNTH #include "audio_provider_avs.h" #endif @@ -56,13 +57,6 @@ #include "frame_main.h" #include "main.h" -/// @brief Get audio with volume -/// @param buf -/// @param start -/// @param count -/// @param volume -/// @return -/// void AudioProvider::GetAudioWithVolume(void *buf, int64_t start, int64_t count, double volume) const { try { GetAudio(buf,start,count); @@ -92,8 +86,9 @@ void AudioProvider::GetAudioWithVolume(void *buf, int64_t start, int64_t count, } AudioProvider *AudioProviderFactory::GetProvider(wxString const& filename, int cache) { - AudioProvider *provider = NULL; - bool found = false; + AudioProvider *provider = 0; + bool found_file = false; + bool found_audio = false; std::string msg; if (!OPT_GET("Provider/Audio/PCM/Disable")->GetBool()) { @@ -104,16 +99,16 @@ AudioProvider *AudioProviderFactory::GetProvider(wxString const& filename, int c catch (agi::FileNotFoundError const& err) { msg = "PCM audio provider: " + err.GetMessage() + " not found.\n"; } - catch (AudioOpenError const& err) { - found = true; - msg += err.GetMessage() + "\n"; + catch (agi::AudioOpenError const& err) { + found_file = true; + msg += err.GetChainedMessage() + "\n"; } } if (!provider) { std::vector list = GetClasses(OPT_GET("Audio/Provider")->GetString()); - if (list.empty()) throw AudioOpenError("No audio providers are available."); + if (list.empty()) throw agi::NoAudioProvidersError("No audio providers are available.", 0); - for (unsigned int i=0;iNeedsCache(); // Give it a converter if needed @@ -155,7 +155,7 @@ AudioProvider *AudioProviderFactory::GetProvider(wxString const& filename, int c // Convert to HD if (cache == 2) return new HDAudioProvider(provider, &progress); - throw AudioOpenError("Unknown caching method"); + throw agi::AudioCacheOpenError("Unknown caching method", 0); } /// @brief Register all providers diff --git a/aegisub/src/audio_provider_avs.cpp b/aegisub/src/audio_provider_avs.cpp index fd12b5f7d..cbe206cc4 100644 --- a/aegisub/src/audio_provider_avs.cpp +++ b/aegisub/src/audio_provider_avs.cpp @@ -46,6 +46,8 @@ #endif #include "audio_provider_avs.h" + +#include "audio_controller.h" #include "charset_conv.h" #include "compat.h" #include "main.h" @@ -55,56 +57,64 @@ /// @brief Constructor /// @param _filename /// -AvisynthAudioProvider::AvisynthAudioProvider(wxString filename) try : filename(filename) { - AVSValue script; - wxMutexLocker lock(AviSynthMutex); +AvisynthAudioProvider::AvisynthAudioProvider(wxString filename) +: filename(filename) +{ + try { + AVSValue script; + wxMutexLocker lock(AviSynthMutex); - wxFileName fn(filename); - if (!fn.FileExists()) - throw agi::FileNotFoundError(STD_STR(filename)); + wxFileName fn(filename); + if (!fn.FileExists()) + throw agi::FileNotFoundError(STD_STR(filename)); - // Include - if (filename.EndsWith(".avs")) { - char *fname = env->SaveString(fn.GetShortPath().mb_str(csConvLocal)); - script = env->Invoke("Import", fname); - } - - // Use DirectShowSource - else { - const char * argnames[3] = { 0, "video", "audio" }; - AVSValue args[3] = { env->SaveString(fn.GetShortPath().mb_str(csConvLocal)), false, true }; - - // Load DirectShowSource.dll from app dir if it exists - wxFileName dsspath(StandardPaths::DecodePath("?data/DirectShowSource.dll")); - if (dsspath.FileExists()) { - env->Invoke("LoadPlugin",env->SaveString(dsspath.GetShortPath().mb_str(csConvLocal))); + // Include + if (filename.EndsWith(".avs")) { + char *fname = env->SaveString(fn.GetShortPath().mb_str(csConvLocal)); + script = env->Invoke("Import", fname); } - // Load audio with DSS if it exists - if (env->FunctionExists("DirectShowSource")) { - script = env->Invoke("DirectShowSource", AVSValue(args,3),argnames); - } - // Otherwise fail + // Use DirectShowSource else { - throw AudioOpenError("No suitable audio source filter found. Try placing DirectShowSource.dll in the Aegisub application directory."); - } - } + const char * argnames[3] = { 0, "video", "audio" }; + AVSValue args[3] = { env->SaveString(fn.GetShortPath().mb_str(csConvLocal)), false, true }; - LoadFromClip(script); -} -catch (AvisynthError &err) { - throw AudioOpenError("Avisynth error: " + std::string(err.msg)); + // Load DirectShowSource.dll from app dir if it exists + wxFileName dsspath(StandardPaths::DecodePath("?data/DirectShowSource.dll")); + if (dsspath.FileExists()) { + env->Invoke("LoadPlugin",env->SaveString(dsspath.GetShortPath().mb_str(csConvLocal))); + } + + // Load audio with DSS if it exists + if (env->FunctionExists("DirectShowSource")) { + script = env->Invoke("DirectShowSource", AVSValue(args,3),argnames); + } + // Otherwise fail + else { + throw agi::AudioProviderOpenError("No suitable audio source filter found. Try placing DirectShowSource.dll in the Aegisub application directory.", 0); + } + } + + LoadFromClip(script); + } + catch (AvisynthError &err) { + std::string errmsg(err.msg); + if (errmsg.find("filter graph manager won't talk to me") != errmsg.npos) + throw agi::AudioDataNotFoundError("Avisynth error: " + errmsg, 0); + else + throw agi::AudioProviderOpenError("Avisynth error: " + errmsg, 0); + } } /// @brief Read from environment /// @param _clip /// -void AvisynthAudioProvider::LoadFromClip(AVSValue _clip) { +void AvisynthAudioProvider::LoadFromClip(AVSValue _clip) { AVSValue script; // Check if it has audio VideoInfo vi = _clip.AsClip()->GetVideoInfo(); - if (!vi.HasAudio()) throw AudioOpenError("No audio found."); + if (!vi.HasAudio()) throw agi::AudioDataNotFoundError("No audio found.", 0); // Convert to one channel char buffer[1024]; diff --git a/aegisub/src/audio_provider_convert.cpp b/aegisub/src/audio_provider_convert.cpp index 010165b86..9b6a5fd58 100644 --- a/aegisub/src/audio_provider_convert.cpp +++ b/aegisub/src/audio_provider_convert.cpp @@ -26,6 +26,7 @@ #include "audio_provider_convert.h" #include "aegisub_endian.h" +#include "audio_controller.h" #include "include/aegisub/audio_provider.h" #include @@ -54,7 +55,7 @@ class BitdepthConvertAudioProvider : public AudioProviderConverter { public: BitdepthConvertAudioProvider(AudioProvider *src) : AudioProviderConverter(src) { if (bytes_per_sample > 8) - throw AudioOpenError("Audio format converter: audio with bitdepths greater than 64 bits/sample is currently unsupported"); + throw agi::AudioProviderOpenError("Audio format converter: audio with bitdepths greater than 64 bits/sample is currently unsupported", 0); src_is_native_endian = src->AreSamplesNativeEndian(); src_bytes_per_sample = bytes_per_sample; diff --git a/aegisub/src/audio_provider_ffmpegsource.cpp b/aegisub/src/audio_provider_ffmpegsource.cpp index c167ee706..90d3caa93 100644 --- a/aegisub/src/audio_provider_ffmpegsource.cpp +++ b/aegisub/src/audio_provider_ffmpegsource.cpp @@ -47,10 +47,11 @@ #endif #include "audio_provider_ffmpegsource.h" + +#include "audio_controller.h" #include "compat.h" #include "main.h" - /// @brief Constructor /// @param filename /// @@ -64,7 +65,7 @@ FFmpegSourceAudioProvider::FFmpegSourceAudioProvider(wxString filename) if (SUCCEEDED(res)) COMInited = true; else if (res != RPC_E_CHANGED_MODE) - throw AudioOpenError("COM initialization failure"); + throw agi::AudioProviderOpenError("COM initialization failure", 0); #endif // initialize ffmpegsource // FIXME: CPU detection? @@ -101,7 +102,7 @@ void FFmpegSourceAudioProvider::LoadAudio(wxString filename) { std::map TrackList = GetTracksOfType(Indexer, FFMS_TYPE_AUDIO); if (TrackList.size() <= 0) - throw AudioOpenError("no audio tracks found"); + throw agi::AudioDataNotFoundError("no audio tracks found", 0); // initialize the track number to an invalid value so we can detect later on // whether the user actually had to choose a track or not @@ -110,7 +111,7 @@ void FFmpegSourceAudioProvider::LoadAudio(wxString filename) { TrackNumber = AskForTrackSelection(TrackList, FFMS_TYPE_AUDIO); // if it's still -1 here, user pressed cancel if (TrackNumber == -1) - throw agi::UserCancelException("audio loading cancelled by user"); + throw agi::UserCancelException("audio loading canceled by user"); } // generate a name for the cache file @@ -137,7 +138,7 @@ void FFmpegSourceAudioProvider::LoadAudio(wxString filename) { if (TrackNumber < 0) { FFMS_DestroyIndex(Index); Index = NULL; - throw AudioOpenError(std::string("Couldn't find any audio tracks: ") + ErrInfo.Buffer); + throw agi::AudioDataNotFoundError(std::string("Couldn't find any audio tracks: ") + ErrInfo.Buffer, 0); } // index is valid and track number is now set, @@ -166,7 +167,7 @@ void FFmpegSourceAudioProvider::LoadAudio(wxString filename) { Index = DoIndexing(Indexer, CacheName, TrackMask, GetErrorHandlingMode()); } catch (wxString const& err) { - throw AudioOpenError(STD_STR(err)); + throw agi::AudioProviderOpenError(STD_STR(err), 0); } // if tracknumber still isn't set we need to set it now @@ -187,7 +188,7 @@ void FFmpegSourceAudioProvider::LoadAudio(wxString filename) { FFMS_DestroyIndex(Index); Index = NULL; if (!AudioSource) { - throw AudioOpenError(std::string("Failed to open audio track: %s") + ErrInfo.Buffer); + throw agi::AudioProviderOpenError(std::string("Failed to open audio track: %s") + ErrInfo.Buffer, 0); } const FFMS_AudioProperties AudioInfo = *FFMS_GetAudioProperties(AudioSource); @@ -196,7 +197,7 @@ void FFmpegSourceAudioProvider::LoadAudio(wxString filename) { sample_rate = AudioInfo.SampleRate; num_samples = AudioInfo.NumSamples; if (channels <= 0 || sample_rate <= 0 || num_samples <= 0) - throw AudioOpenError("sanity check failed, consult your local psychiatrist"); + throw agi::AudioProviderOpenError("sanity check failed, consult your local psychiatrist", 0); // FIXME: use the actual sample format too? // why not just bits_per_sample/8? maybe there's some oddball format with half bytes out there somewhere... @@ -206,7 +207,7 @@ void FFmpegSourceAudioProvider::LoadAudio(wxString filename) { case 24: bytes_per_sample = 3; break; case 32: bytes_per_sample = 4; break; default: - throw AudioOpenError("unknown or unsupported sample format"); + throw agi::AudioProviderOpenError("unknown or unsupported sample format", 0); } } diff --git a/aegisub/src/audio_provider_hd.cpp b/aegisub/src/audio_provider_hd.cpp index 13c6cfb06..cafcd0c73 100644 --- a/aegisub/src/audio_provider_hd.cpp +++ b/aegisub/src/audio_provider_hd.cpp @@ -46,6 +46,7 @@ #include "audio_provider_hd.h" +#include "audio_controller.h" #include "audio_provider_pcm.h" #include "compat.h" #include "main.h" @@ -103,7 +104,7 @@ HDAudioProvider::HDAudioProvider(AudioProvider *src, agi::BackgroundRunner *br) wxDiskspaceSize_t freespace; if (wxGetDiskSpace(cache_dir(), 0, &freespace)) { if (num_samples * channels * bytes_per_sample > freespace) - throw AudioOpenError("Not enough free disk space in " + STD_STR(cache_dir()) + " to cache the audio"); + throw agi::AudioCacheOpenError("Not enough free disk space in " + STD_STR(cache_dir()) + " to cache the audio", 0); } bytes_per_sample = source->GetBytesPerSample(); diff --git a/aegisub/src/audio_provider_pcm.cpp b/aegisub/src/audio_provider_pcm.cpp index 83a316902..fbea3475d 100644 --- a/aegisub/src/audio_provider_pcm.cpp +++ b/aegisub/src/audio_provider_pcm.cpp @@ -54,6 +54,7 @@ #include #include "aegisub_endian.h" +#include "audio_controller.h" #include "audio_provider_pcm.h" #include "compat.h" #include "utils.h" @@ -81,7 +82,7 @@ PCMAudioProvider::PCMAudioProvider(const wxString &filename) LARGE_INTEGER li_file_size = {0}; if (!GetFileSizeEx(file_handle, &li_file_size)) { CloseHandle(file_handle); - throw AudioOpenError("Failed getting file size"); + throw agi::AudioProviderOpenError("Failed getting file size", 0); } file_size = li_file_size.QuadPart; @@ -94,7 +95,7 @@ PCMAudioProvider::PCMAudioProvider(const wxString &filename) if (file_mapping == 0) { CloseHandle(file_handle); - throw AudioOpenError("Failed creating file mapping"); + throw agi::AudioProviderOpenError("Failed creating file mapping", 0); } current_mapping = 0; @@ -111,7 +112,7 @@ PCMAudioProvider::PCMAudioProvider(const wxString &filename) memset(&filestats, 0, sizeof(filestats)); if (fstat(file_handle, &filestats)) { close(file_handle); - throw AudioOpenError("Could not stat file to get size"); + throw agi::AudioProviderOpenError("Could not stat file to get size", 0); } file_size = filestats.st_size; @@ -331,9 +332,9 @@ public: // Check magic values if (!CheckFourcc(header.ch.type, "RIFF")) - throw AudioOpenError("File is not a RIFF file"); + throw agi::AudioDataNotFoundError("File is not a RIFF file", 0); if (!CheckFourcc(header.format, "WAVE")) - throw AudioOpenError("File is not a RIFF WAV file"); + throw agi::AudioDataNotFoundError("File is not a RIFF WAV file", 0); // Count how much more data we can have in the entire file // The first 4 bytes are already eaten by the header.format field @@ -356,13 +357,13 @@ public: filepos += sizeof(ch); if (CheckFourcc(ch.type, "fmt ")) { - if (got_fmt_header) throw AudioOpenError("Invalid file, multiple 'fmt ' chunks"); + if (got_fmt_header) throw agi::AudioProviderOpenError("Invalid file, multiple 'fmt ' chunks", 0); got_fmt_header = true; fmtChunk &fmt = *(fmtChunk*)EnsureRangeAccessible(filepos, sizeof(fmtChunk)); if (Endian::LittleToMachine(fmt.compression) != 1) - throw AudioOpenError("Can't use file, not PCM encoding"); + throw agi::AudioProviderOpenError("Can't use file, not PCM encoding", 0); // Set stuff inherited from the AudioProvider class sample_rate = Endian::LittleToMachine(fmt.samplerate); @@ -374,7 +375,7 @@ public: // This won't pick up 'data' chunks inside 'wavl' chunks // since the 'wavl' chunks wrap those. - if (!got_fmt_header) throw AudioOpenError("Found 'data' chunk before 'fmt ' chunk, file is invalid."); + if (!got_fmt_header) throw agi::AudioProviderOpenError("Found 'data' chunk before 'fmt ' chunk, file is invalid.", 0); int64_t samples = Endian::LittleToMachine(ch.size) / bytes_per_sample; int64_t frames = samples / channels; @@ -518,7 +519,7 @@ public: int64_t smallest_possible_file = sizeof(RiffChunk) + sizeof(FormatChunk) + sizeof(DataChunk); if (file_size < smallest_possible_file) - throw AudioOpenError("File is too small to be a Wave64 file"); + throw agi::AudioDataNotFoundError("File is too small to be a Wave64 file", 0); // Read header // This should throw an exception if the mapping fails @@ -528,9 +529,9 @@ public: // Check magic values if (!CheckGuid(header.riff_guid, w64GuidRIFF)) - throw AudioOpenError("File is not a Wave64 RIFF file"); + throw agi::AudioDataNotFoundError("File is not a Wave64 RIFF file", 0); if (!CheckGuid(header.format_guid, w64GuidWAVE)) - throw AudioOpenError("File is not a Wave64 WAVE file"); + throw agi::AudioDataNotFoundError("File is not a Wave64 WAVE file", 0); // Count how much more data we can have in the entire file uint64_t data_left = Endian::LittleToMachine(header.file_size) - sizeof(RiffChunk); @@ -550,15 +551,15 @@ public: if (CheckGuid(chunk_guid, w64Guidfmt)) { if (got_fmt_header) - throw AudioOpenError("Bad file, found more than one 'fmt' chunk"); + throw agi::AudioProviderOpenError("Bad file, found more than one 'fmt' chunk", 0); FormatChunk &fmt = *(FormatChunk*)EnsureRangeAccessible(filepos, sizeof(FormatChunk)); got_fmt_header = true; if (Endian::LittleToMachine(fmt.format.wFormatTag) == 3) - throw AudioOpenError("File is IEEE 32 bit float format which isn't supported. Bug the developers if this matters."); + throw agi::AudioProviderOpenError("File is IEEE 32 bit float format which isn't supported. Bug the developers if this matters.", 0); if (Endian::LittleToMachine(fmt.format.wFormatTag) != 1) - throw AudioOpenError("Can't use file, not PCM encoding"); + throw agi::AudioProviderOpenError("Can't use file, not PCM encoding", 0); // Set stuff inherited from the AudioProvider class sample_rate = Endian::LittleToMachine(fmt.format.nSamplesPerSec); @@ -567,7 +568,7 @@ public: } else if (CheckGuid(chunk_guid, w64Guiddata)) { if (!got_fmt_header) - throw AudioOpenError("Found 'data' chunk before 'fmt ' chunk, file is invalid."); + throw agi::AudioProviderOpenError("Found 'data' chunk before 'fmt ' chunk, file is invalid.", 0); int64_t samples = chunk_size / bytes_per_sample; int64_t frames = samples / channels; @@ -601,23 +602,35 @@ public: } }; -/// @brief DOCME -/// @param filename -/// AudioProvider *CreatePCMAudioProvider(const wxString &filename) { + bool wrong_file_type = true; std::string msg; + try { return new RiffWavPCMAudioProvider(filename); } - catch (AudioOpenError const& err) { + catch (agi::AudioDataNotFoundError const& err) { msg = "RIFF PCM WAV audio provider: " + err.GetMessage(); } + catch (agi::AudioProviderOpenError const& err) { + wrong_file_type = false; + msg = "RIFF PCM WAV audio provider: " + err.GetMessage(); + } + try { return new Wave64AudioProvider(filename); } - catch (AudioOpenError const& err) { + catch (agi::AudioDataNotFoundError const& err) { msg += "\nWave64 audio provider: " + err.GetMessage(); - throw AudioOpenError(msg); } + catch (agi::AudioProviderOpenError const& err) { + wrong_file_type = false; + msg += "\nWave64 audio provider: " + err.GetMessage(); + } + + if (wrong_file_type) + throw agi::AudioDataNotFoundError(msg, 0); + else + throw agi::AudioProviderOpenError(msg, 0); } diff --git a/aegisub/src/audio_provider_ram.cpp b/aegisub/src/audio_provider_ram.cpp index ec04e708b..646fa42e5 100644 --- a/aegisub/src/audio_provider_ram.cpp +++ b/aegisub/src/audio_provider_ram.cpp @@ -40,6 +40,7 @@ #include "audio_provider_ram.h" +#include "audio_controller.h" #include "compat.h" #include "main.h" #include "utils.h" @@ -67,7 +68,7 @@ RAMAudioProvider::RAMAudioProvider(AudioProvider *src, agi::BackgroundRunner *br } catch (std::bad_alloc const&) { Clear(); - throw AudioOpenError("Couldn't open audio, not enough ram available."); + throw agi::AudioCacheOpenError("Couldn't open audio, not enough ram available.", 0); } // Copy parameters diff --git a/aegisub/src/auto4_base.h b/aegisub/src/auto4_base.h index 21edd672a..cac2ea094 100644 --- a/aegisub/src/auto4_base.h +++ b/aegisub/src/auto4_base.h @@ -72,8 +72,6 @@ namespace agi { struct Context; } namespace cmd { class Command; } -DECLARE_EVENT_TYPE(wxEVT_AUTOMATION_SCRIPT_COMPLETED, -1) - /// DOCME namespace Automation4 { DEFINE_BASE_EXCEPTION_NOINNER(AutomationError, agi::Exception) diff --git a/aegisub/src/command/audio.cpp b/aegisub/src/command/audio.cpp index 2fd353de6..975ceacf8 100644 --- a/aegisub/src/command/audio.cpp +++ b/aegisub/src/command/audio.cpp @@ -119,7 +119,12 @@ struct audio_open_blank : public Command { STR_HELP("Open a 150 minutes blank audio clip, for debugging.") void operator()(agi::Context *c) { - c->audioController->OpenAudio("dummy-audio:silence?sr=44100&bd=16&ch=1&ln=396900000"); + try { + c->audioController->OpenAudio("dummy-audio:silence?sr=44100&bd=16&ch=1&ln=396900000"); + } + catch (agi::Exception const& e) { + wxMessageBox(lagi_wxString(e.GetChainedMessage()), "Error loading file", wxICON_ERROR | wxOK); + } } }; @@ -132,7 +137,12 @@ struct audio_open_noise : public Command { STR_HELP("Open a 150 minutes noise-filled audio clip, for debugging.") void operator()(agi::Context *c) { - c->audioController->OpenAudio("dummy-audio:noise?sr=44100&bd=16&ch=1&ln=396900000"); + try { + c->audioController->OpenAudio("dummy-audio:noise?sr=44100&bd=16&ch=1&ln=396900000"); + } + catch (agi::Exception const& e) { + wxMessageBox(lagi_wxString(e.GetChainedMessage()), "Error loading file", wxICON_ERROR | wxOK); + } } }; @@ -153,6 +163,7 @@ struct audio_open_video : public Command { try { c->audioController->OpenAudio(c->videoController->GetVideoName()); } + catch (agi::UserCancelException const&) { } catch (agi::Exception const& e) { wxMessageBox(lagi_wxString(e.GetChainedMessage()), "Error loading file", wxICON_ERROR | wxOK); } diff --git a/aegisub/src/include/aegisub/audio_player.h b/aegisub/src/include/aegisub/audio_player.h index 69e98525f..eb785cb4e 100644 --- a/aegisub/src/include/aegisub/audio_player.h +++ b/aegisub/src/include/aegisub/audio_player.h @@ -50,9 +50,7 @@ class AudioProvider; /// @brief DOCME /// /// DOCME -class AudioPlayer : public wxEvtHandler { - void OnStopAudio(wxCommandEvent &event); - +class AudioPlayer { protected: /// DOCME AudioProvider *provider; @@ -64,18 +62,11 @@ public: AudioPlayer(); virtual ~AudioPlayer(); - - /// @brief DOCME - /// virtual void OpenStream() {} - - /// @brief DOCME - /// virtual void CloseStream() {} virtual void Play(int64_t start,int64_t count)=0; // Play sample range virtual void Stop(bool timerToo=true)=0; // Stop playing - virtual void RequestStop(); // Request it to stop playing in a thread-safe way virtual bool IsPlaying()=0; virtual void SetVolume(double volume)=0; @@ -87,14 +78,8 @@ public: virtual void SetEndPosition(int64_t pos)=0; virtual void SetCurrentPosition(int64_t pos)=0; - virtual wxMutex *GetMutex() { return NULL; } - virtual void SetProvider(AudioProvider *new_provider) { provider = new_provider; } AudioProvider *GetProvider() const { return provider; } - - void SetDisplayTimer(wxTimer *timer) { displayTimer = timer; } - - DECLARE_EVENT_TABLE() }; class AudioPlayerFactory : public Factory0 { @@ -104,5 +89,3 @@ public: static void RegisterProviders(); static AudioPlayer *GetAudioPlayer(); }; - -DECLARE_EVENT_TYPE(wxEVT_STOP_AUDIO, -1) diff --git a/aegisub/src/include/aegisub/audio_provider.h b/aegisub/src/include/aegisub/audio_provider.h index 6eb6900b2..5baa22f1c 100644 --- a/aegisub/src/include/aegisub/audio_provider.h +++ b/aegisub/src/include/aegisub/audio_provider.h @@ -98,7 +98,5 @@ public: }; DEFINE_BASE_EXCEPTION_NOINNER(AudioProviderError, agi::Exception) -DEFINE_SIMPLE_EXCEPTION_NOINNER(AudioOpenError, AudioProviderError, "audio/open/failed") - /// Error of some sort occurred while decoding a frame DEFINE_SIMPLE_EXCEPTION_NOINNER(AudioDecodeError, AudioProviderError, "audio/error")