output/shout: use AudioOutputWrapper

This commit is contained in:
Max Kellermann 2016-05-04 14:44:00 +02:00
parent 73cadd1798
commit e14cd92d59

View File

@ -20,6 +20,7 @@
#include "config.h" #include "config.h"
#include "ShoutOutputPlugin.hxx" #include "ShoutOutputPlugin.hxx"
#include "../OutputAPI.hxx" #include "../OutputAPI.hxx"
#include "../Wrapper.hxx"
#include "encoder/EncoderInterface.hxx" #include "encoder/EncoderInterface.hxx"
#include "encoder/EncoderPlugin.hxx" #include "encoder/EncoderPlugin.hxx"
#include "encoder/EncoderList.hxx" #include "encoder/EncoderList.hxx"
@ -65,6 +66,16 @@ struct ShoutOutput final {
} }
bool Configure(const ConfigBlock &block, Error &error); bool Configure(const ConfigBlock &block, Error &error);
static ShoutOutput *Create(const ConfigBlock &block, Error &error);
bool Open(AudioFormat &audio_format, Error &error);
void Close();
unsigned Delay() const;
void SendTag(const Tag &tag);
size_t Play(const void *chunk, size_t size, Error &error);
void Cancel();
bool Pause();
}; };
static int shout_init_count; static int shout_init_count;
@ -278,8 +289,8 @@ ShoutOutput::Configure(const ConfigBlock &block, Error &error)
return true; return true;
} }
static AudioOutput * ShoutOutput *
my_shout_init_driver(const ConfigBlock &block, Error &error) ShoutOutput::Create(const ConfigBlock &block, Error &error)
{ {
if (shout_init_count == 0) if (shout_init_count == 0)
shout_init(); shout_init();
@ -297,7 +308,7 @@ my_shout_init_driver(const ConfigBlock &block, Error &error)
return nullptr; return nullptr;
} }
return &sd->base; return sd;
} }
static bool static bool
@ -347,47 +358,30 @@ write_page(ShoutOutput *sd, Error &error)
return true; return true;
} }
static void close_shout_conn(ShoutOutput * sd) void
ShoutOutput::Close()
{ {
if (sd->encoder != nullptr) { if (encoder != nullptr) {
if (encoder_end(sd->encoder, IgnoreError())) if (encoder_end(encoder, IgnoreError()))
write_page(sd, IgnoreError()); write_page(this, IgnoreError());
sd->encoder->Close(); encoder->Close();
} }
if (shout_get_connected(sd->shout_conn) != SHOUTERR_UNCONNECTED && if (shout_get_connected(shout_conn) != SHOUTERR_UNCONNECTED &&
shout_close(sd->shout_conn) != SHOUTERR_SUCCESS) { shout_close(shout_conn) != SHOUTERR_SUCCESS) {
FormatWarning(shout_output_domain, FormatWarning(shout_output_domain,
"problem closing connection to shout server: %s", "problem closing connection to shout server: %s",
shout_get_error(sd->shout_conn)); shout_get_error(shout_conn));
} }
} }
static void void
my_shout_finish_driver(AudioOutput *ao) ShoutOutput::Cancel()
{ {
ShoutOutput *sd = (ShoutOutput *)ao;
delete sd;
}
static void
my_shout_drop_buffered_audio(AudioOutput *ao)
{
gcc_unused
ShoutOutput *sd = (ShoutOutput *)ao;
/* needs to be implemented for shout */ /* needs to be implemented for shout */
} }
static void
my_shout_close_device(AudioOutput *ao)
{
ShoutOutput *sd = (ShoutOutput *)ao;
close_shout_conn(sd);
}
static bool static bool
shout_connect(ShoutOutput *sd, Error &error) shout_connect(ShoutOutput *sd, Error &error)
{ {
@ -406,59 +400,51 @@ shout_connect(ShoutOutput *sd, Error &error)
} }
} }
static bool bool
my_shout_open_device(AudioOutput *ao, AudioFormat &audio_format, ShoutOutput::Open(AudioFormat &audio_format, Error &error)
Error &error)
{ {
ShoutOutput *sd = (ShoutOutput *)ao; if (!shout_connect(this, error))
if (!shout_connect(sd, error))
return false; return false;
if (!sd->encoder->Open(audio_format, error)) { if (!encoder->Open(audio_format, error)) {
shout_close(sd->shout_conn); shout_close(shout_conn);
return false; return false;
} }
if (!write_page(sd, error)) { if (!write_page(this, error)) {
sd->encoder->Close(); encoder->Close();
shout_close(sd->shout_conn); shout_close(shout_conn);
return false; return false;
} }
return true; return true;
} }
static unsigned unsigned
my_shout_delay(AudioOutput *ao) ShoutOutput::Delay() const
{ {
ShoutOutput *sd = (ShoutOutput *)ao; int delay = shout_delay(shout_conn);
int delay = shout_delay(sd->shout_conn);
if (delay < 0) if (delay < 0)
delay = 0; delay = 0;
return delay; return delay;
} }
static size_t size_t
my_shout_play(AudioOutput *ao, const void *chunk, size_t size, ShoutOutput::Play(const void *chunk, size_t size, Error &error)
Error &error)
{ {
ShoutOutput *sd = (ShoutOutput *)ao; return encoder_write(encoder, chunk, size, error) &&
write_page(this, error)
return encoder_write(sd->encoder, chunk, size, error) &&
write_page(sd, error)
? size ? size
: 0; : 0;
} }
static bool bool
my_shout_pause(AudioOutput *ao) ShoutOutput::Pause()
{ {
static char silence[1020]; static char silence[1020];
return my_shout_play(ao, silence, sizeof(silence), IgnoreError()); return Play(silence, sizeof(silence), IgnoreError());
} }
static void static void
@ -487,18 +473,16 @@ shout_tag_to_metadata(const Tag &tag, char *dest, size_t size)
snprintf(dest, size, "%s - %s", artist, title); snprintf(dest, size, "%s - %s", artist, title);
} }
static void my_shout_set_tag(AudioOutput *ao, void
const Tag &tag) ShoutOutput::SendTag(const Tag &tag)
{ {
ShoutOutput *sd = (ShoutOutput *)ao; if (encoder->plugin.tag != nullptr) {
if (sd->encoder->plugin.tag != nullptr) {
/* encoder plugin supports stream tags */ /* encoder plugin supports stream tags */
Error error; Error error;
if (!encoder_pre_tag(sd->encoder, error) || if (!encoder_pre_tag(encoder, error) ||
!write_page(sd, error) || !write_page(this, error) ||
!encoder_tag(sd->encoder, tag, error)) { !encoder_tag(encoder, tag, error)) {
LogError(error); LogError(error);
return; return;
} }
@ -507,31 +491,33 @@ static void my_shout_set_tag(AudioOutput *ao,
char song[1024]; char song[1024];
shout_tag_to_metadata(tag, song, sizeof(song)); shout_tag_to_metadata(tag, song, sizeof(song));
shout_metadata_add(sd->shout_meta, "song", song); shout_metadata_add(shout_meta, "song", song);
if (SHOUTERR_SUCCESS != shout_set_metadata(sd->shout_conn, if (SHOUTERR_SUCCESS != shout_set_metadata(shout_conn,
sd->shout_meta)) { shout_meta)) {
LogWarning(shout_output_domain, LogWarning(shout_output_domain,
"error setting shout metadata"); "error setting shout metadata");
} }
} }
write_page(sd, IgnoreError()); write_page(this, IgnoreError());
} }
typedef AudioOutputWrapper<ShoutOutput> Wrapper;
const struct AudioOutputPlugin shout_output_plugin = { const struct AudioOutputPlugin shout_output_plugin = {
"shout", "shout",
nullptr, nullptr,
my_shout_init_driver, &Wrapper::Init,
my_shout_finish_driver, &Wrapper::Finish,
nullptr, nullptr,
nullptr, nullptr,
my_shout_open_device, &Wrapper::Open,
my_shout_close_device, &Wrapper::Close,
my_shout_delay, &Wrapper::Delay,
my_shout_set_tag, &Wrapper::SendTag,
my_shout_play, &Wrapper::Play,
nullptr, nullptr,
my_shout_drop_buffered_audio, &Wrapper::Cancel,
my_shout_pause, &Wrapper::Pause,
nullptr, nullptr,
}; };