forked from mia/Aegisub
Remove a bunch of unused functionalty from agi::Exception
This commit is contained in:
parent
b43788fa7f
commit
8d26c66d0f
85 changed files with 239 additions and 359 deletions
|
@ -57,7 +57,7 @@ int main(int argc, char **argv) {
|
||||||
try {
|
try {
|
||||||
check(L, !LoadFile(L, argv[1]));
|
check(L, !LoadFile(L, argv[1]));
|
||||||
} catch (agi::Exception const& e) {
|
} catch (agi::Exception const& e) {
|
||||||
fprintf(stderr, "%s\n", e.GetChainedMessage().c_str());
|
fprintf(stderr, "%s\n", e.GetMessage().c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 2; i < argc; ++i)
|
for (int i = 2; i < argc; ++i)
|
||||||
|
|
|
@ -37,15 +37,15 @@ icu::BreakIterator& get_break_iterator(const char *ptr, size_t len) {
|
||||||
std::call_once(token, [&] {
|
std::call_once(token, [&] {
|
||||||
UErrorCode status = U_ZERO_ERROR;
|
UErrorCode status = U_ZERO_ERROR;
|
||||||
bi.reset(BreakIterator::createCharacterInstance(Locale::getDefault(), status));
|
bi.reset(BreakIterator::createCharacterInstance(Locale::getDefault(), status));
|
||||||
if (U_FAILURE(status)) throw agi::InternalError("Failed to create character iterator", nullptr);
|
if (U_FAILURE(status)) throw agi::InternalError("Failed to create character iterator");
|
||||||
});
|
});
|
||||||
|
|
||||||
UErrorCode err = U_ZERO_ERROR;
|
UErrorCode err = U_ZERO_ERROR;
|
||||||
utext_ptr ut(utext_openUTF8(nullptr, ptr, len, &err));
|
utext_ptr ut(utext_openUTF8(nullptr, ptr, len, &err));
|
||||||
if (U_FAILURE(err)) throw agi::InternalError("Failed to open utext", nullptr);
|
if (U_FAILURE(err)) throw agi::InternalError("Failed to open utext");
|
||||||
|
|
||||||
bi->setText(ut.get(), err);
|
bi->setText(ut.get(), err);
|
||||||
if (U_FAILURE(err)) throw agi::InternalError("Failed to set break iterator text", nullptr);
|
if (U_FAILURE(err)) throw agi::InternalError("Failed to set break iterator text");
|
||||||
|
|
||||||
return *bi;
|
return *bi;
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,7 +40,7 @@ char *map(int64_t s_offset, uint64_t length, boost::interprocess::mode_t mode,
|
||||||
|
|
||||||
auto offset = static_cast<uint64_t>(s_offset);
|
auto offset = static_cast<uint64_t>(s_offset);
|
||||||
if (offset + length > file_size)
|
if (offset + length > file_size)
|
||||||
throw agi::InternalError("Attempted to map beyond end of file", nullptr);
|
throw agi::InternalError("Attempted to map beyond end of file");
|
||||||
|
|
||||||
// Check if we can just use the current mapping
|
// Check if we can just use the current mapping
|
||||||
if (region && offset >= mapping_start && offset + length <= mapping_start + region->get_size())
|
if (region && offset >= mapping_start && offset + length <= mapping_start + region->get_size())
|
||||||
|
@ -150,9 +150,9 @@ temp_file_mapping::temp_file_mapping(fs::path const& filename, uint64_t size)
|
||||||
unlink(filename.string().c_str());
|
unlink(filename.string().c_str());
|
||||||
if (ftruncate(handle, size) == -1) {
|
if (ftruncate(handle, size) == -1) {
|
||||||
switch (errno) {
|
switch (errno) {
|
||||||
case EBADF: throw InternalError("Error opening file " + filename.string() + " not handled", nullptr);
|
case EBADF: throw InternalError("Error opening file " + filename.string() + " not handled");
|
||||||
case EFBIG: throw fs::DriveFull(filename);
|
case EFBIG: throw fs::DriveFull(filename);
|
||||||
case EINVAL: throw InternalError("File opened incorrectly: " + filename.string(), nullptr);
|
case EINVAL: throw InternalError("File opened incorrectly: " + filename.string());
|
||||||
case EROFS: throw fs::WriteDenied(filename);
|
case EROFS: throw fs::WriteDenied(filename);
|
||||||
default: throw fs::FileSystemUnknownError("Unknown error opening file: " + filename.string());
|
default: throw fs::FileSystemUnknownError("Unknown error opening file: " + filename.string());
|
||||||
}
|
}
|
||||||
|
|
|
@ -150,7 +150,7 @@ void ConfigVisitor::AddOptionValue(std::unique_ptr<OptionValue>&& opt) {
|
||||||
}
|
}
|
||||||
catch (agi::OptionValueError const& e) {
|
catch (agi::OptionValueError const& e) {
|
||||||
if (ignore_errors)
|
if (ignore_errors)
|
||||||
LOG_E("option/load/config_visitor") << "Error loading option from user configuration: " << e.GetChainedMessage();
|
LOG_E("option/load/config_visitor") << "Error loading option from user configuration: " << e.GetMessage();
|
||||||
else
|
else
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,10 +25,10 @@
|
||||||
|
|
||||||
namespace agi {
|
namespace agi {
|
||||||
|
|
||||||
DEFINE_BASE_EXCEPTION_NOINNER(OptionJsonValueError, Exception)
|
DEFINE_EXCEPTION(OptionJsonValueError, Exception);
|
||||||
DEFINE_SIMPLE_EXCEPTION_NOINNER(OptionJsonValueArray, OptionJsonValueError, "options/value/array")
|
DEFINE_EXCEPTION(OptionJsonValueArray, OptionJsonValueError);
|
||||||
DEFINE_SIMPLE_EXCEPTION_NOINNER(OptionJsonValueSingle, OptionJsonValueError, "options/value")
|
DEFINE_EXCEPTION(OptionJsonValueSingle, OptionJsonValueError);
|
||||||
DEFINE_SIMPLE_EXCEPTION_NOINNER(OptionJsonValueNull, OptionJsonValueError, "options/value")
|
DEFINE_EXCEPTION(OptionJsonValueNull, OptionJsonValueError);
|
||||||
|
|
||||||
class ConfigVisitor final : public json::ConstVisitor {
|
class ConfigVisitor final : public json::ConstVisitor {
|
||||||
/// Option map being populated
|
/// Option map being populated
|
||||||
|
|
|
@ -62,7 +62,7 @@ fs::path Path::Decode(std::string const& path) const {
|
||||||
|
|
||||||
fs::path Path::MakeRelative(fs::path const& path, std::string const& token) const {
|
fs::path Path::MakeRelative(fs::path const& path, std::string const& token) const {
|
||||||
const auto it = tokens.find(token);
|
const auto it = tokens.find(token);
|
||||||
if (it == tokens.end()) throw agi::InternalError("Bad token: " + token, nullptr);
|
if (it == tokens.end()) throw agi::InternalError("Bad token: " + token);
|
||||||
|
|
||||||
return MakeRelative(path, it->second);
|
return MakeRelative(path, it->second);
|
||||||
}
|
}
|
||||||
|
@ -94,7 +94,7 @@ fs::path Path::MakeRelative(fs::path const& path, fs::path const& base) const {
|
||||||
fs::path Path::MakeAbsolute(fs::path path, std::string const& token) const {
|
fs::path Path::MakeAbsolute(fs::path path, std::string const& token) const {
|
||||||
if (path.empty()) return path;
|
if (path.empty()) return path;
|
||||||
const auto it = tokens.find(token);
|
const auto it = tokens.find(token);
|
||||||
if (it == tokens.end()) throw agi::InternalError("Bad token: " + token, nullptr);
|
if (it == tokens.end()) throw agi::InternalError("Bad token: " + token);
|
||||||
|
|
||||||
path.make_preferred();
|
path.make_preferred();
|
||||||
const auto str = path.string();
|
const auto str = path.string();
|
||||||
|
@ -123,7 +123,7 @@ std::string Path::Encode(fs::path const& path) const {
|
||||||
|
|
||||||
void Path::SetToken(std::string const& token_name, fs::path const& token_value) {
|
void Path::SetToken(std::string const& token_name, fs::path const& token_value) {
|
||||||
const auto it = tokens.find(token_name);
|
const auto it = tokens.find(token_name);
|
||||||
if (it == tokens.end()) throw agi::InternalError("Bad token: " + token_name, nullptr);
|
if (it == tokens.end()) throw agi::InternalError("Bad token: " + token_name);
|
||||||
|
|
||||||
if (token_value.empty())
|
if (token_value.empty())
|
||||||
it->second = token_value;
|
it->second = token_value;
|
||||||
|
|
|
@ -26,8 +26,8 @@ namespace agi {
|
||||||
/// Character set conversion and detection.
|
/// Character set conversion and detection.
|
||||||
namespace charset {
|
namespace charset {
|
||||||
|
|
||||||
DEFINE_BASE_EXCEPTION_NOINNER(CharsetError, agi::Exception)
|
DEFINE_EXCEPTION(CharsetError, agi::Exception);
|
||||||
DEFINE_SIMPLE_EXCEPTION_NOINNER(UnknownCharset, CharsetError, "charset/unknown")
|
DEFINE_EXCEPTION(UnknownCharset, CharsetError);
|
||||||
|
|
||||||
/// List of detected encodings.
|
/// List of detected encodings.
|
||||||
typedef std::vector<std::pair<float, std::string>> CharsetListDetected;
|
typedef std::vector<std::pair<float, std::string>> CharsetListDetected;
|
||||||
|
|
|
@ -27,12 +27,12 @@
|
||||||
namespace agi {
|
namespace agi {
|
||||||
namespace charset {
|
namespace charset {
|
||||||
|
|
||||||
DEFINE_BASE_EXCEPTION_NOINNER(ConvError, Exception)
|
DEFINE_EXCEPTION(ConvError, Exception);
|
||||||
DEFINE_SIMPLE_EXCEPTION_NOINNER(UnsupportedConversion, ConvError, "iconv/unsupported")
|
DEFINE_EXCEPTION(UnsupportedConversion, ConvError);
|
||||||
DEFINE_SIMPLE_EXCEPTION_NOINNER(ConversionFailure, ConvError, "iconv/failed")
|
DEFINE_EXCEPTION(ConversionFailure, ConvError);
|
||||||
DEFINE_SIMPLE_EXCEPTION_NOINNER(BufferTooSmall, ConversionFailure, "iconv/failed/E2BIG")
|
DEFINE_EXCEPTION(BufferTooSmall, ConversionFailure);
|
||||||
DEFINE_SIMPLE_EXCEPTION_NOINNER(BadInput, ConversionFailure, "iconv/failed/EILSEQ")
|
DEFINE_EXCEPTION(BadInput, ConversionFailure);
|
||||||
DEFINE_SIMPLE_EXCEPTION_NOINNER(BadOutput, ConversionFailure, "iconv/failed/EINVAL")
|
DEFINE_EXCEPTION(BadOutput, ConversionFailure);
|
||||||
|
|
||||||
typedef void* iconv_t;
|
typedef void* iconv_t;
|
||||||
|
|
||||||
|
|
|
@ -27,14 +27,8 @@
|
||||||
//
|
//
|
||||||
// Aegisub Project http://www.aegisub.org/
|
// Aegisub Project http://www.aegisub.org/
|
||||||
|
|
||||||
/// @file exception.h
|
|
||||||
/// @brief Base exception classes for structured error handling
|
|
||||||
/// @ingroup main_headers
|
|
||||||
///
|
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
namespace agi {
|
namespace agi {
|
||||||
|
@ -90,26 +84,13 @@ namespace agi {
|
||||||
/// The error message
|
/// The error message
|
||||||
std::string message;
|
std::string message;
|
||||||
|
|
||||||
/// An inner exception, the cause of this exception
|
|
||||||
std::shared_ptr<Exception> inner;
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/// @brief Protected constructor initialising members
|
/// @brief Protected constructor initialising members
|
||||||
/// @param msg The error message
|
/// @param msg The error message
|
||||||
/// @param inr The inner exception, optional
|
|
||||||
///
|
///
|
||||||
/// Deriving classes should always use this constructor for initialising
|
/// Deriving classes should always use this constructor for initialising
|
||||||
/// the base class.
|
/// the base class.
|
||||||
Exception(std::string msg, const Exception *inr = nullptr) : message(std::move(msg)) {
|
Exception(std::string msg) : message(std::move(msg)) { }
|
||||||
if (inr)
|
|
||||||
inner.reset(inr->Copy());
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief Default constructor, not implemented
|
|
||||||
///
|
|
||||||
/// The default constructor is not implemented because it must not be used,
|
|
||||||
/// as it leaves the members un-initialised.
|
|
||||||
Exception();
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/// @brief Destructor
|
/// @brief Destructor
|
||||||
|
@ -117,41 +98,7 @@ namespace agi {
|
||||||
|
|
||||||
/// @brief Get the outer exception error message
|
/// @brief Get the outer exception error message
|
||||||
/// @return Error message
|
/// @return Error message
|
||||||
virtual std::string GetMessage() const { return message; }
|
std::string const& GetMessage() const { return message; }
|
||||||
|
|
||||||
/// @brief Get error messages for chained exceptions
|
|
||||||
/// @return Chained error message
|
|
||||||
///
|
|
||||||
/// If there is an inner exception, prepend its chained error message to
|
|
||||||
/// our error message, with a CRLF between. Returns our own error message
|
|
||||||
/// alone if there is no inner exception.
|
|
||||||
std::string GetChainedMessage() const { if (inner.get()) return inner->GetChainedMessage() + "\r\n" + GetMessage(); else return GetMessage(); }
|
|
||||||
|
|
||||||
/// @brief Exception class printable name
|
|
||||||
///
|
|
||||||
/// Sub classes should implement this to return a constant character string
|
|
||||||
/// naming their exception in a hierarchic manner.
|
|
||||||
///
|
|
||||||
/// Exception classes inheriting directly from Exception define a top-level
|
|
||||||
/// name for their sub-tree, further sub-classes add further levels, each
|
|
||||||
/// level is separated by a slash. Characters allowed in the name for a
|
|
||||||
/// level are [a-z0-9_].
|
|
||||||
virtual const char * GetName() const = 0;
|
|
||||||
|
|
||||||
/// @brief Convert to char array as the error message
|
|
||||||
/// @return The error message
|
|
||||||
operator const char * () { return GetMessage().c_str(); }
|
|
||||||
|
|
||||||
/// @brief Convert to std::string as the error message
|
|
||||||
/// @return The error message
|
|
||||||
operator std::string () { return GetMessage(); }
|
|
||||||
|
|
||||||
/// @brief Create a copy of the exception allocated on the heap
|
|
||||||
/// @return A heap-allocated exception object
|
|
||||||
///
|
|
||||||
/// All deriving classes must implement this explicitly to avoid losing
|
|
||||||
/// information in the duplication.
|
|
||||||
virtual Exception *Copy() const = 0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// @brief Convenience macro to include the current location in code
|
/// @brief Convenience macro to include the current location in code
|
||||||
|
@ -160,62 +107,14 @@ namespace agi {
|
||||||
/// indicate the exact position the error occurred at.
|
/// indicate the exact position the error occurred at.
|
||||||
#define AG_WHERE " (at " __FILE__ ":" #__LINE__ ")"
|
#define AG_WHERE " (at " __FILE__ ":" #__LINE__ ")"
|
||||||
|
|
||||||
/// @brief Convenience macro for declaring exceptions with no support for inner exception
|
/// @brief Convenience macro for declaring exceptions
|
||||||
/// @param classname Name of the exception class to declare
|
/// @param classname Name of the exception class to declare
|
||||||
/// @param baseclass Class to derive from
|
/// @param baseclass Class to derive from
|
||||||
/// @param displayname The printable name of the exception (return of GetName())
|
#define DEFINE_EXCEPTION(classname, baseclass) \
|
||||||
///
|
class classname : public baseclass { \
|
||||||
/// This macro covers most cases of exception classes where support for inner
|
public: \
|
||||||
/// exceptions is not relevant/wanted.
|
classname(std::string msg) : baseclass(std::move(msg)) { } \
|
||||||
#define DEFINE_SIMPLE_EXCEPTION_NOINNER(classname,baseclass,displayname) \
|
}
|
||||||
class classname : public baseclass { \
|
|
||||||
public: \
|
|
||||||
classname(const std::string &msg) : baseclass(msg) { } \
|
|
||||||
const char * GetName() const { return displayname; } \
|
|
||||||
Exception * Copy() const { return new classname(*this); } \
|
|
||||||
};
|
|
||||||
|
|
||||||
/// @brief Convenience macro for declaring exceptions supporting inner exceptions
|
|
||||||
/// @param classname Name of the exception class to declare
|
|
||||||
/// @param baseclass Class to derive from
|
|
||||||
/// @param displayname The printable name of the exception (return of GetName())
|
|
||||||
///
|
|
||||||
/// This macro covers most cases of exception classes that should support
|
|
||||||
/// inner exceptions.
|
|
||||||
#define DEFINE_SIMPLE_EXCEPTION(classname,baseclass,displayname) \
|
|
||||||
class classname : public baseclass { \
|
|
||||||
public: \
|
|
||||||
classname(const std::string &msg, Exception *inner) : baseclass(msg, inner) { } \
|
|
||||||
const char * GetName() const { return displayname; } \
|
|
||||||
Exception * Copy() const { return new classname(*this); } \
|
|
||||||
};
|
|
||||||
|
|
||||||
/// @brief Macro for declaring non-instantiable exception base classes
|
|
||||||
/// @param classname Name of the exception class to declare
|
|
||||||
/// @param baseclass Class to derive from
|
|
||||||
///
|
|
||||||
/// Declares an exception class that does not implement the GetName() function
|
|
||||||
/// and as such (unless a base class implements it) is not constructable.
|
|
||||||
/// Classes declared by this macro do not support inner exceptions.
|
|
||||||
#define DEFINE_BASE_EXCEPTION_NOINNER(classname,baseclass) \
|
|
||||||
class classname : public baseclass { \
|
|
||||||
public: \
|
|
||||||
classname(const std::string &msg) : baseclass(msg) { } \
|
|
||||||
};
|
|
||||||
|
|
||||||
/// @brief Macro for declaring non-instantiable exception base classes with inner
|
|
||||||
/// exception support
|
|
||||||
/// @param classname Name of the exception class to declare
|
|
||||||
/// @param baseclass Class to derive from
|
|
||||||
///
|
|
||||||
/// Declares an exception class that does not implement the GetName() function
|
|
||||||
/// and as such (unless a base class implements it) is not constructable.
|
|
||||||
/// Classes declared by this macro do support inner exceptions.
|
|
||||||
#define DEFINE_BASE_EXCEPTION(classname,baseclass) \
|
|
||||||
class classname : public baseclass { \
|
|
||||||
public: \
|
|
||||||
classname(const std::string &msg, Exception *inner) : baseclass(msg, inner) { } \
|
|
||||||
};
|
|
||||||
|
|
||||||
/// @class agi::UserCancelException
|
/// @class agi::UserCancelException
|
||||||
/// @extends agi::Exception
|
/// @extends agi::Exception
|
||||||
|
@ -229,7 +128,7 @@ namespace agi {
|
||||||
/// possible, user cancel exceptions should unwind anything that was going on at the
|
/// possible, user cancel exceptions should unwind anything that was going on at the
|
||||||
/// moment. For this to work, RAII methodology has to be used consequently in the
|
/// moment. For this to work, RAII methodology has to be used consequently in the
|
||||||
/// code in question.
|
/// code in question.
|
||||||
DEFINE_SIMPLE_EXCEPTION_NOINNER(UserCancelException,Exception,"nonerror/user_cancel")
|
DEFINE_EXCEPTION(UserCancelException, Exception);
|
||||||
|
|
||||||
/// @class agi::InternalError
|
/// @class agi::InternalError
|
||||||
/// @extends agi:Exception
|
/// @extends agi:Exception
|
||||||
|
@ -240,7 +139,7 @@ namespace agi {
|
||||||
/// have become inconsistent. All internal errors are of the type "this should never
|
/// have become inconsistent. All internal errors are of the type "this should never
|
||||||
/// happen", most often you'll want this kind of error unwind all the way past the main UI
|
/// happen", most often you'll want this kind of error unwind all the way past the main UI
|
||||||
/// and eventually cause an abort().
|
/// and eventually cause an abort().
|
||||||
DEFINE_SIMPLE_EXCEPTION(InternalError, Exception, "internal_error")
|
DEFINE_EXCEPTION(InternalError, Exception);
|
||||||
|
|
||||||
/// @class agi::EnvironmentError
|
/// @class agi::EnvironmentError
|
||||||
/// @extends agi:Exception
|
/// @extends agi:Exception
|
||||||
|
@ -249,10 +148,10 @@ namespace agi {
|
||||||
/// Throw an environment error when a call to the platform API has failed
|
/// Throw an environment error when a call to the platform API has failed
|
||||||
/// in some way that should normally never happen or suggests that the
|
/// in some way that should normally never happen or suggests that the
|
||||||
/// runtime environment is too insane to support.
|
/// runtime environment is too insane to support.
|
||||||
DEFINE_SIMPLE_EXCEPTION_NOINNER(EnvironmentError, Exception, "environment_error")
|
DEFINE_EXCEPTION(EnvironmentError, Exception);
|
||||||
|
|
||||||
/// @class agi::InvalidInputException
|
/// @class agi::InvalidInputException
|
||||||
/// @extends agi::Exception
|
/// @extends agi::Exception
|
||||||
/// @brief Some input data were invalid and could not be processed
|
/// @brief Some input data were invalid and could not be processed
|
||||||
DEFINE_BASE_EXCEPTION(InvalidInputException, Exception)
|
DEFINE_EXCEPTION(InvalidInputException, Exception);
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,7 +44,7 @@ namespace agi {
|
||||||
/// This base class can not be instantiated.
|
/// This base class can not be instantiated.
|
||||||
/// File system errors do not support inner exceptions, as they
|
/// File system errors do not support inner exceptions, as they
|
||||||
/// are always originating causes for errors.
|
/// are always originating causes for errors.
|
||||||
DEFINE_BASE_EXCEPTION_NOINNER(FileSystemError, Exception)
|
DEFINE_EXCEPTION(FileSystemError, Exception);
|
||||||
|
|
||||||
/// A file can't be accessed for some reason
|
/// A file can't be accessed for some reason
|
||||||
DEFINE_FS_EXCEPTION(FileNotAccessible, FileSystemError, "File is not accessible: ");
|
DEFINE_FS_EXCEPTION(FileNotAccessible, FileSystemError, "File is not accessible: ");
|
||||||
|
@ -53,7 +53,7 @@ namespace agi {
|
||||||
DEFINE_FS_EXCEPTION(FileNotFound, FileNotAccessible, "File not found: ");
|
DEFINE_FS_EXCEPTION(FileNotFound, FileNotAccessible, "File not found: ");
|
||||||
|
|
||||||
/// An error of some unknown type has occured
|
/// An error of some unknown type has occured
|
||||||
DEFINE_SIMPLE_EXCEPTION_NOINNER(FileSystemUnknownError, FileSystemError, "filesystem/unknown");
|
DEFINE_EXCEPTION(FileSystemUnknownError, FileSystemError);;
|
||||||
|
|
||||||
/// The path exists, but isn't a file
|
/// The path exists, but isn't a file
|
||||||
DEFINE_FS_EXCEPTION(NotAFile, FileNotAccessible, "Path is not a file (and should be): ");
|
DEFINE_FS_EXCEPTION(NotAFile, FileNotAccessible, "Path is not a file (and should be): ");
|
||||||
|
|
|
@ -26,8 +26,8 @@
|
||||||
namespace agi {
|
namespace agi {
|
||||||
namespace io {
|
namespace io {
|
||||||
|
|
||||||
DEFINE_BASE_EXCEPTION_NOINNER(IOError, Exception)
|
DEFINE_EXCEPTION(IOError, Exception);
|
||||||
DEFINE_SIMPLE_EXCEPTION_NOINNER(IOFatal, IOError, "io/fatal")
|
DEFINE_EXCEPTION(IOFatal, IOError);
|
||||||
|
|
||||||
std::unique_ptr<std::istream> Open(fs::path const& file, bool binary = false);
|
std::unique_ptr<std::istream> Open(fs::path const& file, bool binary = false);
|
||||||
|
|
||||||
|
|
|
@ -12,10 +12,10 @@
|
||||||
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
|
||||||
#include <vector>
|
#include <libaegisub/exception.h>
|
||||||
|
#include <libaegisub/fs_fwd.h>
|
||||||
|
|
||||||
#include "exception.h"
|
#include <vector>
|
||||||
#include "fs_fwd.h"
|
|
||||||
|
|
||||||
namespace agi {
|
namespace agi {
|
||||||
namespace keyframe {
|
namespace keyframe {
|
||||||
|
@ -29,6 +29,6 @@ namespace agi {
|
||||||
/// @param keyframes List of keyframes to save
|
/// @param keyframes List of keyframes to save
|
||||||
void Save(agi::fs::path const& filename, std::vector<int> const& keyframes);
|
void Save(agi::fs::path const& filename, std::vector<int> const& keyframes);
|
||||||
|
|
||||||
DEFINE_SIMPLE_EXCEPTION_NOINNER(Error, Exception, "keyframe/error")
|
DEFINE_EXCEPTION(Error, Exception);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -79,7 +79,7 @@ int exception_wrapper(lua_State *L) {
|
||||||
return func(L);
|
return func(L);
|
||||||
}
|
}
|
||||||
catch (agi::Exception const& e) {
|
catch (agi::Exception const& e) {
|
||||||
push_value(L, e.GetChainedMessage());
|
push_value(L, e.GetMessage());
|
||||||
return lua_error(L);
|
return lua_error(L);
|
||||||
}
|
}
|
||||||
catch (std::exception const& e) {
|
catch (std::exception const& e) {
|
||||||
|
|
|
@ -27,9 +27,9 @@ namespace json {
|
||||||
namespace agi {
|
namespace agi {
|
||||||
class Options;
|
class Options;
|
||||||
|
|
||||||
DEFINE_BASE_EXCEPTION_NOINNER(MRUError,Exception)
|
DEFINE_EXCEPTION(MRUError, Exception);
|
||||||
DEFINE_SIMPLE_EXCEPTION_NOINNER(MRUErrorInvalidKey, MRUError, "mru/invalid")
|
DEFINE_EXCEPTION(MRUErrorInvalidKey, MRUError);
|
||||||
DEFINE_SIMPLE_EXCEPTION_NOINNER(MRUErrorIndexOutOfRange, MRUError, "mru/invalid")
|
DEFINE_EXCEPTION(MRUErrorIndexOutOfRange, MRUError);
|
||||||
|
|
||||||
/// @class MRUManager
|
/// @class MRUManager
|
||||||
/// @brief Most Recently Used (MRU) list handling
|
/// @brief Most Recently Used (MRU) list handling
|
||||||
|
|
|
@ -33,9 +33,9 @@ namespace json {
|
||||||
|
|
||||||
namespace agi {
|
namespace agi {
|
||||||
|
|
||||||
DEFINE_BASE_EXCEPTION_NOINNER(OptionError,Exception)
|
DEFINE_EXCEPTION(OptionError, Exception);
|
||||||
DEFINE_SIMPLE_EXCEPTION_NOINNER(OptionErrorNotFound, OptionError, "options/not_found")
|
DEFINE_EXCEPTION(OptionErrorNotFound, OptionError);
|
||||||
DEFINE_SIMPLE_EXCEPTION_NOINNER(OptionErrorDuplicateKey, OptionError, "options/dump/duplicate")
|
DEFINE_EXCEPTION(OptionErrorDuplicateKey, OptionError);
|
||||||
|
|
||||||
class OptionValue;
|
class OptionValue;
|
||||||
|
|
||||||
|
|
|
@ -27,8 +27,8 @@
|
||||||
#undef Bool
|
#undef Bool
|
||||||
|
|
||||||
namespace agi {
|
namespace agi {
|
||||||
DEFINE_BASE_EXCEPTION_NOINNER(OptionValueError, Exception)
|
DEFINE_EXCEPTION(OptionValueError, Exception);
|
||||||
DEFINE_SIMPLE_EXCEPTION_NOINNER(OptionValueErrorInvalidType, OptionValueError, "options/invalid_type")
|
DEFINE_EXCEPTION(OptionValueErrorInvalidType, OptionValueError);
|
||||||
|
|
||||||
/// Option type
|
/// Option type
|
||||||
/// No bitsets here.
|
/// No bitsets here.
|
||||||
|
@ -64,7 +64,7 @@ class OptionValue {
|
||||||
case OptionType::ListColor: return "List of Colors";
|
case OptionType::ListColor: return "List of Colors";
|
||||||
case OptionType::ListBool: return "List of Bools";
|
case OptionType::ListBool: return "List of Bools";
|
||||||
}
|
}
|
||||||
throw agi::InternalError("Invalid option type", nullptr);
|
throw agi::InternalError("Invalid option type");
|
||||||
}
|
}
|
||||||
|
|
||||||
OptionValueErrorInvalidType TypeError(OptionType type) const {
|
OptionValueErrorInvalidType TypeError(OptionType type) const {
|
||||||
|
|
|
@ -39,17 +39,17 @@ enum Time {
|
||||||
END
|
END
|
||||||
};
|
};
|
||||||
|
|
||||||
DEFINE_BASE_EXCEPTION_NOINNER(Error, Exception)
|
DEFINE_EXCEPTION(Error, Exception);
|
||||||
/// FPS specified is not a valid frame rate
|
/// FPS specified is not a valid frame rate
|
||||||
DEFINE_SIMPLE_EXCEPTION_NOINNER(BadFPS, Error, "vfr/badfps")
|
DEFINE_EXCEPTION(BadFPS, Error);
|
||||||
/// Unknown timecode file format
|
/// Unknown timecode file format
|
||||||
DEFINE_SIMPLE_EXCEPTION_NOINNER(UnknownFormat, Error, "vfr/timecodes/unknownformat")
|
DEFINE_EXCEPTION(UnknownFormat, Error);
|
||||||
/// Invalid line encountered in a timecode file
|
/// Invalid line encountered in a timecode file
|
||||||
DEFINE_SIMPLE_EXCEPTION_NOINNER(MalformedLine, Error, "vfr/timecodes/malformed")
|
DEFINE_EXCEPTION(MalformedLine, Error);
|
||||||
/// Timecode file or vector has too few timecodes to be usable
|
/// Timecode file or vector has too few timecodes to be usable
|
||||||
DEFINE_SIMPLE_EXCEPTION_NOINNER(TooFewTimecodes, Error, "vfr/timecodes/toofew")
|
DEFINE_EXCEPTION(TooFewTimecodes, Error);
|
||||||
/// Timecode file or vector has timecodes that are not monotonically increasing
|
/// Timecode file or vector has timecodes that are not monotonically increasing
|
||||||
DEFINE_SIMPLE_EXCEPTION_NOINNER(UnorderedTimecodes, Error, "vfr/timecodes/order")
|
DEFINE_EXCEPTION(UnorderedTimecodes, Error);
|
||||||
|
|
||||||
/// @class Framerate
|
/// @class Framerate
|
||||||
/// @brief Class for managing everything related to converting frames to times
|
/// @brief Class for managing everything related to converting frames to times
|
||||||
|
|
|
@ -38,7 +38,7 @@ int wrap(lua_State *L) {
|
||||||
}
|
}
|
||||||
catch (agi::Exception const& e) {
|
catch (agi::Exception const& e) {
|
||||||
lua_pushnil(L);
|
lua_pushnil(L);
|
||||||
push_value(L, e.GetChainedMessage());
|
push_value(L, e.GetMessage());
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
catch (error_tag) {
|
catch (error_tag) {
|
||||||
|
|
|
@ -31,7 +31,7 @@ namespace agi { namespace lua {
|
||||||
filename = agi::fs::Canonicalize(raw_filename);
|
filename = agi::fs::Canonicalize(raw_filename);
|
||||||
}
|
}
|
||||||
catch (agi::fs::FileSystemUnknownError const& e) {
|
catch (agi::fs::FileSystemUnknownError const& e) {
|
||||||
LOG_E("auto4/lua") << "Error canonicalizing path: " << e.GetChainedMessage();
|
LOG_E("auto4/lua") << "Error canonicalizing path: " << e.GetMessage();
|
||||||
}
|
}
|
||||||
|
|
||||||
agi::read_file_mapping file(filename);
|
agi::read_file_mapping file(filename);
|
||||||
|
@ -112,7 +112,7 @@ namespace agi { namespace lua {
|
||||||
// Not an error so swallow and continue on
|
// Not an error so swallow and continue on
|
||||||
}
|
}
|
||||||
catch (agi::Exception const& e) {
|
catch (agi::Exception const& e) {
|
||||||
return error(L, "Error loading Lua module \"%s\":\n%s", path.string().c_str(), e.GetChainedMessage().c_str());
|
return error(L, "Error loading Lua module \"%s\":\n%s", path.string().c_str(), e.GetMessage().c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -81,7 +81,7 @@ public:
|
||||||
|
|
||||||
agi::StringRange next_tok() {
|
agi::StringRange next_tok() {
|
||||||
if (pos.eof())
|
if (pos.eof())
|
||||||
throw SubtitleFormatParseError("Failed parsing line: " + std::string(str.begin(), str.end()), nullptr);
|
throw SubtitleFormatParseError("Failed parsing line: " + std::string(str.begin(), str.end()));
|
||||||
return *pos++;
|
return *pos++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -100,7 +100,7 @@ void AssDialogue::Parse(std::string const& raw) {
|
||||||
str = agi::StringRange(raw.begin() + 9, raw.end());
|
str = agi::StringRange(raw.begin() + 9, raw.end());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
throw SubtitleFormatParseError("Failed parsing line: " + raw, nullptr);
|
throw SubtitleFormatParseError("Failed parsing line: " + raw);
|
||||||
|
|
||||||
tokenizer tkn(str);
|
tokenizer tkn(str);
|
||||||
|
|
||||||
|
|
|
@ -79,7 +79,7 @@ AssOverrideParameter::~AssOverrideParameter() {
|
||||||
}
|
}
|
||||||
|
|
||||||
template<> std::string AssOverrideParameter::Get<std::string>() const {
|
template<> std::string AssOverrideParameter::Get<std::string>() const {
|
||||||
if (omitted) throw agi::InternalError("AssOverrideParameter::Get() called on omitted parameter", nullptr);
|
if (omitted) throw agi::InternalError("AssOverrideParameter::Get() called on omitted parameter");
|
||||||
if (block.get()) {
|
if (block.get()) {
|
||||||
std::string str(block->GetText());
|
std::string str(block->GetText());
|
||||||
if (boost::starts_with(str, "{")) str.erase(begin(str));
|
if (boost::starts_with(str, "{")) str.erase(begin(str));
|
||||||
|
|
|
@ -146,7 +146,7 @@ void AssParser::ParseScriptInfoLine(std::string const& data) {
|
||||||
else if (version_str == "v4.00+")
|
else if (version_str == "v4.00+")
|
||||||
version = 1;
|
version = 1;
|
||||||
else
|
else
|
||||||
throw SubtitleFormatParseError("Unknown SSA file format version", nullptr);
|
throw SubtitleFormatParseError("Unknown SSA file format version");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Nothing actually supports the Collisions property and malformed values
|
// Nothing actually supports the Collisions property and malformed values
|
||||||
|
|
|
@ -56,7 +56,7 @@ class parser {
|
||||||
|
|
||||||
std::string next_tok() {
|
std::string next_tok() {
|
||||||
if (pos.eof())
|
if (pos.eof())
|
||||||
throw SubtitleFormatParseError("Malformed style: not enough fields", nullptr);
|
throw SubtitleFormatParseError("Malformed style: not enough fields");
|
||||||
return agi::str(trim_copy(*pos++));
|
return agi::str(trim_copy(*pos++));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,7 +69,7 @@ public:
|
||||||
|
|
||||||
void check_done() const {
|
void check_done() const {
|
||||||
if (!pos.eof())
|
if (!pos.eof())
|
||||||
throw SubtitleFormatParseError("Malformed style: too many fields", nullptr);
|
throw SubtitleFormatParseError("Malformed style: too many fields");
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string next_str() { return next_tok(); }
|
std::string next_str() { return next_tok(); }
|
||||||
|
@ -80,7 +80,7 @@ public:
|
||||||
return boost::lexical_cast<int>(next_tok());
|
return boost::lexical_cast<int>(next_tok());
|
||||||
}
|
}
|
||||||
catch (boost::bad_lexical_cast const&) {
|
catch (boost::bad_lexical_cast const&) {
|
||||||
throw SubtitleFormatParseError("Malformed style: bad int field", nullptr);
|
throw SubtitleFormatParseError("Malformed style: bad int field");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,7 +89,7 @@ public:
|
||||||
return boost::lexical_cast<double>(next_tok());
|
return boost::lexical_cast<double>(next_tok());
|
||||||
}
|
}
|
||||||
catch (boost::bad_lexical_cast const&) {
|
catch (boost::bad_lexical_cast const&) {
|
||||||
throw SubtitleFormatParseError("Malformed style: bad double field", nullptr);
|
throw SubtitleFormatParseError("Malformed style: bad double field");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -170,12 +170,12 @@ wxDEFINE_EVENT(EVT_VIDEO_ERROR, VideoProviderErrorEvent);
|
||||||
wxDEFINE_EVENT(EVT_SUBTITLES_ERROR, SubtitlesProviderErrorEvent);
|
wxDEFINE_EVENT(EVT_SUBTITLES_ERROR, SubtitlesProviderErrorEvent);
|
||||||
|
|
||||||
VideoProviderErrorEvent::VideoProviderErrorEvent(VideoProviderError const& err)
|
VideoProviderErrorEvent::VideoProviderErrorEvent(VideoProviderError const& err)
|
||||||
: agi::Exception(err.GetMessage(), &err)
|
: agi::Exception(err.GetMessage())
|
||||||
{
|
{
|
||||||
SetEventType(EVT_VIDEO_ERROR);
|
SetEventType(EVT_VIDEO_ERROR);
|
||||||
}
|
}
|
||||||
SubtitlesProviderErrorEvent::SubtitlesProviderErrorEvent(std::string const& err)
|
SubtitlesProviderErrorEvent::SubtitlesProviderErrorEvent(std::string const& err)
|
||||||
: agi::Exception(err, nullptr)
|
: agi::Exception(err)
|
||||||
{
|
{
|
||||||
SetEventType(EVT_SUBTITLES_ERROR);
|
SetEventType(EVT_SUBTITLES_ERROR);
|
||||||
}
|
}
|
||||||
|
|
|
@ -134,16 +134,12 @@ struct FrameReadyEvent final : public wxEvent {
|
||||||
// These exceptions are wxEvents so that they can be passed directly back to
|
// These exceptions are wxEvents so that they can be passed directly back to
|
||||||
// the parent thread as events
|
// the parent thread as events
|
||||||
struct VideoProviderErrorEvent final : public wxEvent, public agi::Exception {
|
struct VideoProviderErrorEvent final : public wxEvent, public agi::Exception {
|
||||||
const char * GetName() const override { return "video/error"; }
|
|
||||||
wxEvent *Clone() const override { return new VideoProviderErrorEvent(*this); };
|
wxEvent *Clone() const override { return new VideoProviderErrorEvent(*this); };
|
||||||
agi::Exception *Copy() const override { return new VideoProviderErrorEvent(*this); };
|
|
||||||
VideoProviderErrorEvent(VideoProviderError const& err);
|
VideoProviderErrorEvent(VideoProviderError const& err);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SubtitlesProviderErrorEvent final : public wxEvent, public agi::Exception {
|
struct SubtitlesProviderErrorEvent final : public wxEvent, public agi::Exception {
|
||||||
const char * GetName() const override { return "subtitles/error"; }
|
|
||||||
wxEvent *Clone() const override { return new SubtitlesProviderErrorEvent(*this); };
|
wxEvent *Clone() const override { return new SubtitlesProviderErrorEvent(*this); };
|
||||||
agi::Exception *Copy() const override { return new SubtitlesProviderErrorEvent(*this); };
|
|
||||||
SubtitlesProviderErrorEvent(std::string const& msg);
|
SubtitlesProviderErrorEvent(std::string const& msg);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -46,7 +46,7 @@ AudioColorScheme::AudioColorScheme(int prec, std::string const& scheme_name, int
|
||||||
case AudioStyle_Inactive: opt_base += "Inactive/"; break;
|
case AudioStyle_Inactive: opt_base += "Inactive/"; break;
|
||||||
case AudioStyle_Selected: opt_base += "Selection/"; break;
|
case AudioStyle_Selected: opt_base += "Selection/"; break;
|
||||||
case AudioStyle_Primary: opt_base += "Primary/"; break;
|
case AudioStyle_Primary: opt_base += "Primary/"; break;
|
||||||
default: throw agi::InternalError("Unknown audio rendering styling", nullptr);
|
default: throw agi::InternalError("Unknown audio rendering styling");
|
||||||
}
|
}
|
||||||
|
|
||||||
double h_base = OPT_GET(opt_base + "Hue Offset")->GetDouble();
|
double h_base = OPT_GET(opt_base + "Hue Offset")->GetDouble();
|
||||||
|
|
|
@ -188,26 +188,26 @@ public:
|
||||||
|
|
||||||
namespace agi {
|
namespace agi {
|
||||||
/// Base class for all audio-related errors
|
/// Base class for all audio-related errors
|
||||||
DEFINE_BASE_EXCEPTION(AudioError, Exception)
|
DEFINE_EXCEPTION(AudioError, Exception);
|
||||||
|
|
||||||
/// Opening the audio failed for any reason
|
/// Opening the audio failed for any reason
|
||||||
DEFINE_SIMPLE_EXCEPTION(AudioOpenError, AudioError, "audio/open")
|
DEFINE_EXCEPTION(AudioOpenError, AudioError);
|
||||||
|
|
||||||
/// There are no audio providers available to open audio files
|
/// There are no audio providers available to open audio files
|
||||||
DEFINE_SIMPLE_EXCEPTION(NoAudioProvidersError, AudioOpenError, "audio/open/no_providers")
|
DEFINE_EXCEPTION(NoAudioProvidersError, AudioOpenError);
|
||||||
|
|
||||||
/// The file exists, but no providers could find any audio tracks in it
|
/// The file exists, but no providers could find any audio tracks in it
|
||||||
DEFINE_SIMPLE_EXCEPTION(AudioDataNotFoundError, AudioOpenError, "audio/open/no_tracks")
|
DEFINE_EXCEPTION(AudioDataNotFoundError, AudioOpenError);
|
||||||
|
|
||||||
/// There are audio tracks, but no provider could actually read them
|
/// There are audio tracks, but no provider could actually read them
|
||||||
DEFINE_SIMPLE_EXCEPTION(AudioProviderOpenError, AudioOpenError, "audio/open/provider")
|
DEFINE_EXCEPTION(AudioProviderOpenError, AudioOpenError);
|
||||||
|
|
||||||
/// The audio cache failed to initialize
|
/// The audio cache failed to initialize
|
||||||
DEFINE_SIMPLE_EXCEPTION(AudioCacheOpenError, AudioOpenError, "audio/open/cache")
|
DEFINE_EXCEPTION(AudioCacheOpenError, AudioOpenError);
|
||||||
|
|
||||||
/// There are no audio players available
|
/// There are no audio players available
|
||||||
DEFINE_SIMPLE_EXCEPTION(NoAudioPlayersError, AudioOpenError, "audio/open/no_players")
|
DEFINE_EXCEPTION(NoAudioPlayersError, AudioOpenError);
|
||||||
|
|
||||||
/// The audio player failed to initialize
|
/// The audio player failed to initialize
|
||||||
DEFINE_SIMPLE_EXCEPTION(AudioPlayerOpenError, AudioOpenError, "audio/open/player")
|
DEFINE_EXCEPTION(AudioPlayerOpenError, AudioOpenError);
|
||||||
}
|
}
|
||||||
|
|
|
@ -89,7 +89,7 @@ std::vector<std::string> AudioPlayerFactory::GetClasses() {
|
||||||
|
|
||||||
std::unique_ptr<AudioPlayer> AudioPlayerFactory::GetAudioPlayer(AudioProvider *provider, wxWindow *window) {
|
std::unique_ptr<AudioPlayer> AudioPlayerFactory::GetAudioPlayer(AudioProvider *provider, wxWindow *window) {
|
||||||
if (std::begin(factories) == std::end(factories))
|
if (std::begin(factories) == std::end(factories))
|
||||||
throw agi::NoAudioPlayersError("No audio players are available.", nullptr);
|
throw agi::NoAudioPlayersError("No audio players are available.");
|
||||||
|
|
||||||
auto preferred = OPT_GET("Audio/Player")->GetString();
|
auto preferred = OPT_GET("Audio/Player")->GetString();
|
||||||
auto sorted = GetSorted(boost::make_iterator_range(std::begin(factories), std::end(factories)), preferred);
|
auto sorted = GetSorted(boost::make_iterator_range(std::begin(factories), std::end(factories)), preferred);
|
||||||
|
@ -100,8 +100,8 @@ std::unique_ptr<AudioPlayer> AudioPlayerFactory::GetAudioPlayer(AudioProvider *p
|
||||||
return factory->create(provider, window);
|
return factory->create(provider, window);
|
||||||
}
|
}
|
||||||
catch (agi::AudioPlayerOpenError const& err) {
|
catch (agi::AudioPlayerOpenError const& err) {
|
||||||
error += std::string(factory->name) + " factory: " + err.GetChainedMessage() + "\n";
|
error += std::string(factory->name) + " factory: " + err.GetMessage() + "\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
throw agi::AudioPlayerOpenError(error, nullptr);
|
throw agi::AudioPlayerOpenError(error);
|
||||||
}
|
}
|
||||||
|
|
|
@ -295,7 +295,7 @@ AlsaPlayer::AlsaPlayer(AudioProvider *provider) try
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
catch (std::system_error const&) {
|
catch (std::system_error const&) {
|
||||||
throw agi::AudioPlayerOpenError("AlsaPlayer: Creating the playback thread failed", 0);
|
throw agi::AudioPlayerOpenError("AlsaPlayer: Creating the playback thread failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
AlsaPlayer::~AlsaPlayer()
|
AlsaPlayer::~AlsaPlayer()
|
||||||
|
|
|
@ -102,7 +102,7 @@ DirectSoundPlayer::DirectSoundPlayer(AudioProvider *provider, wxWindow *parent)
|
||||||
// Initialize the DirectSound object
|
// Initialize the DirectSound object
|
||||||
HRESULT res;
|
HRESULT res;
|
||||||
res = DirectSoundCreate8(&DSDEVID_DefaultPlayback,&directSound,nullptr); // TODO: support selecting audio device
|
res = DirectSoundCreate8(&DSDEVID_DefaultPlayback,&directSound,nullptr); // TODO: support selecting audio device
|
||||||
if (FAILED(res)) throw agi::AudioPlayerOpenError("Failed initializing DirectSound", 0);
|
if (FAILED(res)) throw agi::AudioPlayerOpenError("Failed initializing DirectSound");
|
||||||
|
|
||||||
// Set DirectSound parameters
|
// Set DirectSound parameters
|
||||||
directSound->SetCooperativeLevel((HWND)parent->GetHandle(),DSSCL_PRIORITY);
|
directSound->SetCooperativeLevel((HWND)parent->GetHandle(),DSSCL_PRIORITY);
|
||||||
|
@ -133,11 +133,11 @@ DirectSoundPlayer::DirectSoundPlayer(AudioProvider *provider, wxWindow *parent)
|
||||||
// Create the buffer
|
// Create the buffer
|
||||||
IDirectSoundBuffer *buf;
|
IDirectSoundBuffer *buf;
|
||||||
res = directSound->CreateSoundBuffer(&desc,&buf,nullptr);
|
res = directSound->CreateSoundBuffer(&desc,&buf,nullptr);
|
||||||
if (res != DS_OK) throw agi::AudioPlayerOpenError("Failed creating DirectSound buffer", 0);
|
if (res != DS_OK) throw agi::AudioPlayerOpenError("Failed creating DirectSound buffer");
|
||||||
|
|
||||||
// Copy interface to buffer
|
// Copy interface to buffer
|
||||||
res = buf->QueryInterface(IID_IDirectSoundBuffer8,(LPVOID*) &buffer);
|
res = buf->QueryInterface(IID_IDirectSoundBuffer8,(LPVOID*) &buffer);
|
||||||
if (res != S_OK) throw agi::AudioPlayerOpenError("Failed casting interface to IDirectSoundBuffer8", 0);
|
if (res != S_OK) throw agi::AudioPlayerOpenError("Failed casting interface to IDirectSoundBuffer8");
|
||||||
|
|
||||||
// Set data
|
// Set data
|
||||||
offset = 0;
|
offset = 0;
|
||||||
|
|
|
@ -677,7 +677,7 @@ DirectSoundPlayer2Thread::DirectSoundPlayer2Thread(AudioProvider *provider, int
|
||||||
thread_handle = (HANDLE)_beginthreadex(0, 0, ThreadProc, this, 0, 0);
|
thread_handle = (HANDLE)_beginthreadex(0, 0, ThreadProc, this, 0, 0);
|
||||||
|
|
||||||
if (!thread_handle)
|
if (!thread_handle)
|
||||||
throw agi::AudioPlayerOpenError("Failed creating playback thread in DirectSoundPlayer2. This is bad.", 0);
|
throw agi::AudioPlayerOpenError("Failed creating playback thread in DirectSoundPlayer2. This is bad.");
|
||||||
|
|
||||||
HANDLE running_or_error[] = { thread_running, error_happened };
|
HANDLE running_or_error[] = { thread_running, error_happened };
|
||||||
switch (WaitForMultipleObjects(2, running_or_error, FALSE, INFINITE))
|
switch (WaitForMultipleObjects(2, running_or_error, FALSE, INFINITE))
|
||||||
|
@ -688,10 +688,10 @@ DirectSoundPlayer2Thread::DirectSoundPlayer2Thread(AudioProvider *provider, int
|
||||||
|
|
||||||
case WAIT_OBJECT_0 + 1:
|
case WAIT_OBJECT_0 + 1:
|
||||||
// error happened, we fail
|
// error happened, we fail
|
||||||
throw agi::AudioPlayerOpenError(error_message, 0);
|
throw agi::AudioPlayerOpenError(error_message);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw agi::AudioPlayerOpenError("Failed wait for thread start or thread error in DirectSoundPlayer2. This is bad.", 0);
|
throw agi::AudioPlayerOpenError("Failed wait for thread start or thread error in DirectSoundPlayer2. This is bad.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -722,7 +722,7 @@ void DirectSoundPlayer2Thread::Play(int64_t start, int64_t count)
|
||||||
case WAIT_OBJECT_0+1: // Error
|
case WAIT_OBJECT_0+1: // Error
|
||||||
throw error_message;
|
throw error_message;
|
||||||
default:
|
default:
|
||||||
throw agi::InternalError("Unexpected result from WaitForMultipleObjects in DirectSoundPlayer2Thread::Play", 0);
|
throw agi::InternalError("Unexpected result from WaitForMultipleObjects in DirectSoundPlayer2Thread::Play");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -820,7 +820,7 @@ DirectSoundPlayer2::DirectSoundPlayer2(AudioProvider *provider, wxWindow *parent
|
||||||
catch (const char *msg)
|
catch (const char *msg)
|
||||||
{
|
{
|
||||||
LOG_E("audio/player/dsound") << msg;
|
LOG_E("audio/player/dsound") << msg;
|
||||||
throw agi::AudioPlayerOpenError(msg, 0);
|
throw agi::AudioPlayerOpenError(msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -61,7 +61,7 @@
|
||||||
#pragma comment(lib, "openal32.lib")
|
#pragma comment(lib, "openal32.lib")
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
DEFINE_SIMPLE_EXCEPTION(OpenALException, agi::AudioPlayerOpenError, "audio/open/player/openal")
|
DEFINE_EXCEPTION(OpenALException, agi::AudioPlayerOpenError);
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
class OpenALPlayer final : public AudioPlayer, wxTimer {
|
class OpenALPlayer final : public AudioPlayer, wxTimer {
|
||||||
|
@ -130,25 +130,25 @@ OpenALPlayer::OpenALPlayer(AudioProvider *provider)
|
||||||
try {
|
try {
|
||||||
// Open device
|
// Open device
|
||||||
device = alcOpenDevice(nullptr);
|
device = alcOpenDevice(nullptr);
|
||||||
if (!device) throw OpenALException("Failed opening default OpenAL device", nullptr);
|
if (!device) throw OpenALException("Failed opening default OpenAL device");
|
||||||
|
|
||||||
// Create context
|
// Create context
|
||||||
context = alcCreateContext(device, nullptr);
|
context = alcCreateContext(device, nullptr);
|
||||||
if (!context) throw OpenALException("Failed creating OpenAL context", nullptr);
|
if (!context) throw OpenALException("Failed creating OpenAL context");
|
||||||
if (!alcMakeContextCurrent(context)) throw OpenALException("Failed selecting OpenAL context", nullptr);
|
if (!alcMakeContextCurrent(context)) throw OpenALException("Failed selecting OpenAL context");
|
||||||
|
|
||||||
// Clear error code
|
// Clear error code
|
||||||
alGetError();
|
alGetError();
|
||||||
|
|
||||||
// Generate buffers
|
// Generate buffers
|
||||||
alGenBuffers(num_buffers, buffers);
|
alGenBuffers(num_buffers, buffers);
|
||||||
if (alGetError() != AL_NO_ERROR) throw OpenALException("Error generating OpenAL buffers", nullptr);
|
if (alGetError() != AL_NO_ERROR) throw OpenALException("Error generating OpenAL buffers");
|
||||||
|
|
||||||
// Generate source
|
// Generate source
|
||||||
alGenSources(1, &source);
|
alGenSources(1, &source);
|
||||||
if (alGetError() != AL_NO_ERROR) {
|
if (alGetError() != AL_NO_ERROR) {
|
||||||
alDeleteBuffers(num_buffers, buffers);
|
alDeleteBuffers(num_buffers, buffers);
|
||||||
throw OpenALException("Error generating OpenAL source", nullptr);
|
throw OpenALException("Error generating OpenAL source");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (...)
|
catch (...)
|
||||||
|
|
|
@ -54,7 +54,7 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
DEFINE_SIMPLE_EXCEPTION(OSSError, agi::AudioPlayerOpenError, "audio/player/open/oss")
|
DEFINE_EXCEPTION(OSSError, agi::AudioPlayerOpenError);
|
||||||
class OSSPlayerThread;
|
class OSSPlayerThread;
|
||||||
|
|
||||||
class OSSPlayer final : public AudioPlayer {
|
class OSSPlayer final : public AudioPlayer {
|
||||||
|
@ -153,7 +153,7 @@ void OSSPlayer::OpenStream()
|
||||||
wxString device = to_wx(OPT_GET("Player/Audio/OSS/Device")->GetString());
|
wxString device = to_wx(OPT_GET("Player/Audio/OSS/Device")->GetString());
|
||||||
dspdev = ::open(device.utf8_str(), O_WRONLY, 0);
|
dspdev = ::open(device.utf8_str(), O_WRONLY, 0);
|
||||||
if (dspdev < 0) {
|
if (dspdev < 0) {
|
||||||
throw OSSError("OSS player: opening device failed", 0);
|
throw OSSError("OSS player: opening device failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use a reasonable buffer policy for low latency (OSS4)
|
// Use a reasonable buffer policy for low latency (OSS4)
|
||||||
|
@ -165,7 +165,7 @@ void OSSPlayer::OpenStream()
|
||||||
// Set number of channels
|
// Set number of channels
|
||||||
int channels = provider->GetChannels();
|
int channels = provider->GetChannels();
|
||||||
if (ioctl(dspdev, SNDCTL_DSP_CHANNELS, &channels) < 0) {
|
if (ioctl(dspdev, SNDCTL_DSP_CHANNELS, &channels) < 0) {
|
||||||
throw OSSError("OSS player: setting channels failed", 0);
|
throw OSSError("OSS player: setting channels failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set sample format
|
// Set sample format
|
||||||
|
@ -178,17 +178,17 @@ void OSSPlayer::OpenStream()
|
||||||
sample_format = AFMT_S16_LE;
|
sample_format = AFMT_S16_LE;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw OSSError("OSS player: can only handle 8 and 16 bit sound", 0);
|
throw OSSError("OSS player: can only handle 8 and 16 bit sound");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ioctl(dspdev, SNDCTL_DSP_SETFMT, &sample_format) < 0) {
|
if (ioctl(dspdev, SNDCTL_DSP_SETFMT, &sample_format) < 0) {
|
||||||
throw OSSError("OSS player: setting sample format failed", 0);
|
throw OSSError("OSS player: setting sample format failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set sample rate
|
// Set sample rate
|
||||||
rate = provider->GetSampleRate();
|
rate = provider->GetSampleRate();
|
||||||
if (ioctl(dspdev, SNDCTL_DSP_SPEED, &rate) < 0) {
|
if (ioctl(dspdev, SNDCTL_DSP_SPEED, &rate) < 0) {
|
||||||
throw OSSError("OSS player: setting samplerate failed", 0);
|
throw OSSError("OSS player: setting samplerate failed");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -44,7 +44,7 @@
|
||||||
#include <libaegisub/log.h>
|
#include <libaegisub/log.h>
|
||||||
#include <libaegisub/make_unique.h>
|
#include <libaegisub/make_unique.h>
|
||||||
|
|
||||||
DEFINE_SIMPLE_EXCEPTION(PortAudioError, agi::AudioPlayerOpenError, "audio/player/open/portaudio")
|
DEFINE_EXCEPTION(PortAudioError, agi::AudioPlayerOpenError);
|
||||||
|
|
||||||
// Uncomment to enable extremely spammy debug logging
|
// Uncomment to enable extremely spammy debug logging
|
||||||
//#define PORTAUDIO_DEBUG
|
//#define PORTAUDIO_DEBUG
|
||||||
|
|
|
@ -101,7 +101,7 @@ PulseAudioPlayer::PulseAudioPlayer(AudioProvider *provider) : AudioPlayer(provid
|
||||||
// Initialise a mainloop
|
// Initialise a mainloop
|
||||||
mainloop = pa_threaded_mainloop_new();
|
mainloop = pa_threaded_mainloop_new();
|
||||||
if (!mainloop)
|
if (!mainloop)
|
||||||
throw agi::AudioPlayerOpenError("Failed to initialise PulseAudio threaded mainloop object", 0);
|
throw agi::AudioPlayerOpenError("Failed to initialise PulseAudio threaded mainloop object");
|
||||||
|
|
||||||
pa_threaded_mainloop_start(mainloop);
|
pa_threaded_mainloop_start(mainloop);
|
||||||
|
|
||||||
|
@ -109,7 +109,7 @@ PulseAudioPlayer::PulseAudioPlayer(AudioProvider *provider) : AudioPlayer(provid
|
||||||
context = pa_context_new(pa_threaded_mainloop_get_api(mainloop), "Aegisub");
|
context = pa_context_new(pa_threaded_mainloop_get_api(mainloop), "Aegisub");
|
||||||
if (!context) {
|
if (!context) {
|
||||||
pa_threaded_mainloop_free(mainloop);
|
pa_threaded_mainloop_free(mainloop);
|
||||||
throw agi::AudioPlayerOpenError("Failed to create PulseAudio context", 0);
|
throw agi::AudioPlayerOpenError("Failed to create PulseAudio context");
|
||||||
}
|
}
|
||||||
pa_context_set_state_callback(context, (pa_context_notify_cb_t)pa_context_notify, this);
|
pa_context_set_state_callback(context, (pa_context_notify_cb_t)pa_context_notify, this);
|
||||||
|
|
||||||
|
@ -127,7 +127,7 @@ PulseAudioPlayer::PulseAudioPlayer(AudioProvider *provider) : AudioPlayer(provid
|
||||||
pa_context_unref(context);
|
pa_context_unref(context);
|
||||||
pa_threaded_mainloop_stop(mainloop);
|
pa_threaded_mainloop_stop(mainloop);
|
||||||
pa_threaded_mainloop_free(mainloop);
|
pa_threaded_mainloop_free(mainloop);
|
||||||
throw agi::AudioPlayerOpenError(std::string("PulseAudio reported error: ") + pa_strerror(paerror), 0);
|
throw agi::AudioPlayerOpenError(std::string("PulseAudio reported error: ") + pa_strerror(paerror));
|
||||||
}
|
}
|
||||||
// otherwise loop once more
|
// otherwise loop once more
|
||||||
}
|
}
|
||||||
|
@ -148,7 +148,7 @@ PulseAudioPlayer::PulseAudioPlayer(AudioProvider *provider) : AudioPlayer(provid
|
||||||
pa_context_unref(context);
|
pa_context_unref(context);
|
||||||
pa_threaded_mainloop_stop(mainloop);
|
pa_threaded_mainloop_stop(mainloop);
|
||||||
pa_threaded_mainloop_free(mainloop);
|
pa_threaded_mainloop_free(mainloop);
|
||||||
throw agi::AudioPlayerOpenError("PulseAudio could not create stream", 0);
|
throw agi::AudioPlayerOpenError("PulseAudio could not create stream");
|
||||||
}
|
}
|
||||||
pa_stream_set_state_callback(stream, (pa_stream_notify_cb_t)pa_stream_notify, this);
|
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);
|
pa_stream_set_write_callback(stream, (pa_stream_request_cb_t)pa_stream_write, this);
|
||||||
|
@ -157,7 +157,7 @@ PulseAudioPlayer::PulseAudioPlayer(AudioProvider *provider) : AudioPlayer(provid
|
||||||
paerror = pa_stream_connect_playback(stream, nullptr, nullptr, (pa_stream_flags_t)(PA_STREAM_INTERPOLATE_TIMING|PA_STREAM_NOT_MONOTONOUS|PA_STREAM_AUTO_TIMING_UPDATE), nullptr, nullptr);
|
paerror = pa_stream_connect_playback(stream, nullptr, nullptr, (pa_stream_flags_t)(PA_STREAM_INTERPOLATE_TIMING|PA_STREAM_NOT_MONOTONOUS|PA_STREAM_AUTO_TIMING_UPDATE), nullptr, nullptr);
|
||||||
if (paerror) {
|
if (paerror) {
|
||||||
LOG_E("audio/player/pulse") << "Stream connection failed: " << pa_strerror(paerror) << "(" << paerror << ")";
|
LOG_E("audio/player/pulse") << "Stream connection failed: " << pa_strerror(paerror) << "(" << paerror << ")";
|
||||||
throw agi::AudioPlayerOpenError(std::string("PulseAudio reported error: ") + pa_strerror(paerror), 0);
|
throw agi::AudioPlayerOpenError(std::string("PulseAudio reported error: ") + pa_strerror(paerror));
|
||||||
}
|
}
|
||||||
while (true) {
|
while (true) {
|
||||||
stream_notify.Wait();
|
stream_notify.Wait();
|
||||||
|
@ -166,7 +166,7 @@ PulseAudioPlayer::PulseAudioPlayer(AudioProvider *provider) : AudioPlayer(provid
|
||||||
} else if (sstate == PA_STREAM_FAILED) {
|
} else if (sstate == PA_STREAM_FAILED) {
|
||||||
paerror = pa_context_errno(context);
|
paerror = pa_context_errno(context);
|
||||||
LOG_E("audio/player/pulse") << "Stream connection failed: " << pa_strerror(paerror) << "(" << paerror << ")";
|
LOG_E("audio/player/pulse") << "Stream connection failed: " << pa_strerror(paerror) << "(" << paerror << ")";
|
||||||
throw agi::AudioPlayerOpenError("PulseAudio player: Something went wrong connecting the stream", 0);
|
throw agi::AudioPlayerOpenError("PulseAudio player: Something went wrong connecting the stream");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,7 +44,7 @@ void AudioProvider::GetAudioWithVolume(void *buf, int64_t start, int64_t count,
|
||||||
|
|
||||||
if (volume == 1.0) return;
|
if (volume == 1.0) return;
|
||||||
if (bytes_per_sample != 2)
|
if (bytes_per_sample != 2)
|
||||||
throw agi::InternalError("GetAudioWithVolume called on unconverted audio stream", nullptr);
|
throw agi::InternalError("GetAudioWithVolume called on unconverted audio stream");
|
||||||
|
|
||||||
short *buffer = static_cast<int16_t *>(buf);
|
short *buffer = static_cast<int16_t *>(buf);
|
||||||
for (size_t i = 0; i < (size_t)count; ++i)
|
for (size_t i = 0; i < (size_t)count; ++i)
|
||||||
|
@ -80,7 +80,7 @@ void AudioProvider::GetAudio(void *buf, int64_t start, int64_t count) const {
|
||||||
FillBuffer(buf, start, count);
|
FillBuffer(buf, start, count);
|
||||||
}
|
}
|
||||||
catch (AudioDecodeError const& e) {
|
catch (AudioDecodeError const& e) {
|
||||||
LOG_E("audio_provider") << e.GetChainedMessage();
|
LOG_E("audio_provider") << e.GetMessage();
|
||||||
ZeroFill(buf, count);
|
ZeroFill(buf, count);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -144,19 +144,19 @@ std::unique_ptr<AudioProvider> AudioProviderFactory::GetProvider(agi::fs::path c
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
catch (agi::fs::FileNotFound const& err) {
|
catch (agi::fs::FileNotFound const& err) {
|
||||||
LOG_D("audio_provider") << err.GetChainedMessage();
|
LOG_D("audio_provider") << err.GetMessage();
|
||||||
msg_all += std::string(factory->name) + ": " + err.GetMessage() + " not found.\n";
|
msg_all += std::string(factory->name) + ": " + err.GetMessage() + " not found.\n";
|
||||||
}
|
}
|
||||||
catch (agi::AudioDataNotFoundError const& err) {
|
catch (agi::AudioDataNotFoundError const& err) {
|
||||||
LOG_D("audio_provider") << err.GetChainedMessage();
|
LOG_D("audio_provider") << err.GetMessage();
|
||||||
found_file = true;
|
found_file = true;
|
||||||
msg_all += std::string(factory->name) + ": " + err.GetChainedMessage() + "\n";
|
msg_all += std::string(factory->name) + ": " + err.GetMessage() + "\n";
|
||||||
}
|
}
|
||||||
catch (agi::AudioOpenError const& err) {
|
catch (agi::AudioOpenError const& err) {
|
||||||
LOG_D("audio_provider") << err.GetChainedMessage();
|
LOG_D("audio_provider") << err.GetMessage();
|
||||||
found_audio = true;
|
found_audio = true;
|
||||||
found_file = true;
|
found_file = true;
|
||||||
std::string thismsg = std::string(factory->name) + ": " + err.GetChainedMessage() + "\n";
|
std::string thismsg = std::string(factory->name) + ": " + err.GetMessage() + "\n";
|
||||||
msg_all += thismsg;
|
msg_all += thismsg;
|
||||||
msg_partial += thismsg;
|
msg_partial += thismsg;
|
||||||
}
|
}
|
||||||
|
@ -164,9 +164,9 @@ std::unique_ptr<AudioProvider> AudioProviderFactory::GetProvider(agi::fs::path c
|
||||||
|
|
||||||
if (!provider) {
|
if (!provider) {
|
||||||
if (found_audio)
|
if (found_audio)
|
||||||
throw agi::AudioProviderOpenError(msg_partial, nullptr);
|
throw agi::AudioProviderOpenError(msg_partial);
|
||||||
if (found_file)
|
if (found_file)
|
||||||
throw agi::AudioDataNotFoundError(msg_all, nullptr);
|
throw agi::AudioDataNotFoundError(msg_all);
|
||||||
throw agi::fs::FileNotFound(filename);
|
throw agi::fs::FileNotFound(filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -187,5 +187,5 @@ std::unique_ptr<AudioProvider> AudioProviderFactory::GetProvider(agi::fs::path c
|
||||||
// Convert to HD
|
// Convert to HD
|
||||||
if (cache == 2) return CreateHDAudioProvider(std::move(provider));
|
if (cache == 2) return CreateHDAudioProvider(std::move(provider));
|
||||||
|
|
||||||
throw agi::AudioCacheOpenError("Unknown caching method", nullptr);
|
throw agi::AudioCacheOpenError("Unknown caching method");
|
||||||
}
|
}
|
||||||
|
|
|
@ -89,22 +89,22 @@ AvisynthAudioProvider::AvisynthAudioProvider(agi::fs::path const& filename) {
|
||||||
LoadFromClip(env->Invoke("DirectShowSource", AVSValue(args, 3), argnames));
|
LoadFromClip(env->Invoke("DirectShowSource", AVSValue(args, 3), argnames));
|
||||||
// Otherwise fail
|
// Otherwise fail
|
||||||
else
|
else
|
||||||
throw agi::AudioProviderOpenError("No suitable audio source filter found. Try placing DirectShowSource.dll in the Aegisub application directory.", 0);
|
throw agi::AudioProviderOpenError("No suitable audio source filter found. Try placing DirectShowSource.dll in the Aegisub application directory.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (AvisynthError &err) {
|
catch (AvisynthError &err) {
|
||||||
std::string errmsg(err.msg);
|
std::string errmsg(err.msg);
|
||||||
if (errmsg.find("filter graph manager won't talk to me") != errmsg.npos)
|
if (errmsg.find("filter graph manager won't talk to me") != errmsg.npos)
|
||||||
throw agi::AudioDataNotFoundError("Avisynth error: " + errmsg, 0);
|
throw agi::AudioDataNotFoundError("Avisynth error: " + errmsg);
|
||||||
else
|
else
|
||||||
throw agi::AudioProviderOpenError("Avisynth error: " + errmsg, 0);
|
throw agi::AudioProviderOpenError("Avisynth error: " + errmsg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AvisynthAudioProvider::LoadFromClip(AVSValue clip) {
|
void AvisynthAudioProvider::LoadFromClip(AVSValue clip) {
|
||||||
// Check if it has audio
|
// Check if it has audio
|
||||||
VideoInfo vi = clip.AsClip()->GetVideoInfo();
|
VideoInfo vi = clip.AsClip()->GetVideoInfo();
|
||||||
if (!vi.HasAudio()) throw agi::AudioDataNotFoundError("No audio found.", 0);
|
if (!vi.HasAudio()) throw agi::AudioDataNotFoundError("No audio found.");
|
||||||
|
|
||||||
IScriptEnvironment *env = avs_wrapper.GetEnv();
|
IScriptEnvironment *env = avs_wrapper.GetEnv();
|
||||||
|
|
||||||
|
|
|
@ -35,7 +35,7 @@ class BitdepthConvertAudioProvider final : public AudioProviderWrapper {
|
||||||
public:
|
public:
|
||||||
BitdepthConvertAudioProvider(std::unique_ptr<AudioProvider> src) : AudioProviderWrapper(std::move(src)) {
|
BitdepthConvertAudioProvider(std::unique_ptr<AudioProvider> src) : AudioProviderWrapper(std::move(src)) {
|
||||||
if (bytes_per_sample > 8)
|
if (bytes_per_sample > 8)
|
||||||
throw agi::AudioProviderOpenError("Audio format converter: audio with bitdepths greater than 64 bits/sample is currently unsupported", nullptr);
|
throw agi::AudioProviderOpenError("Audio format converter: audio with bitdepths greater than 64 bits/sample is currently unsupported");
|
||||||
|
|
||||||
src_bytes_per_sample = bytes_per_sample;
|
src_bytes_per_sample = bytes_per_sample;
|
||||||
bytes_per_sample = sizeof(Target);
|
bytes_per_sample = sizeof(Target);
|
||||||
|
@ -107,9 +107,9 @@ class DownmixAudioProvider final : public AudioProviderWrapper {
|
||||||
public:
|
public:
|
||||||
DownmixAudioProvider(std::unique_ptr<AudioProvider> src) : AudioProviderWrapper(std::move(src)) {
|
DownmixAudioProvider(std::unique_ptr<AudioProvider> src) : AudioProviderWrapper(std::move(src)) {
|
||||||
if (bytes_per_sample != 2)
|
if (bytes_per_sample != 2)
|
||||||
throw agi::InternalError("DownmixAudioProvider requires 16-bit input", nullptr);
|
throw agi::InternalError("DownmixAudioProvider requires 16-bit input");
|
||||||
if (channels == 1)
|
if (channels == 1)
|
||||||
throw agi::InternalError("DownmixAudioProvider requires multi-channel input", nullptr);
|
throw agi::InternalError("DownmixAudioProvider requires multi-channel input");
|
||||||
src_channels = channels;
|
src_channels = channels;
|
||||||
channels = 1;
|
channels = 1;
|
||||||
}
|
}
|
||||||
|
@ -137,9 +137,9 @@ class SampleDoublingAudioProvider final : public AudioProviderWrapper {
|
||||||
public:
|
public:
|
||||||
SampleDoublingAudioProvider(std::unique_ptr<AudioProvider> src) : AudioProviderWrapper(std::move(src)) {
|
SampleDoublingAudioProvider(std::unique_ptr<AudioProvider> src) : AudioProviderWrapper(std::move(src)) {
|
||||||
if (source->GetBytesPerSample() != 2)
|
if (source->GetBytesPerSample() != 2)
|
||||||
throw agi::InternalError("UpsampleAudioProvider requires 16-bit input", nullptr);
|
throw agi::InternalError("UpsampleAudioProvider requires 16-bit input");
|
||||||
if (source->GetChannels() != 1)
|
if (source->GetChannels() != 1)
|
||||||
throw agi::InternalError("UpsampleAudioProvider requires mono input", nullptr);
|
throw agi::InternalError("UpsampleAudioProvider requires mono input");
|
||||||
|
|
||||||
sample_rate *= 2;
|
sample_rate *= 2;
|
||||||
num_samples *= 2;
|
num_samples *= 2;
|
||||||
|
|
|
@ -79,10 +79,10 @@ FFmpegSourceAudioProvider::FFmpegSourceAudioProvider(agi::fs::path const& filena
|
||||||
LoadAudio(filename);
|
LoadAudio(filename);
|
||||||
}
|
}
|
||||||
catch (std::string const& err) {
|
catch (std::string const& err) {
|
||||||
throw agi::AudioProviderOpenError(err, nullptr);
|
throw agi::AudioProviderOpenError(err);
|
||||||
}
|
}
|
||||||
catch (const char *err) {
|
catch (const char *err) {
|
||||||
throw agi::AudioProviderOpenError(err, nullptr);
|
throw agi::AudioProviderOpenError(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FFmpegSourceAudioProvider::LoadAudio(agi::fs::path const& filename) {
|
void FFmpegSourceAudioProvider::LoadAudio(agi::fs::path const& filename) {
|
||||||
|
@ -91,12 +91,12 @@ void FFmpegSourceAudioProvider::LoadAudio(agi::fs::path const& filename) {
|
||||||
if (ErrInfo.SubType == FFMS_ERROR_FILE_READ)
|
if (ErrInfo.SubType == FFMS_ERROR_FILE_READ)
|
||||||
throw agi::fs::FileNotFound(std::string(ErrInfo.Buffer));
|
throw agi::fs::FileNotFound(std::string(ErrInfo.Buffer));
|
||||||
else
|
else
|
||||||
throw agi::AudioDataNotFoundError(ErrInfo.Buffer, nullptr);
|
throw agi::AudioDataNotFoundError(ErrInfo.Buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::map<int, std::string> TrackList = GetTracksOfType(Indexer, FFMS_TYPE_AUDIO);
|
std::map<int, std::string> TrackList = GetTracksOfType(Indexer, FFMS_TYPE_AUDIO);
|
||||||
if (TrackList.empty())
|
if (TrackList.empty())
|
||||||
throw agi::AudioDataNotFoundError("no audio tracks found", nullptr);
|
throw agi::AudioDataNotFoundError("no audio tracks found");
|
||||||
|
|
||||||
// initialize the track number to an invalid value so we can detect later on
|
// 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
|
// whether the user actually had to choose a track or not
|
||||||
|
@ -124,7 +124,7 @@ void FFmpegSourceAudioProvider::LoadAudio(agi::fs::path const& filename) {
|
||||||
if (TrackNumber < 0)
|
if (TrackNumber < 0)
|
||||||
TrackNumber = FFMS_GetFirstTrackOfType(Index, FFMS_TYPE_AUDIO, &ErrInfo);
|
TrackNumber = FFMS_GetFirstTrackOfType(Index, FFMS_TYPE_AUDIO, &ErrInfo);
|
||||||
if (TrackNumber < 0)
|
if (TrackNumber < 0)
|
||||||
throw agi::AudioDataNotFoundError(std::string("Couldn't find any audio tracks: ") + ErrInfo.Buffer, nullptr);
|
throw agi::AudioDataNotFoundError(std::string("Couldn't find any audio tracks: ") + ErrInfo.Buffer);
|
||||||
|
|
||||||
// index is valid and track number is now set,
|
// index is valid and track number is now set,
|
||||||
// but do we have indexing info for the desired audio track?
|
// but do we have indexing info for the desired audio track?
|
||||||
|
@ -166,7 +166,7 @@ void FFmpegSourceAudioProvider::LoadAudio(agi::fs::path const& filename) {
|
||||||
|
|
||||||
AudioSource = FFMS_CreateAudioSource(filename.string().c_str(), TrackNumber, Index, -1, &ErrInfo);
|
AudioSource = FFMS_CreateAudioSource(filename.string().c_str(), TrackNumber, Index, -1, &ErrInfo);
|
||||||
if (!AudioSource)
|
if (!AudioSource)
|
||||||
throw agi::AudioProviderOpenError(std::string("Failed to open audio track: ") + ErrInfo.Buffer, nullptr);
|
throw agi::AudioProviderOpenError(std::string("Failed to open audio track: ") + ErrInfo.Buffer);
|
||||||
|
|
||||||
const FFMS_AudioProperties AudioInfo = *FFMS_GetAudioProperties(AudioSource);
|
const FFMS_AudioProperties AudioInfo = *FFMS_GetAudioProperties(AudioSource);
|
||||||
|
|
||||||
|
@ -175,7 +175,7 @@ void FFmpegSourceAudioProvider::LoadAudio(agi::fs::path const& filename) {
|
||||||
num_samples = AudioInfo.NumSamples;
|
num_samples = AudioInfo.NumSamples;
|
||||||
decoded_samples = AudioInfo.NumSamples;
|
decoded_samples = AudioInfo.NumSamples;
|
||||||
if (channels <= 0 || sample_rate <= 0 || num_samples <= 0)
|
if (channels <= 0 || sample_rate <= 0 || num_samples <= 0)
|
||||||
throw agi::AudioProviderOpenError("sanity check failed, consult your local psychiatrist", nullptr);
|
throw agi::AudioProviderOpenError("sanity check failed, consult your local psychiatrist");
|
||||||
|
|
||||||
switch (AudioInfo.SampleFormat) {
|
switch (AudioInfo.SampleFormat) {
|
||||||
case FFMS_FMT_U8: bytes_per_sample = 1; float_samples = false; break;
|
case FFMS_FMT_U8: bytes_per_sample = 1; float_samples = false; break;
|
||||||
|
@ -184,7 +184,7 @@ void FFmpegSourceAudioProvider::LoadAudio(agi::fs::path const& filename) {
|
||||||
case FFMS_FMT_FLT: bytes_per_sample = 4; float_samples = true; break;
|
case FFMS_FMT_FLT: bytes_per_sample = 4; float_samples = true; break;
|
||||||
case FFMS_FMT_DBL: bytes_per_sample = 8; float_samples = true; break;
|
case FFMS_FMT_DBL: bytes_per_sample = 8; float_samples = true; break;
|
||||||
default:
|
default:
|
||||||
throw agi::AudioProviderOpenError("unknown or unsupported sample format", nullptr);
|
throw agi::AudioProviderOpenError("unknown or unsupported sample format");
|
||||||
}
|
}
|
||||||
|
|
||||||
#if FFMS_VERSION >= ((2 << 24) | (17 << 16) | (4 << 8) | 0)
|
#if FFMS_VERSION >= ((2 << 24) | (17 << 16) | (4 << 8) | 0)
|
||||||
|
|
|
@ -62,7 +62,7 @@ public:
|
||||||
|
|
||||||
// Check free space
|
// Check free space
|
||||||
if ((uint64_t)num_samples * bytes_per_sample > agi::fs::FreeSpace(cache_dir))
|
if ((uint64_t)num_samples * bytes_per_sample > agi::fs::FreeSpace(cache_dir))
|
||||||
throw agi::AudioCacheOpenError("Not enough free disk space in " + cache_dir.string() + " to cache the audio", nullptr);
|
throw agi::AudioCacheOpenError("Not enough free disk space in " + cache_dir.string() + " to cache the audio");
|
||||||
|
|
||||||
auto filename = agi::format("audio-%lld-%lld", time(nullptr),
|
auto filename = agi::format("audio-%lld-%lld", time(nullptr),
|
||||||
boost::interprocess::ipcdetail::get_current_process_id());
|
boost::interprocess::ipcdetail::get_current_process_id());
|
||||||
|
|
|
@ -155,9 +155,9 @@ public:
|
||||||
|
|
||||||
// Check magic values
|
// Check magic values
|
||||||
if (!CheckFourcc(header.ch.type, "RIFF"))
|
if (!CheckFourcc(header.ch.type, "RIFF"))
|
||||||
throw agi::AudioDataNotFoundError("File is not a RIFF file", nullptr);
|
throw agi::AudioDataNotFoundError("File is not a RIFF file");
|
||||||
if (!CheckFourcc(header.format, "WAVE"))
|
if (!CheckFourcc(header.format, "WAVE"))
|
||||||
throw agi::AudioDataNotFoundError("File is not a RIFF WAV file", nullptr);
|
throw agi::AudioDataNotFoundError("File is not a RIFF WAV file");
|
||||||
|
|
||||||
// How far into the file we have processed.
|
// How far into the file we have processed.
|
||||||
// Must be incremented by the riff chunk size fields.
|
// Must be incremented by the riff chunk size fields.
|
||||||
|
@ -177,13 +177,13 @@ public:
|
||||||
filepos += sizeof(ch);
|
filepos += sizeof(ch);
|
||||||
|
|
||||||
if (CheckFourcc(ch.type, "fmt ")) {
|
if (CheckFourcc(ch.type, "fmt ")) {
|
||||||
if (got_fmt_header) throw agi::AudioProviderOpenError("Invalid file, multiple 'fmt ' chunks", nullptr);
|
if (got_fmt_header) throw agi::AudioProviderOpenError("Invalid file, multiple 'fmt ' chunks");
|
||||||
got_fmt_header = true;
|
got_fmt_header = true;
|
||||||
|
|
||||||
auto const& fmt = Read<fmtChunk>(filepos);
|
auto const& fmt = Read<fmtChunk>(filepos);
|
||||||
|
|
||||||
if (fmt.compression != 1)
|
if (fmt.compression != 1)
|
||||||
throw agi::AudioProviderOpenError("Can't use file, not PCM encoding", nullptr);
|
throw agi::AudioProviderOpenError("Can't use file, not PCM encoding");
|
||||||
|
|
||||||
// Set stuff inherited from the AudioProvider class
|
// Set stuff inherited from the AudioProvider class
|
||||||
sample_rate = fmt.samplerate;
|
sample_rate = fmt.samplerate;
|
||||||
|
@ -194,7 +194,7 @@ public:
|
||||||
// This won't pick up 'data' chunks inside 'wavl' chunks
|
// This won't pick up 'data' chunks inside 'wavl' chunks
|
||||||
// since the 'wavl' chunks wrap those.
|
// since the 'wavl' chunks wrap those.
|
||||||
|
|
||||||
if (!got_fmt_header) throw agi::AudioProviderOpenError("Found 'data' chunk before 'fmt ' chunk, file is invalid.", nullptr);
|
if (!got_fmt_header) throw agi::AudioProviderOpenError("Found 'data' chunk before 'fmt ' chunk, file is invalid.");
|
||||||
|
|
||||||
auto samples = std::min(total_data - filepos, ch.size) / bytes_per_sample / channels;
|
auto samples = std::min(total_data - filepos, ch.size) / bytes_per_sample / channels;
|
||||||
index_points.push_back(IndexPoint{filepos, samples});
|
index_points.push_back(IndexPoint{filepos, samples});
|
||||||
|
@ -280,16 +280,16 @@ public:
|
||||||
size_t smallest_possible_file = sizeof(RiffChunk) + sizeof(FormatChunk) + sizeof(DataChunk);
|
size_t smallest_possible_file = sizeof(RiffChunk) + sizeof(FormatChunk) + sizeof(DataChunk);
|
||||||
|
|
||||||
if (file->size() < smallest_possible_file)
|
if (file->size() < smallest_possible_file)
|
||||||
throw agi::AudioDataNotFoundError("File is too small to be a Wave64 file", nullptr);
|
throw agi::AudioDataNotFoundError("File is too small to be a Wave64 file");
|
||||||
|
|
||||||
// Read header
|
// Read header
|
||||||
auto const& header = Read<RiffChunk>(0);
|
auto const& header = Read<RiffChunk>(0);
|
||||||
|
|
||||||
// Check magic values
|
// Check magic values
|
||||||
if (!CheckGuid(header.riff_guid, w64GuidRIFF))
|
if (!CheckGuid(header.riff_guid, w64GuidRIFF))
|
||||||
throw agi::AudioDataNotFoundError("File is not a Wave64 RIFF file", nullptr);
|
throw agi::AudioDataNotFoundError("File is not a Wave64 RIFF file");
|
||||||
if (!CheckGuid(header.format_guid, w64GuidWAVE))
|
if (!CheckGuid(header.format_guid, w64GuidWAVE))
|
||||||
throw agi::AudioDataNotFoundError("File is not a Wave64 WAVE file", nullptr);
|
throw agi::AudioDataNotFoundError("File is not a Wave64 WAVE file");
|
||||||
|
|
||||||
// How far into the file we have processed.
|
// How far into the file we have processed.
|
||||||
// Must be incremented by the riff chunk size fields.
|
// Must be incremented by the riff chunk size fields.
|
||||||
|
@ -310,11 +310,11 @@ public:
|
||||||
|
|
||||||
if (CheckGuid(chunk_guid, w64Guidfmt)) {
|
if (CheckGuid(chunk_guid, w64Guidfmt)) {
|
||||||
if (got_fmt_header)
|
if (got_fmt_header)
|
||||||
throw agi::AudioProviderOpenError("Bad file, found more than one 'fmt' chunk", nullptr);
|
throw agi::AudioProviderOpenError("Bad file, found more than one 'fmt' chunk");
|
||||||
|
|
||||||
auto const& fmt = Read<FormatChunk>(filepos);
|
auto const& fmt = Read<FormatChunk>(filepos);
|
||||||
if (fmt.format.wFormatTag != 1)
|
if (fmt.format.wFormatTag != 1)
|
||||||
throw agi::AudioProviderOpenError("File is not uncompressed PCM", nullptr);
|
throw agi::AudioProviderOpenError("File is not uncompressed PCM");
|
||||||
|
|
||||||
got_fmt_header = true;
|
got_fmt_header = true;
|
||||||
// Set stuff inherited from the AudioProvider class
|
// Set stuff inherited from the AudioProvider class
|
||||||
|
@ -324,7 +324,7 @@ public:
|
||||||
}
|
}
|
||||||
else if (CheckGuid(chunk_guid, w64Guiddata)) {
|
else if (CheckGuid(chunk_guid, w64Guiddata)) {
|
||||||
if (!got_fmt_header)
|
if (!got_fmt_header)
|
||||||
throw agi::AudioProviderOpenError("Found 'data' chunk before 'fmt ' chunk, file is invalid.", nullptr);
|
throw agi::AudioProviderOpenError("Found 'data' chunk before 'fmt ' chunk, file is invalid.");
|
||||||
|
|
||||||
auto samples = chunk_size / bytes_per_sample / channels;
|
auto samples = chunk_size / bytes_per_sample / channels;
|
||||||
index_points.push_back(IndexPoint{
|
index_points.push_back(IndexPoint{
|
||||||
|
@ -369,7 +369,7 @@ std::unique_ptr<AudioProvider> CreatePCMAudioProvider(agi::fs::path const& filen
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wrong_file_type)
|
if (wrong_file_type)
|
||||||
throw agi::AudioDataNotFoundError(msg, nullptr);
|
throw agi::AudioDataNotFoundError(msg);
|
||||||
else
|
else
|
||||||
throw agi::AudioProviderOpenError(msg, nullptr);
|
throw agi::AudioProviderOpenError(msg);
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,7 +68,7 @@ public:
|
||||||
blockcache.resize((source->GetNumSamples() * source->GetBytesPerSample() + CacheBlockSize - 1) >> CacheBits);
|
blockcache.resize((source->GetNumSamples() * source->GetBytesPerSample() + CacheBlockSize - 1) >> CacheBits);
|
||||||
}
|
}
|
||||||
catch (std::bad_alloc const&) {
|
catch (std::bad_alloc const&) {
|
||||||
throw agi::AudioCacheOpenError("Couldn't open audio, not enough ram available.", nullptr);
|
throw agi::AudioCacheOpenError("Couldn't open audio, not enough ram available.");
|
||||||
}
|
}
|
||||||
|
|
||||||
decoder = std::thread([&] {
|
decoder = std::thread([&] {
|
||||||
|
|
|
@ -446,7 +446,7 @@ namespace Automation4 {
|
||||||
void ScriptFactory::Register(std::unique_ptr<ScriptFactory> factory)
|
void ScriptFactory::Register(std::unique_ptr<ScriptFactory> factory)
|
||||||
{
|
{
|
||||||
if (find(Factories().begin(), Factories().end(), factory) != Factories().end())
|
if (find(Factories().begin(), Factories().end(), factory) != Factories().end())
|
||||||
throw agi::InternalError("Automation 4: Attempt to register the same script factory multiple times. This should never happen.", nullptr);
|
throw agi::InternalError("Automation 4: Attempt to register the same script factory multiple times. This should never happen.");
|
||||||
|
|
||||||
Factories().emplace_back(std::move(factory));
|
Factories().emplace_back(std::move(factory));
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,9 +54,9 @@ namespace agi { struct Context; }
|
||||||
namespace cmd { class Command; }
|
namespace cmd { class Command; }
|
||||||
|
|
||||||
namespace Automation4 {
|
namespace Automation4 {
|
||||||
DEFINE_BASE_EXCEPTION_NOINNER(AutomationError, agi::Exception)
|
DEFINE_EXCEPTION(AutomationError, agi::Exception);
|
||||||
DEFINE_SIMPLE_EXCEPTION_NOINNER(ScriptLoadError, AutomationError, "automation/load/generic")
|
DEFINE_EXCEPTION(ScriptLoadError, AutomationError);
|
||||||
DEFINE_SIMPLE_EXCEPTION_NOINNER(MacroRunError, AutomationError, "automation/macro/generic")
|
DEFINE_EXCEPTION(MacroRunError, AutomationError);
|
||||||
|
|
||||||
// Calculate the extents of a text string given a style
|
// Calculate the extents of a text string given a style
|
||||||
bool CalculateTextExtents(AssStyle *style, std::string const& text, double &width, double &height, double &descent, double &extlead);
|
bool CalculateTextExtents(AssStyle *style, std::string const& text, double &width, double &height, double &descent, double &extlead);
|
||||||
|
|
|
@ -54,7 +54,7 @@
|
||||||
namespace {
|
namespace {
|
||||||
using namespace agi::lua;
|
using namespace agi::lua;
|
||||||
|
|
||||||
DEFINE_SIMPLE_EXCEPTION_NOINNER(BadField, Automation4::MacroRunError, "automation/macro/bad_field")
|
DEFINE_EXCEPTION(BadField, Automation4::MacroRunError);
|
||||||
BadField bad_field(const char *expected_type, const char *name, const char *line_clasee)
|
BadField bad_field(const char *expected_type, const char *name, const char *line_clasee)
|
||||||
{
|
{
|
||||||
return BadField(std::string("Invalid or missing field '") + name + "' in '" + line_clasee + "' class subtitle line (expected " + expected_type + ")");
|
return BadField(std::string("Invalid or missing field '") + name + "' in '" + line_clasee + "' class subtitle line (expected " + expected_type + ")");
|
||||||
|
|
|
@ -211,7 +211,7 @@ struct app_options final : public Command {
|
||||||
try {
|
try {
|
||||||
while (Preferences(c->parent).ShowModal() < 0);
|
while (Preferences(c->parent).ShowModal() < 0);
|
||||||
} catch (agi::Exception& e) {
|
} catch (agi::Exception& e) {
|
||||||
LOG_E("config/init") << "Caught exception: " << e.GetName() << " -> " << e.GetMessage();
|
LOG_E("config/init") << "Caught exception: " << e.GetMessage();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -53,8 +53,8 @@ struct cname final : public Command { \
|
||||||
|
|
||||||
/// Commands
|
/// Commands
|
||||||
namespace cmd {
|
namespace cmd {
|
||||||
DEFINE_BASE_EXCEPTION_NOINNER(CommandError, agi::Exception)
|
DEFINE_EXCEPTION(CommandError, agi::Exception);
|
||||||
DEFINE_SIMPLE_EXCEPTION_NOINNER(CommandNotFound, CommandError, "command/notfound")
|
DEFINE_EXCEPTION(CommandNotFound, CommandError);
|
||||||
|
|
||||||
enum CommandFlags {
|
enum CommandFlags {
|
||||||
/// Default command type
|
/// Default command type
|
||||||
|
|
|
@ -207,7 +207,7 @@ struct tool_translation_assistant final : public Command {
|
||||||
c->dialog->ShowModal<DialogTranslation>(c);
|
c->dialog->ShowModal<DialogTranslation>(c);
|
||||||
}
|
}
|
||||||
catch (agi::Exception const& e) {
|
catch (agi::Exception const& e) {
|
||||||
wxMessageBox(to_wx(e.GetChainedMessage()));
|
wxMessageBox(to_wx(e.GetMessage()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -123,7 +123,7 @@ void FontsCollectorThread(AssFile *subs, agi::fs::path const& destination, FcMod
|
||||||
}
|
}
|
||||||
catch (agi::fs::FileSystemError const& e) {
|
catch (agi::fs::FileSystemError const& e) {
|
||||||
AppendText(wxString::Format(_("* Failed to create directory '%s': %s.\n"),
|
AppendText(wxString::Format(_("* Failed to create directory '%s': %s.\n"),
|
||||||
destination.parent_path().wstring(), to_wx(e.GetChainedMessage())), 2);
|
destination.parent_path().wstring(), to_wx(e.GetMessage())), 2);
|
||||||
collector->AddPendingEvent(wxThreadEvent(EVT_COLLECTION_DONE));
|
collector->AddPendingEvent(wxThreadEvent(EVT_COLLECTION_DONE));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -154,7 +154,7 @@ void DialogProgress::Run(std::function<void(agi::ProgressSink*)> task, int prior
|
||||||
task(this->ps);
|
task(this->ps);
|
||||||
}
|
}
|
||||||
catch (agi::Exception const& e) {
|
catch (agi::Exception const& e) {
|
||||||
this->ps->Log(e.GetChainedMessage());
|
this->ps->Log(e.GetMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
Main().Async([this]{
|
Main().Async([this]{
|
||||||
|
|
|
@ -323,7 +323,7 @@ void DialogShiftTimes::SaveHistory(json::Array const& shifted_blocks) {
|
||||||
json::Writer::Write(history, agi::io::Save(history_filename).Get());
|
json::Writer::Write(history, agi::io::Save(history_filename).Get());
|
||||||
}
|
}
|
||||||
catch (agi::fs::FileSystemError const& e) {
|
catch (agi::fs::FileSystemError const& e) {
|
||||||
LOG_E("dialog_shift_times/save_history") << "Cannot save shift times history: " << e.GetChainedMessage();
|
LOG_E("dialog_shift_times/save_history") << "Cannot save shift times history: " << e.GetMessage();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -341,7 +341,7 @@ void DialogShiftTimes::LoadHistory() {
|
||||||
history_box->Append(get_history_string(history_entry));
|
history_box->Append(get_history_string(history_entry));
|
||||||
}
|
}
|
||||||
catch (agi::fs::FileSystemError const& e) {
|
catch (agi::fs::FileSystemError const& e) {
|
||||||
LOG_D("dialog_shift_times/load_history") << "Cannot load shift times history: " << e.GetChainedMessage();
|
LOG_D("dialog_shift_times/load_history") << "Cannot load shift times history: " << e.GetMessage();
|
||||||
}
|
}
|
||||||
catch (...) {
|
catch (...) {
|
||||||
history_box->Thaw();
|
history_box->Thaw();
|
||||||
|
|
|
@ -684,7 +684,7 @@ void DialogStyleManager::OnCurrentImport() {
|
||||||
reader->ReadFile(&temp, filename, 0, charset);
|
reader->ReadFile(&temp, filename, 0, charset);
|
||||||
}
|
}
|
||||||
catch (agi::Exception const& err) {
|
catch (agi::Exception const& err) {
|
||||||
wxMessageBox(to_wx(err.GetChainedMessage()), "Error", wxOK | wxICON_ERROR | wxCENTER, this);
|
wxMessageBox(to_wx(err.GetMessage()), "Error", wxOK | wxICON_ERROR | wxCENTER, this);
|
||||||
}
|
}
|
||||||
catch (...) {
|
catch (...) {
|
||||||
wxMessageBox("Unknown error", "Error", wxOK | wxICON_ERROR | wxCENTER, this);
|
wxMessageBox("Unknown error", "Error", wxOK | wxICON_ERROR | wxCENTER, this);
|
||||||
|
|
|
@ -79,5 +79,5 @@ public:
|
||||||
void Commit(bool next);
|
void Commit(bool next);
|
||||||
void InsertOriginal();
|
void InsertOriginal();
|
||||||
|
|
||||||
DEFINE_SIMPLE_EXCEPTION_NOINNER(NothingToTranslate, agi::Exception, "dialog/translation/nothing_to_translate");
|
DEFINE_EXCEPTION(NothingToTranslate, agi::Exception);;
|
||||||
};
|
};
|
||||||
|
|
|
@ -163,7 +163,7 @@ void VersionCheckerResultDialog::OnClose(wxCloseEvent &) {
|
||||||
Destroy();
|
Destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFINE_SIMPLE_EXCEPTION_NOINNER(VersionCheckError, agi::Exception, "versioncheck")
|
DEFINE_EXCEPTION(VersionCheckError, agi::Exception);
|
||||||
|
|
||||||
void PostErrorEvent(bool interactive, wxString const& error_text) {
|
void PostErrorEvent(bool interactive, wxString const& error_text) {
|
||||||
if (interactive) {
|
if (interactive) {
|
||||||
|
|
|
@ -69,7 +69,7 @@ HelpButton::HelpButton(wxWindow *parent, wxString const& page, wxPoint position,
|
||||||
Bind(wxEVT_BUTTON, [=](wxCommandEvent&) { OpenPage(page); });
|
Bind(wxEVT_BUTTON, [=](wxCommandEvent&) { OpenPage(page); });
|
||||||
init_static();
|
init_static();
|
||||||
if (pages.find(page) == pages.end())
|
if (pages.find(page) == pages.end())
|
||||||
throw agi::InternalError("Invalid help page", nullptr);
|
throw agi::InternalError("Invalid help page");
|
||||||
}
|
}
|
||||||
|
|
||||||
void HelpButton::OpenPage(wxString const& pageID) {
|
void HelpButton::OpenPage(wxString const& pageID) {
|
||||||
|
|
|
@ -172,7 +172,7 @@ bool check(std::string const& context, agi::Context *c, wxKeyEvent &evt) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
catch (cmd::CommandNotFound const& e) {
|
catch (cmd::CommandNotFound const& e) {
|
||||||
wxMessageBox(to_wx(e.GetChainedMessage()), _("Invalid command name for hotkey"),
|
wxMessageBox(to_wx(e.GetMessage()), _("Invalid command name for hotkey"),
|
||||||
wxOK | wxICON_ERROR | wxCENTER | wxSTAY_ON_TOP);
|
wxOK | wxICON_ERROR | wxCENTER | wxSTAY_ON_TOP);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -105,11 +105,11 @@ public:
|
||||||
variant = cmd::get(combo.CmdName())->StrHelp();
|
variant = cmd::get(combo.CmdName())->StrHelp();
|
||||||
}
|
}
|
||||||
catch (agi::Exception const& e) {
|
catch (agi::Exception const& e) {
|
||||||
variant = to_wx(e.GetChainedMessage());
|
variant = to_wx(e.GetMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
throw agi::InternalError("HotkeyDataViewModel asked for an invalid column number", nullptr);
|
throw agi::InternalError("HotkeyDataViewModel asked for an invalid column number");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SetValue(wxVariant const& variant, unsigned int col) override {
|
bool SetValue(wxVariant const& variant, unsigned int col) override {
|
||||||
|
|
|
@ -94,6 +94,6 @@ struct AudioProviderFactory {
|
||||||
static std::unique_ptr<AudioProvider> GetProvider(agi::fs::path const& filename, agi::BackgroundRunner *br);
|
static std::unique_ptr<AudioProvider> GetProvider(agi::fs::path const& filename, agi::BackgroundRunner *br);
|
||||||
};
|
};
|
||||||
|
|
||||||
DEFINE_BASE_EXCEPTION_NOINNER(AudioProviderError, agi::Exception)
|
DEFINE_EXCEPTION(AudioProviderError, agi::Exception);
|
||||||
/// Error of some sort occurred while decoding a frame
|
/// Error of some sort occurred while decoding a frame
|
||||||
DEFINE_SIMPLE_EXCEPTION_NOINNER(AudioDecodeError, AudioProviderError, "audio/error")
|
DEFINE_EXCEPTION(AudioDecodeError, AudioProviderError);
|
||||||
|
|
|
@ -29,9 +29,9 @@ class wxMenuBar;
|
||||||
class wxWindow;
|
class wxWindow;
|
||||||
|
|
||||||
namespace menu {
|
namespace menu {
|
||||||
DEFINE_BASE_EXCEPTION_NOINNER(Error, agi::Exception)
|
DEFINE_EXCEPTION(Error, agi::Exception);
|
||||||
DEFINE_SIMPLE_EXCEPTION_NOINNER(UnknownMenu, Error, "menu/unknown")
|
DEFINE_EXCEPTION(UnknownMenu, Error);
|
||||||
DEFINE_SIMPLE_EXCEPTION_NOINNER(InvalidMenu, Error, "menu/invalid")
|
DEFINE_EXCEPTION(InvalidMenu, Error);
|
||||||
|
|
||||||
/// @brief Get the menu with the specified name as a wxMenuBar
|
/// @brief Get the menu with the specified name as a wxMenuBar
|
||||||
/// @param name Name of the menu
|
/// @param name Name of the menu
|
||||||
|
|
|
@ -86,11 +86,11 @@ public:
|
||||||
virtual bool HasAudio() const { return false; }
|
virtual bool HasAudio() const { return false; }
|
||||||
};
|
};
|
||||||
|
|
||||||
DEFINE_BASE_EXCEPTION_NOINNER(VideoProviderError, agi::Exception)
|
DEFINE_EXCEPTION(VideoProviderError, agi::Exception);
|
||||||
/// File could be opened, but is not a supported format
|
/// File could be opened, but is not a supported format
|
||||||
DEFINE_SIMPLE_EXCEPTION_NOINNER(VideoNotSupported, VideoProviderError, "video/open/notsupported")
|
DEFINE_EXCEPTION(VideoNotSupported, VideoProviderError);
|
||||||
/// File appears to be a supported format, but could not be opened
|
/// File appears to be a supported format, but could not be opened
|
||||||
DEFINE_SIMPLE_EXCEPTION_NOINNER(VideoOpenError, VideoProviderError, "video/open/failed")
|
DEFINE_EXCEPTION(VideoOpenError, VideoProviderError);
|
||||||
|
|
||||||
/// Error of some sort occurred while decoding a frame
|
/// Error of some sort occurred while decoding a frame
|
||||||
DEFINE_SIMPLE_EXCEPTION_NOINNER(VideoDecodeError, VideoProviderError, "video/error")
|
DEFINE_EXCEPTION(VideoDecodeError, VideoProviderError);
|
||||||
|
|
|
@ -198,7 +198,7 @@ bool AegisubApp::OnInit() {
|
||||||
boost::interprocess::ibufferstream stream((const char *)default_config, sizeof(default_config));
|
boost::interprocess::ibufferstream stream((const char *)default_config, sizeof(default_config));
|
||||||
config::opt->ConfigNext(stream);
|
config::opt->ConfigNext(stream);
|
||||||
} catch (agi::Exception& e) {
|
} catch (agi::Exception& e) {
|
||||||
LOG_E("config/init") << "Caught exception: " << e.GetName() << " -> " << e.GetMessage();
|
LOG_E("config/init") << "Caught exception: " << e.GetMessage();
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -421,7 +421,7 @@ bool AegisubApp::OnExceptionInMainLoop() {
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
catch (const agi::Exception &e) {
|
catch (const agi::Exception &e) {
|
||||||
SHOW_EXCEPTION(to_wx(e.GetChainedMessage()));
|
SHOW_EXCEPTION(to_wx(e.GetMessage()));
|
||||||
}
|
}
|
||||||
catch (const std::exception &e) {
|
catch (const std::exception &e) {
|
||||||
SHOW_EXCEPTION(to_wx(e.what()));
|
SHOW_EXCEPTION(to_wx(e.what()));
|
||||||
|
@ -450,7 +450,7 @@ int AegisubApp::OnRun() {
|
||||||
catch (const wxString &err) { error = from_wx(err); }
|
catch (const wxString &err) { error = from_wx(err); }
|
||||||
catch (const char *err) { error = err; }
|
catch (const char *err) { error = err; }
|
||||||
catch (const std::exception &e) { error = std::string("std::exception: ") + e.what(); }
|
catch (const std::exception &e) { error = std::string("std::exception: ") + e.what(); }
|
||||||
catch (const agi::Exception &e) { error = "agi::exception: " + e.GetChainedMessage(); }
|
catch (const agi::Exception &e) { error = "agi::exception: " + e.GetMessage(); }
|
||||||
catch (...) { error = "Program terminated in error."; }
|
catch (...) { error = "Program terminated in error."; }
|
||||||
|
|
||||||
// Report errors
|
// Report errors
|
||||||
|
|
|
@ -71,7 +71,7 @@ struct MkvStdIO final : InputStream {
|
||||||
memcpy(buffer, self->file.read(pos, count), count);
|
memcpy(buffer, self->file.read(pos, count), count);
|
||||||
}
|
}
|
||||||
catch (agi::Exception const& e) {
|
catch (agi::Exception const& e) {
|
||||||
self->error = e.GetChainedMessage();
|
self->error = e.GetMessage();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,7 +90,7 @@ struct MkvStdIO final : InputStream {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (agi::Exception const& e) {
|
catch (agi::Exception const& e) {
|
||||||
self->error = e.GetChainedMessage();
|
self->error = e.GetMessage();
|
||||||
}
|
}
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
#include <libaegisub/exception.h>
|
#include <libaegisub/exception.h>
|
||||||
#include <libaegisub/fs_fwd.h>
|
#include <libaegisub/fs_fwd.h>
|
||||||
|
|
||||||
DEFINE_SIMPLE_EXCEPTION_NOINNER(MatroskaException, agi::Exception, "matroksa_wrapper/generic")
|
DEFINE_EXCEPTION(MatroskaException, agi::Exception);
|
||||||
|
|
||||||
class AssFile;
|
class AssFile;
|
||||||
|
|
||||||
|
|
|
@ -30,9 +30,9 @@ class wxButton;
|
||||||
class wxTreebook;
|
class wxTreebook;
|
||||||
namespace agi { class OptionValue; }
|
namespace agi { class OptionValue; }
|
||||||
|
|
||||||
DEFINE_BASE_EXCEPTION_NOINNER(PreferencesError, agi::Exception)
|
DEFINE_EXCEPTION(PreferencesError, agi::Exception);
|
||||||
DEFINE_SIMPLE_EXCEPTION_NOINNER(PreferenceIncorrectType, PreferencesError, "preferences/incorrect_type")
|
DEFINE_EXCEPTION(PreferenceIncorrectType, PreferencesError);
|
||||||
DEFINE_SIMPLE_EXCEPTION_NOINNER(PreferenceNotSupported, PreferencesError, "preferences/not_supported")
|
DEFINE_EXCEPTION(PreferenceNotSupported, PreferencesError);
|
||||||
|
|
||||||
class Preferences final : public wxDialog {
|
class Preferences final : public wxDialog {
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -124,7 +124,7 @@ void Project::DoLoadSubtitles(agi::fs::path const& path, std::string encoding) {
|
||||||
return ShowError(path.string() + " not found.");
|
return ShowError(path.string() + " not found.");
|
||||||
}
|
}
|
||||||
catch (agi::Exception const& e) {
|
catch (agi::Exception const& e) {
|
||||||
return ShowError(e.GetChainedMessage());
|
return ShowError(e.GetMessage());
|
||||||
}
|
}
|
||||||
catch (std::exception const& e) {
|
catch (std::exception const& e) {
|
||||||
return ShowError(std::string(e.what()));
|
return ShowError(std::string(e.what()));
|
||||||
|
@ -226,21 +226,21 @@ void Project::DoLoadAudio(agi::fs::path const& path, bool quiet) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (agi::fs::FileNotFound const& e) {
|
catch (agi::fs::FileNotFound const& e) {
|
||||||
return ShowError(_("The audio file was not found: ") + to_wx(e.GetChainedMessage()));
|
return ShowError(_("The audio file was not found: ") + to_wx(e.GetMessage()));
|
||||||
}
|
}
|
||||||
catch (agi::AudioDataNotFoundError const& e) {
|
catch (agi::AudioDataNotFoundError const& e) {
|
||||||
if (quiet) {
|
if (quiet) {
|
||||||
LOG_D("video/open/audio") << "File " << video_file << " has no audio data: " << e.GetChainedMessage();
|
LOG_D("video/open/audio") << "File " << video_file << " has no audio data: " << e.GetMessage();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return ShowError(_("None of the available audio providers recognised the selected file as containing audio data.\n\nThe following providers were tried:\n") + to_wx(e.GetChainedMessage()));
|
return ShowError(_("None of the available audio providers recognised the selected file as containing audio data.\n\nThe following providers were tried:\n") + to_wx(e.GetMessage()));
|
||||||
}
|
}
|
||||||
catch (agi::AudioProviderOpenError const& e) {
|
catch (agi::AudioProviderOpenError const& e) {
|
||||||
return ShowError(_("None of the available audio providers have a codec available to handle the selected file.\n\nThe following providers were tried:\n") + to_wx(e.GetChainedMessage()));
|
return ShowError(_("None of the available audio providers have a codec available to handle the selected file.\n\nThe following providers were tried:\n") + to_wx(e.GetMessage()));
|
||||||
}
|
}
|
||||||
catch (agi::Exception const& e) {
|
catch (agi::Exception const& e) {
|
||||||
return ShowError(e.GetChainedMessage());
|
return ShowError(e.GetMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
SetPath(audio_file, "?audio", "Audio", path);
|
SetPath(audio_file, "?audio", "Audio", path);
|
||||||
|
@ -336,11 +336,11 @@ void Project::LoadTimecodes(agi::fs::path const& path) {
|
||||||
DoLoadTimecodes(path);
|
DoLoadTimecodes(path);
|
||||||
}
|
}
|
||||||
catch (agi::fs::FileSystemError const& e) {
|
catch (agi::fs::FileSystemError const& e) {
|
||||||
ShowError(e.GetChainedMessage());
|
ShowError(e.GetMessage());
|
||||||
config::mru->Remove("Timecodes", path);
|
config::mru->Remove("Timecodes", path);
|
||||||
}
|
}
|
||||||
catch (agi::vfr::Error const& e) {
|
catch (agi::vfr::Error const& e) {
|
||||||
ShowError("Failed to parse timecodes file: " + e.GetChainedMessage());
|
ShowError("Failed to parse timecodes file: " + e.GetMessage());
|
||||||
config::mru->Remove("Timecodes", path);
|
config::mru->Remove("Timecodes", path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -362,11 +362,11 @@ void Project::LoadKeyframes(agi::fs::path const& path) {
|
||||||
DoLoadKeyframes(path);
|
DoLoadKeyframes(path);
|
||||||
}
|
}
|
||||||
catch (agi::fs::FileSystemError const& e) {
|
catch (agi::fs::FileSystemError const& e) {
|
||||||
ShowError(e.GetChainedMessage());
|
ShowError(e.GetMessage());
|
||||||
config::mru->Remove("Keyframes", path);
|
config::mru->Remove("Keyframes", path);
|
||||||
}
|
}
|
||||||
catch (agi::keyframe::Error const& e) {
|
catch (agi::keyframe::Error const& e) {
|
||||||
ShowError("Failed to parse keyframes file: " + e.GetChainedMessage());
|
ShowError("Failed to parse keyframes file: " + e.GetMessage());
|
||||||
config::mru->Remove("Keyframes", path);
|
config::mru->Remove("Keyframes", path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -200,7 +200,7 @@ namespace {
|
||||||
case YCbCrMatrix::tv_fcc: case YCbCrMatrix::pc_fcc: return agi::ycbcr_matrix::fcc;
|
case YCbCrMatrix::tv_fcc: case YCbCrMatrix::pc_fcc: return agi::ycbcr_matrix::fcc;
|
||||||
case YCbCrMatrix::tv_240m: case YCbCrMatrix::pc_240m: return agi::ycbcr_matrix::smpte_240m;
|
case YCbCrMatrix::tv_240m: case YCbCrMatrix::pc_240m: return agi::ycbcr_matrix::smpte_240m;
|
||||||
}
|
}
|
||||||
throw agi::InternalError("Invalid matrix", nullptr);
|
throw agi::InternalError("Invalid matrix");
|
||||||
}
|
}
|
||||||
|
|
||||||
agi::ycbcr_range range(YCbCrMatrix mat) {
|
agi::ycbcr_range range(YCbCrMatrix mat) {
|
||||||
|
@ -217,7 +217,7 @@ namespace {
|
||||||
case YCbCrMatrix::pc_240m:
|
case YCbCrMatrix::pc_240m:
|
||||||
return agi::ycbcr_range::pc;
|
return agi::ycbcr_range::pc;
|
||||||
}
|
}
|
||||||
throw agi::InternalError("Invalid matrix", nullptr);
|
throw agi::InternalError("Invalid matrix");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -39,7 +39,7 @@ auto get_dialogue_field(SearchReplaceSettings::Field field) -> decltype(&AssDial
|
||||||
case SearchReplaceSettings::Field::ACTOR: return &AssDialogueBase::Actor;
|
case SearchReplaceSettings::Field::ACTOR: return &AssDialogueBase::Actor;
|
||||||
case SearchReplaceSettings::Field::EFFECT: return &AssDialogueBase::Effect;
|
case SearchReplaceSettings::Field::EFFECT: return &AssDialogueBase::Effect;
|
||||||
}
|
}
|
||||||
throw agi::InternalError("Bad field for search", nullptr);
|
throw agi::InternalError("Bad field for search");
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string const& get_normalized(const AssDialogue *diag, decltype(&AssDialogueBase::Text) field) {
|
std::string const& get_normalized(const AssDialogue *diag, decltype(&AssDialogueBase::Text) field) {
|
||||||
|
|
|
@ -150,7 +150,7 @@ agi::vfr::Framerate SubtitleFormat::AskForFPS(bool allow_vfr, bool show_smpte, a
|
||||||
case 10: return Framerate(120000, 1001); break;
|
case 10: return Framerate(120000, 1001); break;
|
||||||
case 11: return Framerate(120, 1); break;
|
case 11: return Framerate(120, 1); break;
|
||||||
}
|
}
|
||||||
throw agi::InternalError("Out of bounds result from wxGetSingleChoiceIndex?", nullptr);
|
throw agi::InternalError("Out of bounds result from wxGetSingleChoiceIndex?");
|
||||||
}
|
}
|
||||||
|
|
||||||
void SubtitleFormat::StripTags(AssFile &file) {
|
void SubtitleFormat::StripTags(AssFile &file) {
|
||||||
|
@ -277,7 +277,7 @@ template<class Cont, class Pred>
|
||||||
SubtitleFormat *find_or_throw(Cont &container, Pred pred) {
|
SubtitleFormat *find_or_throw(Cont &container, Pred pred) {
|
||||||
auto it = find_if(container.begin(), container.end(), pred);
|
auto it = find_if(container.begin(), container.end(), pred);
|
||||||
if (it == container.end())
|
if (it == container.end())
|
||||||
throw UnknownSubtitleFormatError("Subtitle format for extension not found", nullptr);
|
throw UnknownSubtitleFormatError("Subtitle format for extension not found");
|
||||||
return it->get();
|
return it->get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -118,5 +118,5 @@ public:
|
||||||
static void LoadFormats();
|
static void LoadFormats();
|
||||||
};
|
};
|
||||||
|
|
||||||
DEFINE_SIMPLE_EXCEPTION(SubtitleFormatParseError, agi::InvalidInputException, "subtitle_io/parse/generic")
|
DEFINE_EXCEPTION(SubtitleFormatParseError, agi::InvalidInputException);
|
||||||
DEFINE_SIMPLE_EXCEPTION(UnknownSubtitleFormatError, agi::InvalidInputException, "subtitle_io/unknown")
|
DEFINE_EXCEPTION(UnknownSubtitleFormatError, agi::InvalidInputException);
|
||||||
|
|
|
@ -31,7 +31,7 @@
|
||||||
#include <libaegisub/ass/uuencode.h>
|
#include <libaegisub/ass/uuencode.h>
|
||||||
#include <libaegisub/fs.h>
|
#include <libaegisub/fs.h>
|
||||||
|
|
||||||
DEFINE_SIMPLE_EXCEPTION(AssParseError, SubtitleFormatParseError, "subtitle_io/parse/ass")
|
DEFINE_EXCEPTION(AssParseError, SubtitleFormatParseError);
|
||||||
|
|
||||||
void AssSubtitleFormat::ReadFile(AssFile *target, agi::fs::path const& filename, agi::vfr::Framerate const& fps, std::string const& encoding) const {
|
void AssSubtitleFormat::ReadFile(AssFile *target, agi::fs::path const& filename, agi::vfr::Framerate const& fps, std::string const& encoding) const {
|
||||||
TextFileReader file(filename, encoding);
|
TextFileReader file(filename, encoding);
|
||||||
|
@ -44,7 +44,7 @@ void AssSubtitleFormat::ReadFile(AssFile *target, agi::fs::path const& filename,
|
||||||
parser.AddLine(line);
|
parser.AddLine(line);
|
||||||
}
|
}
|
||||||
catch (const char *err) {
|
catch (const char *err) {
|
||||||
throw AssParseError("Error processing line: " + line + ": " + err, nullptr);
|
throw AssParseError("Error processing line: " + line + ": " + err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -404,7 +404,7 @@ namespace
|
||||||
else if (!imline.CheckLineLengths(export_settings.max_line_length))
|
else if (!imline.CheckLineLengths(export_settings.max_line_length))
|
||||||
{
|
{
|
||||||
if (export_settings.line_wrapping_mode == EbuExportSettings::AbortOverLength)
|
if (export_settings.line_wrapping_mode == EbuExportSettings::AbortOverLength)
|
||||||
throw Ebu3264SubtitleFormat::ConversionFailed(from_wx(wxString::Format(_("Line over maximum length: %s"), line.Text.get())), nullptr);
|
throw Ebu3264SubtitleFormat::ConversionFailed(from_wx(wxString::Format(_("Line over maximum length: %s"), line.Text.get())));
|
||||||
else // skip over-long lines
|
else // skip over-long lines
|
||||||
subs_list.pop_back();
|
subs_list.pop_back();
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,5 +30,5 @@ public:
|
||||||
std::vector<std::string> GetWriteWildcards() const override;
|
std::vector<std::string> GetWriteWildcards() const override;
|
||||||
void WriteFile(const AssFile *src, agi::fs::path const& filename, agi::vfr::Framerate const& fps, std::string const& encoding) const override;
|
void WriteFile(const AssFile *src, agi::fs::path const& filename, agi::vfr::Framerate const& fps, std::string const& encoding) const override;
|
||||||
|
|
||||||
DEFINE_SIMPLE_EXCEPTION(ConversionFailed, agi::InvalidInputException, "subtitle_io/ebu3264/conversion_error")
|
DEFINE_EXCEPTION(ConversionFailed, agi::InvalidInputException);
|
||||||
};
|
};
|
||||||
|
|
|
@ -51,7 +51,7 @@
|
||||||
#include <boost/regex.hpp>
|
#include <boost/regex.hpp>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
DEFINE_SIMPLE_EXCEPTION(SRTParseError, SubtitleFormatParseError, "subtitle_io/parse/srt")
|
DEFINE_EXCEPTION(SRTParseError, SubtitleFormatParseError);
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
class SrtTagParser {
|
class SrtTagParser {
|
||||||
|
@ -382,11 +382,11 @@ void SRTSubtitleFormat::ReadFile(AssFile *target, agi::fs::path const& filename,
|
||||||
if (regex_search(text_line, timestamp_match, timestamp_regex))
|
if (regex_search(text_line, timestamp_match, timestamp_regex))
|
||||||
goto found_timestamps;
|
goto found_timestamps;
|
||||||
|
|
||||||
throw SRTParseError(agi::format("Parsing SRT: Expected subtitle index at line %d", line_num), nullptr);
|
throw SRTParseError(agi::format("Parsing SRT: Expected subtitle index at line %d", line_num));
|
||||||
|
|
||||||
case STATE_TIMESTAMP:
|
case STATE_TIMESTAMP:
|
||||||
if (!regex_search(text_line, timestamp_match, timestamp_regex))
|
if (!regex_search(text_line, timestamp_match, timestamp_regex))
|
||||||
throw SRTParseError(agi::format("Parsing SRT: Expected timestamp pair at line %d", line_num), nullptr);
|
throw SRTParseError(agi::format("Parsing SRT: Expected timestamp pair at line %d", line_num));
|
||||||
found_timestamps:
|
found_timestamps:
|
||||||
if (line) {
|
if (line) {
|
||||||
// finalize active line
|
// finalize active line
|
||||||
|
@ -452,7 +452,7 @@ found_timestamps:
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state == 1 || state == 2)
|
if (state == 1 || state == 2)
|
||||||
throw SRTParseError("Parsing SRT: Incomplete file", nullptr);
|
throw SRTParseError("Parsing SRT: Incomplete file");
|
||||||
|
|
||||||
if (line) // an unfinalized line
|
if (line) // an unfinalized line
|
||||||
line->Text = tag_parser.ToAss(text);
|
line->Text = tag_parser.ToAss(text);
|
||||||
|
|
|
@ -23,4 +23,4 @@ public:
|
||||||
/// @todo Not actually true
|
/// @todo Not actually true
|
||||||
bool CanSave(const AssFile*) const override { return true; }
|
bool CanSave(const AssFile*) const override { return true; }
|
||||||
void WriteFile(const AssFile *src, agi::fs::path const& filename, agi::vfr::Framerate const& fps, std::string const& encoding) const override;
|
void WriteFile(const AssFile *src, agi::fs::path const& filename, agi::vfr::Framerate const& fps, std::string const& encoding) const override;
|
||||||
};
|
};
|
||||||
|
|
|
@ -43,7 +43,7 @@
|
||||||
#include <boost/range/adaptor/reversed.hpp>
|
#include <boost/range/adaptor/reversed.hpp>
|
||||||
#include <wx/xml/xml.h>
|
#include <wx/xml/xml.h>
|
||||||
|
|
||||||
DEFINE_SIMPLE_EXCEPTION(TTXTParseError, SubtitleFormatParseError, "subtitle_io/parse/ttxt")
|
DEFINE_EXCEPTION(TTXTParseError, SubtitleFormatParseError);
|
||||||
|
|
||||||
TTXTSubtitleFormat::TTXTSubtitleFormat()
|
TTXTSubtitleFormat::TTXTSubtitleFormat()
|
||||||
: SubtitleFormat("MPEG-4 Streaming Text")
|
: SubtitleFormat("MPEG-4 Streaming Text")
|
||||||
|
@ -63,10 +63,10 @@ void TTXTSubtitleFormat::ReadFile(AssFile *target, agi::fs::path const& filename
|
||||||
|
|
||||||
// Load XML document
|
// Load XML document
|
||||||
wxXmlDocument doc;
|
wxXmlDocument doc;
|
||||||
if (!doc.Load(filename.wstring())) throw TTXTParseError("Failed loading TTXT XML file.", nullptr);
|
if (!doc.Load(filename.wstring())) throw TTXTParseError("Failed loading TTXT XML file.");
|
||||||
|
|
||||||
// Check root node name
|
// Check root node name
|
||||||
if (doc.GetRoot()->GetName() != "TextStream") throw TTXTParseError("Invalid TTXT file.", nullptr);
|
if (doc.GetRoot()->GetName() != "TextStream") throw TTXTParseError("Invalid TTXT file.");
|
||||||
|
|
||||||
// Check version
|
// Check version
|
||||||
wxString verStr = doc.GetRoot()->GetAttribute("version", "");
|
wxString verStr = doc.GetRoot()->GetAttribute("version", "");
|
||||||
|
@ -76,7 +76,7 @@ void TTXTSubtitleFormat::ReadFile(AssFile *target, agi::fs::path const& filename
|
||||||
else if (verStr == "1.1")
|
else if (verStr == "1.1")
|
||||||
version = 1;
|
version = 1;
|
||||||
else
|
else
|
||||||
throw TTXTParseError("Unknown TTXT version: " + from_wx(verStr), nullptr);
|
throw TTXTParseError("Unknown TTXT version: " + from_wx(verStr));
|
||||||
|
|
||||||
// Get children
|
// Get children
|
||||||
AssDialogue *diag = nullptr;
|
AssDialogue *diag = nullptr;
|
||||||
|
|
|
@ -81,7 +81,7 @@ void TXTSubtitleFormat::ReadFile(AssFile *target, agi::fs::path const& filename,
|
||||||
|
|
||||||
// Check if this isn't a timecodes file
|
// Check if this isn't a timecodes file
|
||||||
if (boost::starts_with(value, "# timecode"))
|
if (boost::starts_with(value, "# timecode"))
|
||||||
throw SubtitleFormatParseError("File is a timecode file, cannot load as subtitles.", nullptr);
|
throw SubtitleFormatParseError("File is a timecode file, cannot load as subtitles.");
|
||||||
|
|
||||||
// Read comment data
|
// Read comment data
|
||||||
bool isComment = false;
|
bool isComment = false;
|
||||||
|
|
|
@ -83,7 +83,7 @@ CSRISubtitlesProvider::CSRISubtitlesProvider(std::string type) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!renderer)
|
if (!renderer)
|
||||||
throw agi::InternalError("CSRI renderer vanished between initial list and creation?", 0);
|
throw agi::InternalError("CSRI renderer vanished between initial list and creation?");
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSRISubtitlesProvider::DrawSubtitles(VideoFrame &dst, double time) {
|
void CSRISubtitlesProvider::DrawSubtitles(VideoFrame &dst, double time) {
|
||||||
|
|
|
@ -106,7 +106,7 @@ void Thesaurus::OnLanguageChanged() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
catch (agi::Exception const& e) {
|
catch (agi::Exception const& e) {
|
||||||
LOG_E("thesaurus") << e.GetChainedMessage();
|
LOG_E("thesaurus") << e.GetMessage();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -106,7 +106,7 @@ namespace {
|
||||||
auto root_it = root.find(name);
|
auto root_it = root.find(name);
|
||||||
if (root_it == root.end()) {
|
if (root_it == root.end()) {
|
||||||
// Toolbar names are all hardcoded so this should never happen
|
// Toolbar names are all hardcoded so this should never happen
|
||||||
throw agi::InternalError("Toolbar named " + name + " not found.", nullptr);
|
throw agi::InternalError("Toolbar named " + name + " not found.");
|
||||||
}
|
}
|
||||||
|
|
||||||
json::Array const& arr = root_it->second;
|
json::Array const& arr = root_it->second;
|
||||||
|
|
|
@ -196,7 +196,7 @@ void CleanCache(agi::fs::path const& directory, std::string const& file_type, ui
|
||||||
LOG_D("utils/clean_cache") << "deleted " << i.second;
|
LOG_D("utils/clean_cache") << "deleted " << i.second;
|
||||||
}
|
}
|
||||||
catch (agi::Exception const& e) {
|
catch (agi::Exception const& e) {
|
||||||
LOG_D("utils/clean_cache") << "failed to delete file " << i.second << ": " << e.GetChainedMessage();
|
LOG_D("utils/clean_cache") << "failed to delete file " << i.second << ": " << e.GetMessage();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -175,7 +175,7 @@ bool StringBinder::TransferFromWindow() {
|
||||||
else if (wxComboBox *ctrl = dynamic_cast<wxComboBox*>(window))
|
else if (wxComboBox *ctrl = dynamic_cast<wxComboBox*>(window))
|
||||||
*value = from_wx(ctrl->GetValue());
|
*value = from_wx(ctrl->GetValue());
|
||||||
else
|
else
|
||||||
throw agi::InternalError("Unsupported control type", nullptr);
|
throw agi::InternalError("Unsupported control type");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -186,6 +186,6 @@ bool StringBinder::TransferToWindow() {
|
||||||
else if (wxComboBox *ctrl = dynamic_cast<wxComboBox*>(window))
|
else if (wxComboBox *ctrl = dynamic_cast<wxComboBox*>(window))
|
||||||
ctrl->SetValue(to_wx(*value));
|
ctrl->SetValue(to_wx(*value));
|
||||||
else
|
else
|
||||||
throw agi::InternalError("Unsupported control type", nullptr);
|
throw agi::InternalError("Unsupported control type");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -84,7 +84,7 @@ class EnumBinder final : public wxValidator {
|
||||||
else if (auto rb = dynamic_cast<wxComboBox*>(GetWindow()))
|
else if (auto rb = dynamic_cast<wxComboBox*>(GetWindow()))
|
||||||
*value = static_cast<T>(rb->GetSelection());
|
*value = static_cast<T>(rb->GetSelection());
|
||||||
else
|
else
|
||||||
throw agi::InternalError("Control type not supported by EnumBinder", nullptr);
|
throw agi::InternalError("Control type not supported by EnumBinder");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -94,7 +94,7 @@ class EnumBinder final : public wxValidator {
|
||||||
else if (auto cb = dynamic_cast<wxComboBox*>(GetWindow()))
|
else if (auto cb = dynamic_cast<wxComboBox*>(GetWindow()))
|
||||||
cb->SetSelection(static_cast<int>(*value));
|
cb->SetSelection(static_cast<int>(*value));
|
||||||
else
|
else
|
||||||
throw agi::InternalError("Control type not supported by EnumBinder", nullptr);
|
throw agi::InternalError("Control type not supported by EnumBinder");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -196,7 +196,7 @@ double VideoController::GetARFromType(AspectRatio type) const {
|
||||||
case AspectRatio::Widescreen: return 16.0/9.0;
|
case AspectRatio::Widescreen: return 16.0/9.0;
|
||||||
case AspectRatio::Cinematic: return 2.35;
|
case AspectRatio::Cinematic: return 2.35;
|
||||||
}
|
}
|
||||||
throw agi::InternalError("Bad AR type", nullptr);
|
throw agi::InternalError("Bad AR type");
|
||||||
}
|
}
|
||||||
|
|
||||||
void VideoController::SetAspectRatio(double value) {
|
void VideoController::SetAspectRatio(double value) {
|
||||||
|
|
|
@ -67,16 +67,12 @@
|
||||||
/// Attribute list for gl canvases; set the canvases to doublebuffered rgba with an 8 bit stencil buffer
|
/// Attribute list for gl canvases; set the canvases to doublebuffered rgba with an 8 bit stencil buffer
|
||||||
int attribList[] = { WX_GL_RGBA , WX_GL_DOUBLEBUFFER, WX_GL_STENCIL_SIZE, 8, 0 };
|
int attribList[] = { WX_GL_RGBA , WX_GL_DOUBLEBUFFER, WX_GL_STENCIL_SIZE, 8, 0 };
|
||||||
|
|
||||||
/// @class VideoOutRenderException
|
/// An OpenGL error occurred while uploading or displaying a frame
|
||||||
/// @extends VideoOutException
|
|
||||||
/// @brief An OpenGL error occurred while uploading or displaying a frame
|
|
||||||
class OpenGlException final : public agi::Exception {
|
class OpenGlException final : public agi::Exception {
|
||||||
public:
|
public:
|
||||||
OpenGlException(const char *func, int err)
|
OpenGlException(const char *func, int err)
|
||||||
: agi::Exception(from_wx(wxString::Format("%s failed with error code %d", func, err)))
|
: agi::Exception(from_wx(wxString::Format("%s failed with error code %d", func, err)))
|
||||||
{ }
|
{ }
|
||||||
const char * GetName() const override { return "video/opengl"; }
|
|
||||||
Exception * Copy() const override { return new OpenGlException(*this); }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#define E(cmd) cmd; if (GLenum err = glGetError()) throw OpenGlException(#cmd, err)
|
#define E(cmd) cmd; if (GLenum err = glGetError()) throw OpenGlException(#cmd, err)
|
||||||
|
@ -224,7 +220,7 @@ catch (const agi::Exception &err) {
|
||||||
wxLogError(
|
wxLogError(
|
||||||
"An error occurred trying to render the video frame on the screen.\n"
|
"An error occurred trying to render the video frame on the screen.\n"
|
||||||
"Error message reported: %s",
|
"Error message reported: %s",
|
||||||
err.GetChainedMessage());
|
err.GetMessage());
|
||||||
con->project->CloseVideo();
|
con->project->CloseVideo();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -75,37 +75,26 @@ public:
|
||||||
/// @param height Height in pixels of viewport
|
/// @param height Height in pixels of viewport
|
||||||
void Render(int x, int y, int width, int height);
|
void Render(int x, int y, int width, int height);
|
||||||
|
|
||||||
/// @brief Constructor
|
|
||||||
VideoOutGL();
|
VideoOutGL();
|
||||||
/// @brief Destructor
|
|
||||||
~VideoOutGL();
|
~VideoOutGL();
|
||||||
};
|
};
|
||||||
|
|
||||||
/// @class VideoOutException
|
/// Base class for all exceptions thrown by VideoOutGL
|
||||||
/// @extends Aegisub::Exception
|
DEFINE_EXCEPTION(VideoOutException, agi::Exception);
|
||||||
/// @brief Base class for all exceptions thrown by VideoOutGL
|
|
||||||
DEFINE_BASE_EXCEPTION_NOINNER(VideoOutException, agi::Exception)
|
|
||||||
|
|
||||||
/// @class VideoOutRenderException
|
/// An OpenGL error occurred while uploading or displaying a frame
|
||||||
/// @extends VideoOutException
|
|
||||||
/// @brief An OpenGL error occurred while uploading or displaying a frame
|
|
||||||
class VideoOutRenderException final : public VideoOutException {
|
class VideoOutRenderException final : public VideoOutException {
|
||||||
public:
|
public:
|
||||||
VideoOutRenderException(const char *func, int err)
|
VideoOutRenderException(const char *func, int err)
|
||||||
: VideoOutException(std::string(func) + " failed with error code " + std::to_string(err))
|
: VideoOutException(std::string(func) + " failed with error code " + std::to_string(err))
|
||||||
{ }
|
{ }
|
||||||
const char * GetName() const override { return "videoout/opengl/render"; }
|
|
||||||
Exception * Copy() const override { return new VideoOutRenderException(*this); }
|
|
||||||
};
|
};
|
||||||
/// @class VideoOutOpenGLException
|
|
||||||
/// @extends VideoOutException
|
/// An OpenGL error occurred while setting up the video display
|
||||||
/// @brief An OpenGL error occurred while setting up the video display
|
|
||||||
class VideoOutInitException final : public VideoOutException {
|
class VideoOutInitException final : public VideoOutException {
|
||||||
public:
|
public:
|
||||||
VideoOutInitException(const char *func, int err)
|
VideoOutInitException(const char *func, int err)
|
||||||
: VideoOutException(std::string(func) + " failed with error code " + std::to_string(err))
|
: VideoOutException(std::string(func) + " failed with error code " + std::to_string(err))
|
||||||
{ }
|
{ }
|
||||||
VideoOutInitException(const char *err) : VideoOutException(err) { }
|
VideoOutInitException(const char *err) : VideoOutException(err) { }
|
||||||
const char * GetName() const override { return "videoout/opengl/init"; }
|
|
||||||
Exception * Copy() const override { return new VideoOutInitException(*this); }
|
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue