encoder: migrate from class Error to C++ exceptions

This commit is contained in:
Max Kellermann
2016-11-07 09:20:12 +01:00
parent b8aac3f8fc
commit d8b6aff23a
16 changed files with 299 additions and 477 deletions

View File

@@ -110,8 +110,10 @@ private:
/**
* Finish the encoder and commit the file.
*
* Throws #std::runtime_error on error.
*/
bool Commit(Error &error);
void Commit();
void FinishFormat();
bool ReopenFormat(AllocatedPath &&new_path, Error &error);
@@ -209,10 +211,11 @@ RecorderOutput::Open(AudioFormat &audio_format, Error &error)
/* open the encoder */
encoder = prepared_encoder->Open(audio_format, error);
if (encoder == nullptr) {
try {
encoder = prepared_encoder->Open(audio_format);
} catch (const std::runtime_error &) {
delete file;
return false;
throw;
}
if (!HasDynamicPath()) {
@@ -235,39 +238,33 @@ RecorderOutput::Open(AudioFormat &audio_format, Error &error)
return true;
}
inline bool
RecorderOutput::Commit(Error &error)
inline void
RecorderOutput::Commit()
{
assert(!path.IsNull());
/* flush the encoder and write the rest to the file */
bool success = encoder->End(error);
if (success) {
try {
EncoderToFile();
} catch (...) {
delete encoder;
throw;
}
try {
encoder->End();
EncoderToFile();
} catch (...) {
delete encoder;
throw;
}
/* now really close everything */
delete encoder;
if (success) {
try {
file->Commit();
} catch (...) {
delete file;
throw;
}
try {
file->Commit();
} catch (...) {
delete file;
throw;
}
delete file;
return success;
}
inline void
@@ -282,9 +279,7 @@ RecorderOutput::Close()
}
try {
Error error;
if (!Commit(error))
LogError(error);
Commit();
} catch (const std::exception &e) {
LogError(e);
}
@@ -304,9 +299,7 @@ RecorderOutput::FinishFormat()
return;
try {
Error error;
if (!Commit(error))
LogError(error);
Commit();
} catch (const std::exception &e) {
LogError(e);
}
@@ -331,10 +324,12 @@ RecorderOutput::ReopenFormat(AllocatedPath &&new_path, Error &error)
}
AudioFormat new_audio_format = effective_audio_format;
encoder = prepared_encoder->Open(new_audio_format, error);
if (encoder == nullptr) {
try {
encoder = prepared_encoder->Open(new_audio_format);
} catch (...) {
delete new_file;
return false;
throw;
}
/* reopening the encoder must always result in the same
@@ -395,21 +390,9 @@ RecorderOutput::SendTag(const Tag &tag)
}
}
Error error;
if (!encoder->PreTag(error)) {
LogError(error);
return;
}
try {
EncoderToFile();
} catch (const std::exception &e) {
LogError(e);
return;
}
if (!encoder->SendTag(tag, error))
LogError(error);
encoder->PreTag();
EncoderToFile();
encoder->SendTag(tag);
}
inline size_t
@@ -423,8 +406,7 @@ RecorderOutput::Play(const void *chunk, size_t size, Error &error)
return size;
}
if (!encoder->Write(chunk, size, error))
return 0;
encoder->Write(chunk, size);
try {
EncoderToFile();

View File

@@ -32,6 +32,8 @@
#include <shout/shout.h>
#include <stdexcept>
#include <assert.h>
#include <stdlib.h>
#include <string.h>
@@ -366,8 +368,12 @@ void
ShoutOutput::Close()
{
if (encoder != nullptr) {
if (encoder->End(IgnoreError()))
try {
encoder->End();
write_page(this, IgnoreError());
} catch (const std::runtime_error &) {
/* ignore */
}
delete encoder;
}
@@ -410,16 +416,22 @@ ShoutOutput::Open(AudioFormat &audio_format, Error &error)
if (!shout_connect(this, error))
return false;
encoder = prepared_encoder->Open(audio_format, error);
if (encoder == nullptr) {
shout_close(shout_conn);
return false;
}
try {
encoder = prepared_encoder->Open(audio_format);
if (!write_page(this, error)) {
delete encoder;
try {
if (!write_page(this, error)) {
delete encoder;
shout_close(shout_conn);
return false;
}
} catch (const std::runtime_error &) {
delete encoder;
throw;
}
} catch (const std::runtime_error &) {
shout_close(shout_conn);
return false;
throw;
}
return true;
@@ -438,8 +450,8 @@ ShoutOutput::Delay() const
size_t
ShoutOutput::Play(const void *chunk, size_t size, Error &error)
{
return encoder->Write(chunk, size, error) &&
write_page(this, error)
encoder->Write(chunk, size);
return write_page(this, error)
? size
: 0;
}
@@ -484,13 +496,15 @@ ShoutOutput::SendTag(const Tag &tag)
if (encoder->ImplementsTag()) {
/* encoder plugin supports stream tags */
encoder->PreTag();
Error error;
if (!encoder->PreTag(error) ||
!write_page(this, error) ||
!encoder->SendTag(tag, error)) {
if (!write_page(this, error)) {
LogError(error);
return;
}
encoder->SendTag(tag);
} else {
/* no stream tag support: fall back to icy-metadata */
char song[1024];

View File

@@ -171,8 +171,10 @@ public:
/**
* Caller must lock the mutex.
*
* Throws #std::runtime_error on error.
*/
bool OpenEncoder(AudioFormat &audio_format, Error &error);
void OpenEncoder(AudioFormat &audio_format);
/**
* Caller must lock the mutex.
@@ -237,7 +239,10 @@ public:
*/
void BroadcastFromEncoder();
bool EncodeAndPlay(const void *chunk, size_t size, Error &error);
/**
* Throws #std::runtime_error on error.
*/
void EncodeAndPlay(const void *chunk, size_t size);
void SendTag(const Tag &tag);

View File

@@ -221,7 +221,12 @@ HttpdOutput::ReadPage()
/* we have fed a lot of input into the encoder, but it
didn't give anything back yet - flush now to avoid
buffer underruns */
encoder->Flush(IgnoreError());
try {
encoder->Flush();
} catch (const std::runtime_error &) {
/* ignore */
}
unflushed_input = 0;
}
@@ -260,12 +265,10 @@ httpd_output_disable(AudioOutput *ao)
httpd->Unbind();
}
inline bool
HttpdOutput::OpenEncoder(AudioFormat &audio_format, Error &error)
inline void
HttpdOutput::OpenEncoder(AudioFormat &audio_format)
{
encoder = prepared_encoder->Open(audio_format, error);
if (encoder == nullptr)
return false;
encoder = prepared_encoder->Open(audio_format);
/* we have to remember the encoder header, i.e. the first
bytes of encoder output after opening it, because it has to
@@ -273,20 +276,15 @@ HttpdOutput::OpenEncoder(AudioFormat &audio_format, Error &error)
header = ReadPage();
unflushed_input = 0;
return true;
}
inline bool
HttpdOutput::Open(AudioFormat &audio_format, Error &error)
HttpdOutput::Open(AudioFormat &audio_format, Error &)
{
assert(!open);
assert(clients.empty());
/* open the encoder */
if (!OpenEncoder(audio_format, error))
return false;
OpenEncoder(audio_format);
/* initialize other attributes */
@@ -410,25 +408,21 @@ HttpdOutput::BroadcastFromEncoder()
DeferredMonitor::Schedule();
}
inline bool
HttpdOutput::EncodeAndPlay(const void *chunk, size_t size, Error &error)
inline void
HttpdOutput::EncodeAndPlay(const void *chunk, size_t size)
{
if (!encoder->Write(chunk, size, error))
return false;
encoder->Write(chunk, size);
unflushed_input += size;
BroadcastFromEncoder();
return true;
}
inline size_t
HttpdOutput::Play(const void *chunk, size_t size, Error &error)
HttpdOutput::Play(const void *chunk, size_t size, Error &)
{
if (LockHasClients()) {
if (!EncodeAndPlay(chunk, size, error))
return 0;
}
if (LockHasClients())
EncodeAndPlay(chunk, size);
if (!timer->IsStarted())
timer->Start();
@@ -468,13 +462,22 @@ HttpdOutput::SendTag(const Tag &tag)
/* flush the current stream, and end it */
encoder->PreTag(IgnoreError());
try {
encoder->PreTag();
} catch (const std::runtime_error &) {
/* ignore */
}
BroadcastFromEncoder();
/* send the tag to the encoder - which starts a new
stream now */
encoder->SendTag(tag, IgnoreError());
try {
encoder->SendTag(tag);
} catch (const std::runtime_error &) {
/* ignore */
}
/* the first page generated by the encoder will now be
used as the new "header" page, which is sent to all