output/shout: use AudioOutputWrapper
This commit is contained in:
parent
73cadd1798
commit
e14cd92d59
@ -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,
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user