encoder: migrate from class Error to C++ exceptions
This commit is contained in:
@@ -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();
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user