util/Error: new error passing library

Replaces GLib's GError.
This commit is contained in:
Max Kellermann
2013-08-10 18:02:44 +02:00
parent c9fcc7f148
commit 29030b54c9
256 changed files with 3269 additions and 3371 deletions

View File

@@ -23,6 +23,8 @@
#include "MixerList.hxx"
#include "pcm/PcmExport.hxx"
#include "util/Manual.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
#include <glib.h>
#include <alsa/asoundlib.h>
@@ -115,9 +117,9 @@ struct AlsaOutput {
AlsaOutput():mode(0), writei(snd_pcm_writei) {
}
bool Init(const config_param &param, GError **error_r) {
bool Init(const config_param &param, Error &error) {
return ao_base_init(&base, &alsa_output_plugin,
param, error_r);
param, error);
}
void Deinit() {
@@ -125,14 +127,7 @@ struct AlsaOutput {
}
};
/**
* The quark used for GError.domain.
*/
static inline GQuark
alsa_output_quark(void)
{
return g_quark_from_static_string("alsa_output");
}
static constexpr Domain alsa_output_domain("alsa_output");
static const char *
alsa_device(const AlsaOutput *ad)
@@ -170,11 +165,11 @@ alsa_configure(AlsaOutput *ad, const config_param &param)
}
static struct audio_output *
alsa_init(const config_param &param, GError **error_r)
alsa_init(const config_param &param, Error &error)
{
AlsaOutput *ad = new AlsaOutput();
if (!ad->Init(param, error_r)) {
if (!ad->Init(param, error)) {
delete ad;
return NULL;
}
@@ -197,7 +192,7 @@ alsa_finish(struct audio_output *ao)
}
static bool
alsa_output_enable(struct audio_output *ao, gcc_unused GError **error_r)
alsa_output_enable(struct audio_output *ao, gcc_unused Error &error)
{
AlsaOutput *ad = (AlsaOutput *)ao;
@@ -394,7 +389,7 @@ alsa_output_setup_format(snd_pcm_t *pcm, snd_pcm_hw_params_t *hwparams,
*/
static bool
alsa_setup(AlsaOutput *ad, AudioFormat &audio_format,
bool *packed_r, bool *reverse_endian_r, GError **error)
bool *packed_r, bool *reverse_endian_r, Error &error)
{
unsigned int sample_rate = audio_format.sample_rate;
unsigned int channels = audio_format.channels;
@@ -438,11 +433,11 @@ configure_hw:
err = alsa_output_setup_format(ad->pcm, hwparams, audio_format,
packed_r, reverse_endian_r);
if (err < 0) {
g_set_error(error, alsa_output_quark(), err,
"ALSA device \"%s\" does not support format %s: %s",
alsa_device(ad),
sample_format_to_string(audio_format.format),
snd_strerror(-err));
error.Format(alsa_output_domain, err,
"ALSA device \"%s\" does not support format %s: %s",
alsa_device(ad),
sample_format_to_string(audio_format.format),
snd_strerror(-err));
return false;
}
@@ -454,10 +449,10 @@ configure_hw:
err = snd_pcm_hw_params_set_channels_near(ad->pcm, hwparams,
&channels);
if (err < 0) {
g_set_error(error, alsa_output_quark(), err,
"ALSA device \"%s\" does not support %i channels: %s",
alsa_device(ad), (int)audio_format.channels,
snd_strerror(-err));
error.Format(alsa_output_domain, err,
"ALSA device \"%s\" does not support %i channels: %s",
alsa_device(ad), (int)audio_format.channels,
snd_strerror(-err));
return false;
}
audio_format.channels = (int8_t)channels;
@@ -465,9 +460,9 @@ configure_hw:
err = snd_pcm_hw_params_set_rate_near(ad->pcm, hwparams,
&sample_rate, NULL);
if (err < 0 || sample_rate == 0) {
g_set_error(error, alsa_output_quark(), err,
"ALSA device \"%s\" does not support %u Hz audio",
alsa_device(ad), audio_format.sample_rate);
error.Format(alsa_output_domain, err,
"ALSA device \"%s\" does not support %u Hz audio",
alsa_device(ad), audio_format.sample_rate);
return false;
}
audio_format.sample_rate = sample_rate;
@@ -594,16 +589,16 @@ configure_hw:
return true;
error:
g_set_error(error, alsa_output_quark(), err,
"Error opening ALSA device \"%s\" (%s): %s",
alsa_device(ad), cmd, snd_strerror(-err));
error.Format(alsa_output_domain, err,
"Error opening ALSA device \"%s\" (%s): %s",
alsa_device(ad), cmd, snd_strerror(-err));
return false;
}
static bool
alsa_setup_dsd(AlsaOutput *ad, const AudioFormat audio_format,
bool *shift8_r, bool *packed_r, bool *reverse_endian_r,
GError **error_r)
Error &error)
{
assert(ad->dsd_usb);
assert(audio_format.format == SampleFormat::DSD);
@@ -616,7 +611,7 @@ alsa_setup_dsd(AlsaOutput *ad, const AudioFormat audio_format,
const AudioFormat check = usb_format;
if (!alsa_setup(ad, usb_format, packed_r, reverse_endian_r, error_r))
if (!alsa_setup(ad, usb_format, packed_r, reverse_endian_r, error))
return false;
/* if the device allows only 32 bit, shift all DSD-over-USB
@@ -631,9 +626,9 @@ alsa_setup_dsd(AlsaOutput *ad, const AudioFormat audio_format,
if (usb_format != check) {
/* no bit-perfect playback, which is required
for DSD over USB */
g_set_error(error_r, alsa_output_quark(), 0,
"Failed to configure DSD-over-USB on ALSA device \"%s\"",
alsa_device(ad));
error.Format(alsa_output_domain,
"Failed to configure DSD-over-USB on ALSA device \"%s\"",
alsa_device(ad));
g_free(ad->silence);
return false;
}
@@ -643,7 +638,7 @@ alsa_setup_dsd(AlsaOutput *ad, const AudioFormat audio_format,
static bool
alsa_setup_or_dsd(AlsaOutput *ad, AudioFormat &audio_format,
GError **error_r)
Error &error)
{
bool shift8 = false, packed, reverse_endian;
@@ -652,9 +647,9 @@ alsa_setup_or_dsd(AlsaOutput *ad, AudioFormat &audio_format,
const bool success = dsd_usb
? alsa_setup_dsd(ad, audio_format,
&shift8, &packed, &reverse_endian,
error_r)
error)
: alsa_setup(ad, audio_format, &packed, &reverse_endian,
error_r);
error);
if (!success)
return false;
@@ -665,14 +660,14 @@ alsa_setup_or_dsd(AlsaOutput *ad, AudioFormat &audio_format,
}
static bool
alsa_open(struct audio_output *ao, AudioFormat &audio_format, GError **error)
alsa_open(struct audio_output *ao, AudioFormat &audio_format, Error &error)
{
AlsaOutput *ad = (AlsaOutput *)ao;
int err = snd_pcm_open(&ad->pcm, alsa_device(ad),
SND_PCM_STREAM_PLAYBACK, ad->mode);
if (err < 0) {
g_set_error(error, alsa_output_quark(), err,
error.Format(alsa_output_domain, err,
"Failed to open ALSA device \"%s\": %s",
alsa_device(ad), snd_strerror(err));
return false;
@@ -800,7 +795,7 @@ alsa_close(struct audio_output *ao)
static size_t
alsa_play(struct audio_output *ao, const void *chunk, size_t size,
GError **error)
Error &error)
{
AlsaOutput *ad = (AlsaOutput *)ao;
@@ -824,8 +819,7 @@ alsa_play(struct audio_output *ao, const void *chunk, size_t size,
if (ret < 0 && ret != -EAGAIN && ret != -EINTR &&
alsa_recover(ad, ret) < 0) {
g_set_error(error, alsa_output_quark(), errno,
"%s", snd_strerror(-errno));
error.Set(alsa_output_domain, ret, snd_strerror(-ret));
return 0;
}
}

View File

@@ -20,6 +20,8 @@
#include "config.h"
#include "AoOutputPlugin.hxx"
#include "OutputAPI.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
#include <ao/ao.h>
#include <glib.h>
@@ -42,26 +44,22 @@ struct AoOutput {
ao_option *options;
ao_device *device;
bool Initialize(const config_param &param, GError **error_r) {
bool Initialize(const config_param &param, Error &error) {
return ao_base_init(&base, &ao_output_plugin, param,
error_r);
error);
}
void Deinitialize() {
ao_base_finish(&base);
}
bool Configure(const config_param &param, GError **error_r);
bool Configure(const config_param &param, Error &error);
};
static inline GQuark
ao_output_quark(void)
{
return g_quark_from_static_string("ao_output");
}
static constexpr Domain ao_output_domain("ao_output");
static void
ao_output_error(GError **error_r)
ao_output_error(Error &error_r)
{
const char *error;
@@ -87,15 +85,15 @@ ao_output_error(GError **error_r)
break;
default:
error = g_strerror(errno);
error_r.SetErrno();
return;
}
g_set_error(error_r, ao_output_quark(), errno,
"%s", error);
error_r.Set(ao_output_domain, errno, error);
}
inline bool
AoOutput::Configure(const config_param &param, GError **error_r)
AoOutput::Configure(const config_param &param, Error &error)
{
const char *value;
@@ -115,16 +113,15 @@ AoOutput::Configure(const config_param &param, GError **error_r)
driver = ao_driver_id(value);
if (driver < 0) {
g_set_error(error_r, ao_output_quark(), 0,
"\"%s\" is not a valid ao driver",
value);
error.Format(ao_output_domain,
"\"%s\" is not a valid ao driver",
value);
return false;
}
ao_info *ai = ao_driver_info(driver);
if (ai == nullptr) {
g_set_error(error_r, ao_output_quark(), 0,
"problems getting driver info");
error.Set(ao_output_domain, "problems getting driver info");
return false;
}
@@ -139,9 +136,9 @@ AoOutput::Configure(const config_param &param, GError **error_r)
gchar **key_value = g_strsplit(_options[i], "=", 2);
if (key_value[0] == nullptr || key_value[1] == nullptr) {
g_set_error(error_r, ao_output_quark(), 0,
"problems parsing options \"%s\"",
_options[i]);
error.Format(ao_output_domain,
"problems parsing options \"%s\"",
_options[i]);
return false;
}
@@ -158,16 +155,16 @@ AoOutput::Configure(const config_param &param, GError **error_r)
}
static struct audio_output *
ao_output_init(const config_param &param, GError **error_r)
ao_output_init(const config_param &param, Error &error)
{
AoOutput *ad = new AoOutput();
if (!ad->Initialize(param, error_r)) {
if (!ad->Initialize(param, error)) {
delete ad;
return nullptr;
}
if (!ad->Configure(param, error_r)) {
if (!ad->Configure(param, error)) {
ad->Deinitialize();
delete ad;
return nullptr;
@@ -201,7 +198,7 @@ ao_output_close(struct audio_output *ao)
static bool
ao_output_open(struct audio_output *ao, AudioFormat &audio_format,
GError **error)
Error &error)
{
ao_sample_format format = OUR_AO_FORMAT_INITIALIZER;
AoOutput *ad = (AoOutput *)ao;
@@ -257,7 +254,7 @@ static int ao_play_deconst(ao_device *device, const void *output_samples,
static size_t
ao_output_play(struct audio_output *ao, const void *chunk, size_t size,
GError **error)
Error &error)
{
AoOutput *ad = (AoOutput *)ao;

View File

@@ -19,11 +19,14 @@
#include "config.h"
#include "FifoOutputPlugin.hxx"
#include "ConfigError.hxx"
#include "OutputAPI.hxx"
#include "Timer.hxx"
#include "system/fd_util.h"
#include "fs/Path.hxx"
#include "fs/FileSystem.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
#include "open.h"
#include <glib.h>
@@ -53,31 +56,24 @@ struct FifoOutput {
FifoOutput()
:path(Path::Null()), input(-1), output(-1), created(false) {}
bool Initialize(const config_param &param, GError **error_r) {
bool Initialize(const config_param &param, Error &error) {
return ao_base_init(&base, &fifo_output_plugin, param,
error_r);
error);
}
void Deinitialize() {
ao_base_finish(&base);
}
bool Create(GError **error_r);
bool Check(GError **error_r);
bool Create(Error &error);
bool Check(Error &error);
void Delete();
bool Open(GError **error_r);
bool Open(Error &error);
void Close();
};
/**
* The quark used for GError.domain.
*/
static inline GQuark
fifo_output_quark(void)
{
return g_quark_from_static_string("fifo_output");
}
static constexpr Domain fifo_output_domain("fifo_output");
inline void
FifoOutput::Delete()
@@ -112,12 +108,11 @@ FifoOutput::Close()
}
inline bool
FifoOutput::Create(GError **error_r)
FifoOutput::Create(Error &error)
{
if (!MakeFifo(path, 0666)) {
g_set_error(error_r, fifo_output_quark(), errno,
"Couldn't create FIFO \"%s\": %s",
path_utf8.c_str(), g_strerror(errno));
error.FormatErrno("Couldn't create FIFO \"%s\"",
path_utf8.c_str());
return false;
}
@@ -126,25 +121,24 @@ FifoOutput::Create(GError **error_r)
}
inline bool
FifoOutput::Check(GError **error_r)
FifoOutput::Check(Error &error)
{
struct stat st;
if (!StatFile(path, st)) {
if (errno == ENOENT) {
/* Path doesn't exist */
return Create(error_r);
return Create(error);
}
g_set_error(error_r, fifo_output_quark(), errno,
"Failed to stat FIFO \"%s\": %s",
path_utf8.c_str(), g_strerror(errno));
error.FormatErrno("Failed to stat FIFO \"%s\"",
path_utf8.c_str());
return false;
}
if (!S_ISFIFO(st.st_mode)) {
g_set_error(error_r, fifo_output_quark(), 0,
"\"%s\" already exists, but is not a FIFO",
path_utf8.c_str());
error.Format(fifo_output_domain,
"\"%s\" already exists, but is not a FIFO",
path_utf8.c_str());
return false;
}
@@ -152,25 +146,23 @@ FifoOutput::Check(GError **error_r)
}
inline bool
FifoOutput::Open(GError **error_r)
FifoOutput::Open(Error &error)
{
if (!Check(error_r))
if (!Check(error))
return false;
input = OpenFile(path, O_RDONLY|O_NONBLOCK|O_BINARY, 0);
if (input < 0) {
g_set_error(error_r, fifo_output_quark(), errno,
"Could not open FIFO \"%s\" for reading: %s",
path_utf8.c_str(), g_strerror(errno));
error.FormatErrno("Could not open FIFO \"%s\" for reading",
path_utf8.c_str());
Close();
return false;
}
output = OpenFile(path, O_WRONLY|O_NONBLOCK|O_BINARY, 0);
if (output < 0) {
g_set_error(error_r, fifo_output_quark(), errno,
"Could not open FIFO \"%s\" for writing: %s",
path_utf8.c_str(), g_strerror(errno));
error.FormatErrno("Could not open FIFO \"%s\" for writing",
path_utf8.c_str());
Close();
return false;
}
@@ -179,37 +171,34 @@ FifoOutput::Open(GError **error_r)
}
static bool
fifo_open(FifoOutput *fd, GError **error_r)
fifo_open(FifoOutput *fd, Error &error)
{
return fd->Open(error_r);
return fd->Open(error);
}
static struct audio_output *
fifo_output_init(const config_param &param, GError **error_r)
fifo_output_init(const config_param &param, Error &error)
{
GError *error = nullptr;
FifoOutput *fd = new FifoOutput();
fd->path = param.GetBlockPath("path", &error);
fd->path = param.GetBlockPath("path", error);
if (fd->path.IsNull()) {
delete fd;
if (error != nullptr)
g_propagate_error(error_r, error);
else
g_set_error(error_r, fifo_output_quark(), 0,
"No \"path\" parameter specified");
if (!error.IsDefined())
error.Set(config_domain,
"No \"path\" parameter specified");
return nullptr;
}
fd->path_utf8 = fd->path.ToUTF8();
if (!fd->Initialize(param, error_r)) {
if (!fd->Initialize(param, error)) {
delete fd;
return nullptr;
}
if (!fifo_open(fd, error_r)) {
if (!fifo_open(fd, error)) {
fd->Deinitialize();
delete fd;
return nullptr;
@@ -230,7 +219,7 @@ fifo_output_finish(struct audio_output *ao)
static bool
fifo_output_open(struct audio_output *ao, AudioFormat &audio_format,
gcc_unused GError **error)
gcc_unused Error &error)
{
FifoOutput *fd = (FifoOutput *)ao;
@@ -277,7 +266,7 @@ fifo_output_delay(struct audio_output *ao)
static size_t
fifo_output_play(struct audio_output *ao, const void *chunk, size_t size,
GError **error)
Error &error)
{
FifoOutput *fd = (FifoOutput *)ao;
ssize_t bytes;
@@ -301,9 +290,8 @@ fifo_output_play(struct audio_output *ao, const void *chunk, size_t size,
continue;
}
g_set_error(error, fifo_output_quark(), errno,
"Failed to write to FIFO %s: %s",
fd->path_utf8.c_str(), g_strerror(errno));
error.FormatErrno("Failed to write to FIFO %s",
fd->path_utf8.c_str());
return 0;
}
}

View File

@@ -431,10 +431,9 @@ HttpdClient::OnSocketInput(const void *data, size_t length)
}
void
HttpdClient::OnSocketError(GError *error)
HttpdClient::OnSocketError(Error &&error)
{
g_warning("error on HTTP client: %s", error->message);
g_error_free(error);
g_warning("error on HTTP client: %s", error.GetMessage());
}
void

View File

@@ -179,7 +179,7 @@ protected:
virtual bool OnSocketReady(unsigned flags) override;
virtual InputResult OnSocketInput(const void *data,
size_t length) override;
virtual void OnSocketError(GError *error) override;
virtual void OnSocketError(Error &&error) override;
virtual void OnSocketClosed() override;
};

View File

@@ -33,6 +33,7 @@
#include <forward_list>
struct config_param;
class Error;
class EventLoop;
class ServerSocket;
class HttpdClient;
@@ -123,21 +124,20 @@ struct HttpdOutput final : private ServerSocket {
HttpdOutput(EventLoop &_loop);
~HttpdOutput();
bool Configure(const config_param &param, GError **error_r);
bool Configure(const config_param &param, Error &error);
bool Bind(GError **error_r);
bool Bind(Error &error);
void Unbind();
/**
* Caller must lock the mutex.
*/
bool OpenEncoder(AudioFormat &audio_format,
GError **error_r);
bool OpenEncoder(AudioFormat &audio_format, Error &error);
/**
* Caller must lock the mutex.
*/
bool Open(AudioFormat &audio_format, GError **error_r);
bool Open(AudioFormat &audio_format, Error &error);
/**
* Caller must lock the mutex.
@@ -194,7 +194,7 @@ struct HttpdOutput final : private ServerSocket {
*/
void BroadcastFromEncoder();
bool EncodeAndPlay(const void *chunk, size_t size, GError **error_r);
bool EncodeAndPlay(const void *chunk, size_t size, Error &error);
void SendTag(const Tag *tag);

View File

@@ -29,6 +29,8 @@
#include "IcyMetaDataServer.hxx"
#include "system/fd_util.h"
#include "Main.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
#include <assert.h>
@@ -45,14 +47,7 @@
#undef G_LOG_DOMAIN
#define G_LOG_DOMAIN "httpd_output"
/**
* The quark used for GError.domain.
*/
static inline GQuark
httpd_output_quark(void)
{
return g_quark_from_static_string("httpd_output");
}
static constexpr Domain httpd_output_domain("httpd_output");
inline
HttpdOutput::HttpdOutput(EventLoop &_loop)
@@ -73,12 +68,12 @@ HttpdOutput::~HttpdOutput()
}
inline bool
HttpdOutput::Bind(GError **error_r)
HttpdOutput::Bind(Error &error)
{
open = false;
const ScopeLock protect(mutex);
return ServerSocket::Open(error_r);
return ServerSocket::Open(error);
}
inline void
@@ -91,7 +86,7 @@ HttpdOutput::Unbind()
}
inline bool
HttpdOutput::Configure(const config_param &param, GError **error_r)
HttpdOutput::Configure(const config_param &param, Error &error)
{
/* read configuration */
name = param.GetBlockValue("name", "Set name in config");
@@ -104,8 +99,8 @@ HttpdOutput::Configure(const config_param &param, GError **error_r)
param.GetBlockValue("encoder", "vorbis");
const auto encoder_plugin = encoder_plugin_get(encoder_name);
if (encoder_plugin == NULL) {
g_set_error(error_r, httpd_output_quark(), 0,
"No such encoder: %s", encoder_name);
error.Format(httpd_output_domain,
"No such encoder: %s", encoder_name);
return false;
}
@@ -116,14 +111,14 @@ HttpdOutput::Configure(const config_param &param, GError **error_r)
const char *bind_to_address = param.GetBlockValue("bind_to_address");
bool success = bind_to_address != NULL &&
strcmp(bind_to_address, "any") != 0
? AddHost(bind_to_address, port, error_r)
: AddPort(port, error_r);
? AddHost(bind_to_address, port, error)
: AddPort(port, error);
if (!success)
return false;
/* initialize encoder */
encoder = encoder_init(*encoder_plugin, param, error_r);
encoder = encoder_init(*encoder_plugin, param, error);
if (encoder == nullptr)
return false;
@@ -136,18 +131,17 @@ HttpdOutput::Configure(const config_param &param, GError **error_r)
}
static struct audio_output *
httpd_output_init(const struct config_param &param,
GError **error_r)
httpd_output_init(const config_param &param, Error &error)
{
HttpdOutput *httpd = new HttpdOutput(*main_loop);
if (!ao_base_init(&httpd->base, &httpd_output_plugin, param,
error_r)) {
error)) {
delete httpd;
return nullptr;
}
if (!httpd->Configure(param, error_r)) {
if (!httpd->Configure(param, error)) {
ao_base_finish(&httpd->base);
delete httpd;
return nullptr;
@@ -205,7 +199,8 @@ HttpdOutput::OnAccept(int fd, const sockaddr &address,
#ifdef HAVE_LIBWRAP
if (address.sa_family != AF_UNIX) {
char *hostaddr = sockaddr_to_string(&address, address_length, NULL);
char *hostaddr = sockaddr_to_string(&address, address_length,
IgnoreError());
const char *progname = g_get_prgname();
struct request_info req;
@@ -249,7 +244,7 @@ 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(encoder, NULL);
encoder_flush(encoder, IgnoreError());
unflushed_input = 0;
}
@@ -273,11 +268,11 @@ HttpdOutput::ReadPage()
}
static bool
httpd_output_enable(struct audio_output *ao, GError **error_r)
httpd_output_enable(struct audio_output *ao, Error &error)
{
HttpdOutput *httpd = Cast(ao);
return httpd->Bind(error_r);
return httpd->Bind(error);
}
static void
@@ -289,7 +284,7 @@ httpd_output_disable(struct audio_output *ao)
}
inline bool
HttpdOutput::OpenEncoder(AudioFormat &audio_format, GError **error)
HttpdOutput::OpenEncoder(AudioFormat &audio_format, Error &error)
{
if (!encoder_open(encoder, audio_format, error))
return false;
@@ -305,14 +300,14 @@ HttpdOutput::OpenEncoder(AudioFormat &audio_format, GError **error)
}
inline bool
HttpdOutput::Open(AudioFormat &audio_format, GError **error_r)
HttpdOutput::Open(AudioFormat &audio_format, Error &error)
{
assert(!open);
assert(clients.empty());
/* open the encoder */
if (!OpenEncoder(audio_format, error_r))
if (!OpenEncoder(audio_format, error))
return false;
/* initialize other attributes */
@@ -327,7 +322,7 @@ HttpdOutput::Open(AudioFormat &audio_format, GError **error_r)
static bool
httpd_output_open(struct audio_output *ao, AudioFormat &audio_format,
GError **error)
Error &error)
{
HttpdOutput *httpd = Cast(ao);
@@ -439,9 +434,9 @@ HttpdOutput::BroadcastFromEncoder()
}
inline bool
HttpdOutput::EncodeAndPlay(const void *chunk, size_t size, GError **error_r)
HttpdOutput::EncodeAndPlay(const void *chunk, size_t size, Error &error)
{
if (!encoder_write(encoder, chunk, size, error_r))
if (!encoder_write(encoder, chunk, size, error))
return false;
unflushed_input += size;
@@ -452,12 +447,12 @@ HttpdOutput::EncodeAndPlay(const void *chunk, size_t size, GError **error_r)
static size_t
httpd_output_play(struct audio_output *ao, const void *chunk, size_t size,
GError **error_r)
Error &error)
{
HttpdOutput *httpd = Cast(ao);
if (httpd->LockHasClients()) {
if (!httpd->EncodeAndPlay(chunk, size, error_r))
if (!httpd->EncodeAndPlay(chunk, size, error))
return 0;
}
@@ -476,7 +471,7 @@ httpd_output_pause(struct audio_output *ao)
if (httpd->LockHasClients()) {
static const char silence[1020] = { 0 };
return httpd_output_play(ao, silence, sizeof(silence),
NULL) > 0;
IgnoreError()) > 0;
} else {
return true;
}
@@ -492,13 +487,13 @@ HttpdOutput::SendTag(const Tag *tag)
/* flush the current stream, and end it */
encoder_pre_tag(encoder, NULL);
encoder_pre_tag(encoder, IgnoreError());
BroadcastFromEncoder();
/* send the tag to the encoder - which starts a new
stream now */
encoder_tag(encoder, tag, NULL);
encoder_tag(encoder, tag, IgnoreError());
/* the first page generated by the encoder will now be
used as the new "header" page, which is sent to all

View File

@@ -20,6 +20,9 @@
#include "config.h"
#include "JackOutputPlugin.hxx"
#include "OutputAPI.hxx"
#include "ConfigError.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
#include <assert.h>
@@ -82,7 +85,7 @@ struct JackOutput {
*/
bool pause;
bool Initialize(const config_param &param, GError **error_r) {
bool Initialize(const config_param &param, Error &error_r) {
return ao_base_init(&base, &jack_output_plugin, param,
error_r);
}
@@ -92,14 +95,7 @@ struct JackOutput {
}
};
/**
* The quark used for GError.domain.
*/
static inline GQuark
jack_output_quark(void)
{
return g_quark_from_static_string("jack_output");
}
static constexpr Domain jack_output_domain("jack_output");
/**
* Determine the number of frames guaranteed to be available on all
@@ -250,7 +246,7 @@ mpd_jack_disconnect(JackOutput *jd)
* (e.g. register callbacks).
*/
static bool
mpd_jack_connect(JackOutput *jd, GError **error_r)
mpd_jack_connect(JackOutput *jd, Error &error)
{
jack_status_t status;
@@ -261,9 +257,9 @@ mpd_jack_connect(JackOutput *jd, GError **error_r)
jd->client = jack_client_open(jd->name, jd->options, &status,
jd->server_name);
if (jd->client == nullptr) {
g_set_error(error_r, jack_output_quark(), 0,
"Failed to connect to JACK server, status=%d",
status);
error.Format(jack_output_domain, status,
"Failed to connect to JACK server, status=%d",
status);
return false;
}
@@ -276,9 +272,9 @@ mpd_jack_connect(JackOutput *jd, GError **error_r)
JACK_DEFAULT_AUDIO_TYPE,
JackPortIsOutput, 0);
if (jd->ports[i] == nullptr) {
g_set_error(error_r, jack_output_quark(), 0,
"Cannot register output port \"%s\"",
jd->source_ports[i]);
error.Format(jack_output_domain,
"Cannot register output port \"%s\"",
jd->source_ports[i]);
mpd_jack_disconnect(jd);
return false;
}
@@ -294,16 +290,16 @@ mpd_jack_test_default_device(void)
}
static unsigned
parse_port_list(int line, const char *source, char **dest, GError **error_r)
parse_port_list(int line, const char *source, char **dest, Error &error)
{
char **list = g_strsplit(source, ",", 0);
unsigned n = 0;
for (n = 0; list[n] != nullptr; ++n) {
if (n >= MAX_PORTS) {
g_set_error(error_r, jack_output_quark(), 0,
"too many port names in line %d",
line);
error.Format(config_domain,
"too many port names in line %d",
line);
return 0;
}
@@ -313,9 +309,9 @@ parse_port_list(int line, const char *source, char **dest, GError **error_r)
g_free(list);
if (n == 0) {
g_set_error(error_r, jack_output_quark(), 0,
"at least one port name expected in line %d",
line);
error.Format(config_domain,
"at least one port name expected in line %d",
line);
return 0;
}
@@ -323,11 +319,11 @@ parse_port_list(int line, const char *source, char **dest, GError **error_r)
}
static struct audio_output *
mpd_jack_init(const config_param &param, GError **error_r)
mpd_jack_init(const config_param &param, Error &error)
{
JackOutput *jd = new JackOutput();
if (!jd->Initialize(param, error_r)) {
if (!jd->Initialize(param, error)) {
delete jd;
return nullptr;
}
@@ -355,7 +351,7 @@ mpd_jack_init(const config_param &param, GError **error_r)
value = param.GetBlockValue("source_ports", "left,right");
jd->num_source_ports = parse_port_list(param.line, value,
jd->source_ports, error_r);
jd->source_ports, error);
if (jd->num_source_ports == 0)
return nullptr;
@@ -373,7 +369,7 @@ mpd_jack_init(const config_param &param, GError **error_r)
if (value != nullptr) {
jd->num_destination_ports =
parse_port_list(param.line, value,
jd->destination_ports, error_r);
jd->destination_ports, error);
if (jd->num_destination_ports == 0)
return nullptr;
} else {
@@ -414,14 +410,14 @@ mpd_jack_finish(struct audio_output *ao)
}
static bool
mpd_jack_enable(struct audio_output *ao, GError **error_r)
mpd_jack_enable(struct audio_output *ao, Error &error)
{
JackOutput *jd = (JackOutput *)ao;
for (unsigned i = 0; i < jd->num_source_ports; ++i)
jd->ringbuffer[i] = nullptr;
return mpd_jack_connect(jd, error_r);
return mpd_jack_connect(jd, error);
}
static void
@@ -460,7 +456,7 @@ mpd_jack_stop(JackOutput *jd)
}
static bool
mpd_jack_start(JackOutput *jd, GError **error_r)
mpd_jack_start(JackOutput *jd, Error &error)
{
const char *destination_ports[MAX_PORTS], **jports;
const char *duplicate_port = nullptr;
@@ -484,8 +480,7 @@ mpd_jack_start(JackOutput *jd, GError **error_r)
}
if ( jack_activate(jd->client) ) {
g_set_error(error_r, jack_output_quark(), 0,
"cannot activate client");
error.Set(jack_output_domain, "cannot activate client");
mpd_jack_stop(jd);
return false;
}
@@ -496,8 +491,7 @@ mpd_jack_start(JackOutput *jd, GError **error_r)
jports = jack_get_ports(jd->client, nullptr, nullptr,
JackPortIsPhysical | JackPortIsInput);
if (jports == nullptr) {
g_set_error(error_r, jack_output_quark(), 0,
"no ports found");
error.Set(jack_output_domain, "no ports found");
mpd_jack_stop(jd);
return false;
}
@@ -551,9 +545,9 @@ mpd_jack_start(JackOutput *jd, GError **error_r)
ret = jack_connect(jd->client, jack_port_name(jd->ports[i]),
destination_ports[i]);
if (ret != 0) {
g_set_error(error_r, jack_output_quark(), 0,
"Not a valid JACK port: %s",
destination_ports[i]);
error.Format(jack_output_domain,
"Not a valid JACK port: %s",
destination_ports[i]);
if (jports != nullptr)
free(jports);
@@ -571,9 +565,9 @@ mpd_jack_start(JackOutput *jd, GError **error_r)
ret = jack_connect(jd->client, jack_port_name(jd->ports[0]),
duplicate_port);
if (ret != 0) {
g_set_error(error_r, jack_output_quark(), 0,
"Not a valid JACK port: %s",
duplicate_port);
error.Format(jack_output_domain,
"Not a valid JACK port: %s",
duplicate_port);
if (jports != nullptr)
free(jports);
@@ -591,7 +585,7 @@ mpd_jack_start(JackOutput *jd, GError **error_r)
static bool
mpd_jack_open(struct audio_output *ao, AudioFormat &audio_format,
GError **error_r)
Error &error)
{
JackOutput *jd = (JackOutput *)ao;
@@ -602,13 +596,13 @@ mpd_jack_open(struct audio_output *ao, AudioFormat &audio_format,
if (jd->client != nullptr && jd->shutdown)
mpd_jack_disconnect(jd);
if (jd->client == nullptr && !mpd_jack_connect(jd, error_r))
if (jd->client == nullptr && !mpd_jack_connect(jd, error))
return false;
set_audioformat(jd, audio_format);
jd->audio_format = audio_format;
if (!mpd_jack_start(jd, error_r))
if (!mpd_jack_start(jd, error))
return false;
return true;
@@ -701,7 +695,7 @@ mpd_jack_write_samples(JackOutput *jd, const void *src,
static size_t
mpd_jack_play(struct audio_output *ao, const void *chunk, size_t size,
GError **error_r)
Error &error)
{
JackOutput *jd = (JackOutput *)ao;
const size_t frame_size = jd->audio_format.GetFrameSize();
@@ -714,9 +708,9 @@ mpd_jack_play(struct audio_output *ao, const void *chunk, size_t size,
while (true) {
if (jd->shutdown) {
g_set_error(error_r, jack_output_quark(), 0,
"Refusing to play, because "
"there is no client thread");
error.Set(jack_output_domain,
"Refusing to play, because "
"there is no client thread");
return 0;
}

View File

@@ -31,9 +31,9 @@ struct NullOutput {
Timer *timer;
bool Initialize(const config_param &param, GError **error_r) {
bool Initialize(const config_param &param, Error &error) {
return ao_base_init(&base, &null_output_plugin, param,
error_r);
error);
}
void Deinitialize() {
@@ -42,11 +42,11 @@ struct NullOutput {
};
static struct audio_output *
null_init(const config_param &param, GError **error_r)
null_init(const config_param &param, Error &error)
{
NullOutput *nd = new NullOutput();
if (!nd->Initialize(param, error_r)) {
if (!nd->Initialize(param, error)) {
delete nd;
return nullptr;
}
@@ -67,7 +67,7 @@ null_finish(struct audio_output *ao)
static bool
null_open(struct audio_output *ao, AudioFormat &audio_format,
gcc_unused GError **error)
gcc_unused Error &error)
{
NullOutput *nd = (NullOutput *)ao;
@@ -98,7 +98,7 @@ null_delay(struct audio_output *ao)
static size_t
null_play(struct audio_output *ao, gcc_unused const void *chunk, size_t size,
gcc_unused GError **error)
gcc_unused Error &error)
{
NullOutput *nd = (NullOutput *)ao;
Timer *timer = nd->timer;

View File

@@ -21,6 +21,8 @@
#include "OSXOutputPlugin.hxx"
#include "OutputAPI.hxx"
#include "util/fifo_buffer.h"
#include "util/Error.hxx"
#include "util/Domain.hxx"
#include "thread/Mutex.hxx"
#include "thread/Cond.hxx"
@@ -47,14 +49,7 @@ struct OSXOutput {
struct fifo_buffer *buffer;
};
/**
* The quark used for GError.domain.
*/
static inline GQuark
osx_output_quark(void)
{
return g_quark_from_static_string("osx_output");
}
static constexpr Domain osx_output_domain("osx_output");
static bool
osx_output_test_default_device(void)
@@ -85,10 +80,10 @@ osx_output_configure(OSXOutput *oo, const config_param &param)
}
static struct audio_output *
osx_output_init(const config_param &param, GError **error_r)
osx_output_init(const config_param &param, Error &error)
{
OSXOutput *oo = new OSXOutput();
if (!ao_base_init(&oo->base, &osx_output_plugin, param, error_r)) {
if (!ao_base_init(&oo->base, &osx_output_plugin, param, error)) {
delete oo;
return NULL;
}
@@ -107,7 +102,7 @@ osx_output_finish(struct audio_output *ao)
}
static bool
osx_output_set_device(OSXOutput *oo, GError **error)
osx_output_set_device(OSXOutput *oo, Error &error)
{
bool ret = true;
OSStatus status;
@@ -124,9 +119,9 @@ osx_output_set_device(OSXOutput *oo, GError **error)
&size,
NULL);
if (status != noErr) {
g_set_error(error, osx_output_quark(), status,
"Unable to determine number of OS X audio devices: %s",
GetMacOSStatusCommentString(status));
error.Format(osx_output_domain, status,
"Unable to determine number of OS X audio devices: %s",
GetMacOSStatusCommentString(status));
ret = false;
goto done;
}
@@ -138,9 +133,9 @@ osx_output_set_device(OSXOutput *oo, GError **error)
&size,
deviceids);
if (status != noErr) {
g_set_error(error, osx_output_quark(), status,
"Unable to determine OS X audio device IDs: %s",
GetMacOSStatusCommentString(status));
error.Format(osx_output_domain, status,
"Unable to determine OS X audio device IDs: %s",
GetMacOSStatusCommentString(status));
ret = false;
goto done;
}
@@ -152,11 +147,11 @@ osx_output_set_device(OSXOutput *oo, GError **error)
kAudioDevicePropertyDeviceName,
&size, name);
if (status != noErr) {
g_set_error(error, osx_output_quark(), status,
"Unable to determine OS X device name "
"(device %u): %s",
(unsigned int) deviceids[i],
GetMacOSStatusCommentString(status));
error.Format(osx_output_domain, status,
"Unable to determine OS X device name "
"(device %u): %s",
(unsigned int) deviceids[i],
GetMacOSStatusCommentString(status));
ret = false;
goto done;
}
@@ -180,9 +175,9 @@ osx_output_set_device(OSXOutput *oo, GError **error)
&(deviceids[i]),
sizeof(AudioDeviceID));
if (status != noErr) {
g_set_error(error, osx_output_quark(), status,
"Unable to set OS X audio output device: %s",
GetMacOSStatusCommentString(status));
error.Format(osx_output_domain, status,
"Unable to set OS X audio output device: %s",
GetMacOSStatusCommentString(status));
ret = false;
goto done;
}
@@ -237,7 +232,7 @@ osx_render(void *vdata,
}
static bool
osx_output_enable(struct audio_output *ao, GError **error_r)
osx_output_enable(struct audio_output *ao, Error &error)
{
OSXOutput *oo = (OSXOutput *)ao;
@@ -250,20 +245,20 @@ osx_output_enable(struct audio_output *ao, GError **error_r)
Component comp = FindNextComponent(NULL, &desc);
if (comp == 0) {
g_set_error(error_r, osx_output_quark(), 0,
"Error finding OS X component");
error.Set(osx_output_domain,
"Error finding OS X component");
return false;
}
OSStatus status = OpenAComponent(comp, &oo->au);
if (status != noErr) {
g_set_error(error_r, osx_output_quark(), status,
"Unable to open OS X component: %s",
GetMacOSStatusCommentString(status));
error.Format(osx_output_domain, status,
"Unable to open OS X component: %s",
GetMacOSStatusCommentString(status));
return false;
}
if (!osx_output_set_device(oo, error_r)) {
if (!osx_output_set_device(oo, error)) {
CloseComponent(oo->au);
return false;
}
@@ -279,8 +274,8 @@ osx_output_enable(struct audio_output *ao, GError **error_r)
&callback, sizeof(callback));
if (result != noErr) {
CloseComponent(oo->au);
g_set_error(error_r, osx_output_quark(), result,
"unable to set callback for OS X audio unit");
error.Set(osx_output_domain, result,
"unable to set callback for OS X audio unit");
return false;
}
@@ -316,7 +311,8 @@ osx_output_close(struct audio_output *ao)
}
static bool
osx_output_open(struct audio_output *ao, AudioFormat &audio_format, GError **error)
osx_output_open(struct audio_output *ao, AudioFormat &audio_format,
Error &error)
{
OSXOutput *od = (OSXOutput *)ao;
@@ -359,16 +355,16 @@ osx_output_open(struct audio_output *ao, AudioFormat &audio_format, GError **err
&stream_description,
sizeof(stream_description));
if (result != noErr) {
g_set_error(error, osx_output_quark(), result,
"Unable to set format on OS X device");
error.Set(osx_output_domain, result,
"Unable to set format on OS X device");
return false;
}
OSStatus status = AudioUnitInitialize(od->au);
if (status != noErr) {
g_set_error(error, osx_output_quark(), status,
"Unable to initialize OS X audio unit: %s",
GetMacOSStatusCommentString(status));
error.Set(osx_output_domain, status,
"Unable to initialize OS X audio unit: %s",
GetMacOSStatusCommentString(status));
return false;
}
@@ -379,9 +375,9 @@ osx_output_open(struct audio_output *ao, AudioFormat &audio_format, GError **err
status = AudioOutputUnitStart(od->au);
if (status != 0) {
AudioUnitUninitialize(od->au);
g_set_error(error, osx_output_quark(), status,
"unable to start audio output: %s",
GetMacOSStatusCommentString(status));
error.Format(osx_output_domain, status,
"unable to start audio output: %s",
GetMacOSStatusCommentString(status));
return false;
}
@@ -390,7 +386,7 @@ osx_output_open(struct audio_output *ao, AudioFormat &audio_format, GError **err
static size_t
osx_output_play(struct audio_output *ao, const void *chunk, size_t size,
gcc_unused GError **error)
gcc_unused Error &error)
{
OSXOutput *od = (OSXOutput *)ao;

View File

@@ -20,6 +20,8 @@
#include "config.h"
#include "OpenALOutputPlugin.hxx"
#include "OutputAPI.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
#include <glib.h>
@@ -49,7 +51,7 @@ struct OpenALOutput {
ALenum format;
ALuint frequency;
bool Initialize(const config_param &param, GError **error_r) {
bool Initialize(const config_param &param, Error &error_r) {
return ao_base_init(&base, &openal_output_plugin, param,
error_r);
}
@@ -59,12 +61,7 @@ struct OpenALOutput {
}
};
gcc_const
static inline GQuark
openal_output_quark(void)
{
return g_quark_from_static_string("openal_output");
}
static constexpr Domain openal_output_domain("openal_output");
static ALenum
openal_audio_format(AudioFormat &audio_format)
@@ -115,24 +112,23 @@ openal_is_playing(const OpenALOutput *od)
}
static bool
openal_setup_context(OpenALOutput *od,
GError **error)
openal_setup_context(OpenALOutput *od, Error &error)
{
od->device = alcOpenDevice(od->device_name);
if (od->device == nullptr) {
g_set_error(error, openal_output_quark(), 0,
"Error opening OpenAL device \"%s\"\n",
od->device_name);
error.Format(openal_output_domain,
"Error opening OpenAL device \"%s\"",
od->device_name);
return false;
}
od->context = alcCreateContext(od->device, nullptr);
if (od->context == nullptr) {
g_set_error(error, openal_output_quark(), 0,
"Error creating context for \"%s\"\n",
od->device_name);
error.Format(openal_output_domain,
"Error creating context for \"%s\"",
od->device_name);
alcCloseDevice(od->device);
return false;
}
@@ -141,7 +137,7 @@ openal_setup_context(OpenALOutput *od,
}
static struct audio_output *
openal_init(const config_param &param, GError **error_r)
openal_init(const config_param &param, Error &error)
{
const char *device_name = param.GetBlockValue("device");
if (device_name == nullptr) {
@@ -149,7 +145,7 @@ openal_init(const config_param &param, GError **error_r)
}
OpenALOutput *od = new OpenALOutput();
if (!od->Initialize(param, error_r)) {
if (!od->Initialize(param, error)) {
delete od;
return nullptr;
}
@@ -170,7 +166,7 @@ openal_finish(struct audio_output *ao)
static bool
openal_open(struct audio_output *ao, AudioFormat &audio_format,
GError **error)
Error &error)
{
OpenALOutput *od = (OpenALOutput *)ao;
@@ -184,16 +180,14 @@ openal_open(struct audio_output *ao, AudioFormat &audio_format,
alGenBuffers(NUM_BUFFERS, od->buffers);
if (alGetError() != AL_NO_ERROR) {
g_set_error(error, openal_output_quark(), 0,
"Failed to generate buffers");
error.Set(openal_output_domain, "Failed to generate buffers");
return false;
}
alGenSources(1, &od->source);
if (alGetError() != AL_NO_ERROR) {
g_set_error(error, openal_output_quark(), 0,
"Failed to generate source");
error.Set(openal_output_domain, "Failed to generate source");
alDeleteBuffers(NUM_BUFFERS, od->buffers);
return false;
}
@@ -231,7 +225,7 @@ openal_delay(struct audio_output *ao)
static size_t
openal_play(struct audio_output *ao, const void *chunk, size_t size,
gcc_unused GError **error)
gcc_unused Error &error)
{
OpenALOutput *od = (OpenALOutput *)ao;
ALuint buffer;

View File

@@ -22,6 +22,8 @@
#include "OutputAPI.hxx"
#include "MixerList.hxx"
#include "system/fd_util.h"
#include "util/Error.hxx"
#include "util/Domain.hxx"
#include <glib.h>
@@ -80,7 +82,7 @@ struct OssOutput {
OssOutput():fd(-1), device(nullptr) {}
bool Initialize(const config_param &param, GError **error_r) {
bool Initialize(const config_param &param, Error &error_r) {
return ao_base_init(&base, &oss_output_plugin, param,
error_r);
}
@@ -90,14 +92,7 @@ struct OssOutput {
}
};
/**
* The quark used for GError.domain.
*/
static inline GQuark
oss_output_quark(void)
{
return g_quark_from_static_string("oss_output");
}
static constexpr Domain oss_output_domain("oss_output");
enum oss_stat {
OSS_STAT_NO_ERROR = 0,
@@ -155,7 +150,7 @@ oss_output_test_default_device(void)
}
static struct audio_output *
oss_open_default(GError **error)
oss_open_default(Error &error)
{
int err[G_N_ELEMENTS(default_devices)];
enum oss_stat ret[G_N_ELEMENTS(default_devices)];
@@ -196,18 +191,18 @@ oss_open_default(GError **error)
}
}
g_set_error(error, oss_output_quark(), 0,
"error trying to open default OSS device");
error.Set(oss_output_domain,
"error trying to open default OSS device");
return NULL;
}
static struct audio_output *
oss_output_init(const config_param &param, GError **error_r)
oss_output_init(const config_param &param, Error &error)
{
const char *device = param.GetBlockValue("device");
if (device != NULL) {
OssOutput *od = new OssOutput();
if (!od->Initialize(param, error_r)) {
if (!od->Initialize(param, error)) {
delete od;
return NULL;
}
@@ -216,7 +211,7 @@ oss_output_init(const config_param &param, GError **error_r)
return &od->base;
}
return oss_open_default(error_r);
return oss_open_default(error);
}
static void
@@ -231,7 +226,7 @@ oss_output_finish(struct audio_output *ao)
#ifdef AFMT_S24_PACKED
static bool
oss_output_enable(struct audio_output *ao, gcc_unused GError **error_r)
oss_output_enable(struct audio_output *ao, gcc_unused Error &error)
{
OssOutput *od = (OssOutput *)ao;
@@ -269,16 +264,16 @@ enum oss_setup_result {
/**
* Invoke an ioctl on the OSS file descriptor. On success, SUCCESS is
* returned. If the parameter is not supported, UNSUPPORTED is
* returned. Any other failure returns ERROR and allocates a GError.
* returned. Any other failure returns ERROR and allocates an #Error.
*/
static enum oss_setup_result
oss_try_ioctl_r(int fd, unsigned long request, int *value_r,
const char *msg, GError **error_r)
const char *msg, Error &error)
{
assert(fd >= 0);
assert(value_r != NULL);
assert(msg != NULL);
assert(error_r == NULL || *error_r == NULL);
assert(!error.IsDefined());
int ret = ioctl(fd, request, value_r);
if (ret >= 0)
@@ -287,19 +282,18 @@ oss_try_ioctl_r(int fd, unsigned long request, int *value_r,
if (errno == EINVAL)
return UNSUPPORTED;
g_set_error(error_r, oss_output_quark(), errno,
"%s: %s", msg, g_strerror(errno));
error.SetErrno(msg);
return ERROR;
}
/**
* Invoke an ioctl on the OSS file descriptor. On success, SUCCESS is
* returned. If the parameter is not supported, UNSUPPORTED is
* returned. Any other failure returns ERROR and allocates a GError.
* returned. Any other failure returns ERROR and allocates an #Error.
*/
static enum oss_setup_result
oss_try_ioctl(int fd, unsigned long request, int value,
const char *msg, GError **error_r)
const char *msg, Error &error_r)
{
return oss_try_ioctl_r(fd, request, &value, msg, error_r);
}
@@ -309,12 +303,12 @@ oss_try_ioctl(int fd, unsigned long request, int value,
* specified number is not supported.
*/
static bool
oss_setup_channels(int fd, AudioFormat &audio_format, GError **error_r)
oss_setup_channels(int fd, AudioFormat &audio_format, Error &error)
{
const char *const msg = "Failed to set channel count";
int channels = audio_format.channels;
enum oss_setup_result result =
oss_try_ioctl_r(fd, SNDCTL_DSP_CHANNELS, &channels, msg, error_r);
oss_try_ioctl_r(fd, SNDCTL_DSP_CHANNELS, &channels, msg, error);
switch (result) {
case SUCCESS:
if (!audio_valid_channel_count(channels))
@@ -337,7 +331,7 @@ oss_setup_channels(int fd, AudioFormat &audio_format, GError **error_r)
channels = i;
result = oss_try_ioctl_r(fd, SNDCTL_DSP_CHANNELS, &channels,
msg, error_r);
msg, error);
switch (result) {
case SUCCESS:
if (!audio_valid_channel_count(channels))
@@ -354,7 +348,7 @@ oss_setup_channels(int fd, AudioFormat &audio_format, GError **error_r)
}
}
g_set_error(error_r, oss_output_quark(), EINVAL, "%s", msg);
error.Set(oss_output_domain, msg);
return false;
}
@@ -364,13 +358,13 @@ oss_setup_channels(int fd, AudioFormat &audio_format, GError **error_r)
*/
static bool
oss_setup_sample_rate(int fd, AudioFormat &audio_format,
GError **error_r)
Error &error)
{
const char *const msg = "Failed to set sample rate";
int sample_rate = audio_format.sample_rate;
enum oss_setup_result result =
oss_try_ioctl_r(fd, SNDCTL_DSP_SPEED, &sample_rate,
msg, error_r);
msg, error);
switch (result) {
case SUCCESS:
if (!audio_valid_sample_rate(sample_rate))
@@ -393,7 +387,7 @@ oss_setup_sample_rate(int fd, AudioFormat &audio_format,
continue;
result = oss_try_ioctl_r(fd, SNDCTL_DSP_SPEED, &sample_rate,
msg, error_r);
msg, error);
switch (result) {
case SUCCESS:
if (!audio_valid_sample_rate(sample_rate))
@@ -410,7 +404,7 @@ oss_setup_sample_rate(int fd, AudioFormat &audio_format,
}
}
g_set_error(error_r, oss_output_quark(), EINVAL, "%s", msg);
error.Set(oss_output_domain, msg);
return false;
}
@@ -498,7 +492,7 @@ oss_probe_sample_format(int fd, SampleFormat sample_format,
#ifdef AFMT_S24_PACKED
PcmExport &pcm_export,
#endif
GError **error_r)
Error &error)
{
int oss_format = sample_format_to_oss(sample_format);
if (oss_format == AFMT_QUERY)
@@ -507,7 +501,7 @@ oss_probe_sample_format(int fd, SampleFormat sample_format,
enum oss_setup_result result =
oss_try_ioctl_r(fd, SNDCTL_DSP_SAMPLESIZE,
&oss_format,
"Failed to set sample format", error_r);
"Failed to set sample format", error);
#ifdef AFMT_S24_PACKED
if (result == UNSUPPORTED && sample_format == SampleFormat::S24_P32) {
@@ -516,7 +510,7 @@ oss_probe_sample_format(int fd, SampleFormat sample_format,
oss_format = AFMT_S24_PACKED;
result = oss_try_ioctl_r(fd, SNDCTL_DSP_SAMPLESIZE,
&oss_format,
"Failed to set sample format", error_r);
"Failed to set sample format", error);
}
#endif
@@ -550,7 +544,7 @@ oss_setup_sample_format(int fd, AudioFormat &audio_format,
#ifdef AFMT_S24_PACKED
PcmExport &pcm_export,
#endif
GError **error_r)
Error &error)
{
SampleFormat mpd_format;
enum oss_setup_result result =
@@ -559,7 +553,7 @@ oss_setup_sample_format(int fd, AudioFormat &audio_format,
#ifdef AFMT_S24_PACKED
pcm_export,
#endif
error_r);
error);
switch (result) {
case SUCCESS:
audio_format.format = mpd_format;
@@ -597,7 +591,7 @@ oss_setup_sample_format(int fd, AudioFormat &audio_format,
#ifdef AFMT_S24_PACKED
pcm_export,
#endif
error_r);
error);
switch (result) {
case SUCCESS:
audio_format.format = mpd_format;
@@ -611,8 +605,7 @@ oss_setup_sample_format(int fd, AudioFormat &audio_format,
}
}
g_set_error_literal(error_r, oss_output_quark(), EINVAL,
"Failed to set sample format");
error.Set(oss_output_domain, "Failed to set sample format");
return false;
}
@@ -621,30 +614,29 @@ oss_setup_sample_format(int fd, AudioFormat &audio_format,
*/
static bool
oss_setup(OssOutput *od, AudioFormat &audio_format,
GError **error_r)
Error &error)
{
return oss_setup_channels(od->fd, audio_format, error_r) &&
oss_setup_sample_rate(od->fd, audio_format, error_r) &&
return oss_setup_channels(od->fd, audio_format, error) &&
oss_setup_sample_rate(od->fd, audio_format, error) &&
oss_setup_sample_format(od->fd, audio_format, &od->oss_format,
#ifdef AFMT_S24_PACKED
od->pcm_export,
#endif
error_r);
error);
}
/**
* Reopen the device with the saved audio_format, without any probing.
*/
static bool
oss_reopen(OssOutput *od, GError **error_r)
oss_reopen(OssOutput *od, Error &error)
{
assert(od->fd < 0);
od->fd = open_cloexec(od->device, O_WRONLY, 0);
if (od->fd < 0) {
g_set_error(error_r, oss_output_quark(), errno,
"Error opening OSS device \"%s\": %s",
od->device, g_strerror(errno));
error.FormatErrno("Error opening OSS device \"%s\"",
od->device);
return false;
}
@@ -652,35 +644,32 @@ oss_reopen(OssOutput *od, GError **error_r)
const char *const msg1 = "Failed to set channel count";
result = oss_try_ioctl(od->fd, SNDCTL_DSP_CHANNELS,
od->audio_format.channels, msg1, error_r);
od->audio_format.channels, msg1, error);
if (result != SUCCESS) {
oss_close(od);
if (result == UNSUPPORTED)
g_set_error(error_r, oss_output_quark(), EINVAL,
"%s", msg1);
error.Set(oss_output_domain, msg1);
return false;
}
const char *const msg2 = "Failed to set sample rate";
result = oss_try_ioctl(od->fd, SNDCTL_DSP_SPEED,
od->audio_format.sample_rate, msg2, error_r);
od->audio_format.sample_rate, msg2, error);
if (result != SUCCESS) {
oss_close(od);
if (result == UNSUPPORTED)
g_set_error(error_r, oss_output_quark(), EINVAL,
"%s", msg2);
error.Set(oss_output_domain, msg2);
return false;
}
const char *const msg3 = "Failed to set sample format";
result = oss_try_ioctl(od->fd, SNDCTL_DSP_SAMPLESIZE,
od->oss_format,
msg3, error_r);
msg3, error);
if (result != SUCCESS) {
oss_close(od);
if (result == UNSUPPORTED)
g_set_error(error_r, oss_output_quark(), EINVAL,
"%s", msg3);
error.Set(oss_output_domain, msg3);
return false;
}
@@ -689,15 +678,14 @@ oss_reopen(OssOutput *od, GError **error_r)
static bool
oss_output_open(struct audio_output *ao, AudioFormat &audio_format,
GError **error)
Error &error)
{
OssOutput *od = (OssOutput *)ao;
od->fd = open_cloexec(od->device, O_WRONLY, 0);
if (od->fd < 0) {
g_set_error(error, oss_output_quark(), errno,
"Error opening OSS device \"%s\": %s",
od->device, g_strerror(errno));
error.FormatErrno("Error opening OSS device \"%s\"",
od->device);
return false;
}
@@ -731,7 +719,7 @@ oss_output_cancel(struct audio_output *ao)
static size_t
oss_output_play(struct audio_output *ao, const void *chunk, size_t size,
GError **error)
Error &error)
{
OssOutput *od = (OssOutput *)ao;
ssize_t ret;
@@ -754,9 +742,7 @@ oss_output_play(struct audio_output *ao, const void *chunk, size_t size,
}
if (ret < 0 && errno != EINTR) {
g_set_error(error, oss_output_quark(), errno,
"Write error on %s: %s",
od->device, g_strerror(errno));
error.FormatErrno("Write error on %s", od->device);
return 0;
}
}

View File

@@ -20,6 +20,9 @@
#include "config.h"
#include "PipeOutputPlugin.hxx"
#include "OutputAPI.hxx"
#include "ConfigError.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
#include <stdio.h>
#include <errno.h>
@@ -30,34 +33,27 @@ struct PipeOutput {
char *cmd;
FILE *fh;
bool Initialize(const config_param &param, GError **error_r) {
bool Initialize(const config_param &param, Error &error) {
return ao_base_init(&base, &pipe_output_plugin, param,
error_r);
error);
}
void Deinitialize() {
ao_base_finish(&base);
}
bool Configure(const config_param &param, GError **error_r);
bool Configure(const config_param &param, Error &error);
};
/**
* The quark used for GError.domain.
*/
static inline GQuark
pipe_output_quark(void)
{
return g_quark_from_static_string("pipe_output");
}
static constexpr Domain pipe_output_domain("pipe_output");
inline bool
PipeOutput::Configure(const config_param &param, GError **error_r)
PipeOutput::Configure(const config_param &param, Error &error)
{
cmd = param.DupBlockString("command");
if (cmd == nullptr) {
g_set_error(error_r, pipe_output_quark(), 0,
"No \"command\" parameter specified");
error.Set(config_domain,
"No \"command\" parameter specified");
return false;
}
@@ -65,16 +61,16 @@ PipeOutput::Configure(const config_param &param, GError **error_r)
}
static struct audio_output *
pipe_output_init(const config_param &param, GError **error_r)
pipe_output_init(const config_param &param, Error &error)
{
PipeOutput *pd = new PipeOutput();
if (!pd->Initialize(param, error_r)) {
if (!pd->Initialize(param, error)) {
delete pd;
return nullptr;
}
if (!pd->Configure(param, error_r)) {
if (!pd->Configure(param, error)) {
pd->Deinitialize();
delete pd;
return nullptr;
@@ -96,15 +92,14 @@ pipe_output_finish(struct audio_output *ao)
static bool
pipe_output_open(struct audio_output *ao,
gcc_unused AudioFormat &audio_format,
gcc_unused GError **error)
Error &error)
{
PipeOutput *pd = (PipeOutput *)ao;
pd->fh = popen(pd->cmd, "w");
if (pd->fh == nullptr) {
g_set_error(error, pipe_output_quark(), errno,
"Error opening pipe \"%s\": %s",
pd->cmd, g_strerror(errno));
error.FormatErrno("Error opening pipe \"%s\"",
pd->cmd);
return false;
}
@@ -120,15 +115,15 @@ pipe_output_close(struct audio_output *ao)
}
static size_t
pipe_output_play(struct audio_output *ao, const void *chunk, size_t size, GError **error)
pipe_output_play(struct audio_output *ao, const void *chunk, size_t size,
Error &error)
{
PipeOutput *pd = (PipeOutput *)ao;
size_t ret;
ret = fwrite(chunk, 1, size, pd->fh);
if (ret == 0)
g_set_error(error, pipe_output_quark(), errno,
"Write error on pipe: %s", g_strerror(errno));
error.SetErrno("Write error on pipe");
return ret;
}

View File

@@ -22,6 +22,8 @@
#include "OutputAPI.hxx"
#include "MixerList.hxx"
#include "mixer/PulseMixerPlugin.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
#include <glib.h>
@@ -54,13 +56,13 @@ struct PulseOutput {
size_t writable;
};
/**
* The quark used for GError.domain.
*/
static inline GQuark
pulse_output_quark(void)
static constexpr Domain pulse_output_domain("pulse_output");
static void
SetError(Error &error, pa_context *context, const char *msg)
{
return g_quark_from_static_string("pulse_output");
const int e = pa_context_errno(context);
error.Format(pulse_output_domain, e, "%s: %s", msg, pa_strerror(e));
}
void
@@ -112,14 +114,14 @@ pulse_output_clear_mixer(PulseOutput *po, gcc_unused PulseMixer *pm)
}
bool
pulse_output_set_volume(PulseOutput *po,
const struct pa_cvolume *volume, GError **error_r)
pulse_output_set_volume(PulseOutput *po, const pa_cvolume *volume,
Error &error)
{
pa_operation *o;
if (po->context == nullptr || po->stream == nullptr ||
pa_stream_get_state(po->stream) != PA_STREAM_READY) {
g_set_error(error_r, pulse_output_quark(), 0, "disconnected");
error.Set(pulse_output_domain, "disconnected");
return false;
}
@@ -127,9 +129,8 @@ pulse_output_set_volume(PulseOutput *po,
pa_stream_get_index(po->stream),
volume, nullptr, nullptr);
if (o == nullptr) {
g_set_error(error_r, pulse_output_quark(), 0,
"failed to set PulseAudio volume: %s",
pa_strerror(pa_context_errno(po->context)));
SetError(error, po->context,
"failed to set PulseAudio volume");
return false;
}
@@ -235,19 +236,15 @@ pulse_output_subscribe_cb(pa_context *context,
* @return true on success, false on error
*/
static bool
pulse_output_connect(PulseOutput *po, GError **error_r)
pulse_output_connect(PulseOutput *po, Error &error)
{
assert(po != nullptr);
assert(po->context != nullptr);
int error;
error = pa_context_connect(po->context, po->server,
(pa_context_flags_t)0, nullptr);
if (error < 0) {
g_set_error(error_r, pulse_output_quark(), 0,
"pa_context_connect() has failed: %s",
pa_strerror(pa_context_errno(po->context)));
if (pa_context_connect(po->context, po->server,
(pa_context_flags_t)0, nullptr) < 0) {
SetError(error, po->context,
"pa_context_connect() has failed");
return false;
}
@@ -300,7 +297,7 @@ pulse_output_delete_context(PulseOutput *po)
* @return true on success, false on error
*/
static bool
pulse_output_setup_context(PulseOutput *po, GError **error_r)
pulse_output_setup_context(PulseOutput *po, Error &error)
{
assert(po != nullptr);
assert(po->mainloop != nullptr);
@@ -308,8 +305,7 @@ pulse_output_setup_context(PulseOutput *po, GError **error_r)
po->context = pa_context_new(pa_threaded_mainloop_get_api(po->mainloop),
MPD_PULSE_NAME);
if (po->context == nullptr) {
g_set_error(error_r, pulse_output_quark(), 0,
"pa_context_new() has failed");
error.Set(pulse_output_domain, "pa_context_new() has failed");
return false;
}
@@ -318,7 +314,7 @@ pulse_output_setup_context(PulseOutput *po, GError **error_r)
pa_context_set_subscribe_callback(po->context,
pulse_output_subscribe_cb, po);
if (!pulse_output_connect(po, error_r)) {
if (!pulse_output_connect(po, error)) {
pulse_output_delete_context(po);
return false;
}
@@ -327,14 +323,14 @@ pulse_output_setup_context(PulseOutput *po, GError **error_r)
}
static struct audio_output *
pulse_output_init(const config_param &param, GError **error_r)
pulse_output_init(const config_param &param, Error &error)
{
PulseOutput *po;
g_setenv("PULSE_PROP_media.role", "music", true);
po = new PulseOutput();
if (!ao_base_init(&po->base, &pulse_output_plugin, param, error_r)) {
if (!ao_base_init(&po->base, &pulse_output_plugin, param, error)) {
delete po;
return nullptr;
}
@@ -361,7 +357,7 @@ pulse_output_finish(struct audio_output *ao)
}
static bool
pulse_output_enable(struct audio_output *ao, GError **error_r)
pulse_output_enable(struct audio_output *ao, Error &error)
{
PulseOutput *po = (PulseOutput *)ao;
@@ -374,8 +370,8 @@ pulse_output_enable(struct audio_output *ao, GError **error_r)
if (po->mainloop == nullptr) {
g_free(po);
g_set_error(error_r, pulse_output_quark(), 0,
"pa_threaded_mainloop_new() has failed");
error.Set(pulse_output_domain,
"pa_threaded_mainloop_new() has failed");
return false;
}
@@ -386,14 +382,14 @@ pulse_output_enable(struct audio_output *ao, GError **error_r)
pa_threaded_mainloop_free(po->mainloop);
po->mainloop = nullptr;
g_set_error(error_r, pulse_output_quark(), 0,
"pa_threaded_mainloop_start() has failed");
error.Set(pulse_output_domain,
"pa_threaded_mainloop_start() has failed");
return false;
}
/* create the libpulse context and connect it */
if (!pulse_output_setup_context(po, error_r)) {
if (!pulse_output_setup_context(po, error)) {
pa_threaded_mainloop_unlock(po->mainloop);
pa_threaded_mainloop_stop(po->mainloop);
pa_threaded_mainloop_free(po->mainloop);
@@ -429,13 +425,13 @@ pulse_output_disable(struct audio_output *ao)
* @return true on success, false on error
*/
static bool
pulse_output_wait_connection(PulseOutput *po, GError **error_r)
pulse_output_wait_connection(PulseOutput *po, Error &error)
{
assert(po->mainloop != nullptr);
pa_context_state_t state;
if (po->context == nullptr && !pulse_output_setup_context(po, error_r))
if (po->context == nullptr && !pulse_output_setup_context(po, error))
return false;
while (true) {
@@ -449,9 +445,7 @@ pulse_output_wait_connection(PulseOutput *po, GError **error_r)
case PA_CONTEXT_TERMINATED:
case PA_CONTEXT_FAILED:
/* failure */
g_set_error(error_r, pulse_output_quark(), 0,
"failed to connect: %s",
pa_strerror(pa_context_errno(po->context)));
SetError(error, po->context, "failed to connect");
pulse_output_delete_context(po);
return false;
@@ -530,16 +524,14 @@ pulse_output_stream_write_cb(gcc_unused pa_stream *stream, size_t nbytes,
*/
static bool
pulse_output_setup_stream(PulseOutput *po, const pa_sample_spec *ss,
GError **error_r)
Error &error)
{
assert(po != nullptr);
assert(po->context != nullptr);
po->stream = pa_stream_new(po->context, po->name, ss, nullptr);
if (po->stream == nullptr) {
g_set_error(error_r, pulse_output_quark(), 0,
"pa_stream_new() has failed: %s",
pa_strerror(pa_context_errno(po->context)));
SetError(error, po->context, "pa_stream_new() has failed");
return false;
}
@@ -556,11 +548,10 @@ pulse_output_setup_stream(PulseOutput *po, const pa_sample_spec *ss,
static bool
pulse_output_open(struct audio_output *ao, AudioFormat &audio_format,
GError **error_r)
Error &error)
{
PulseOutput *po = (PulseOutput *)ao;
pa_sample_spec ss;
int error;
assert(po->mainloop != nullptr);
@@ -585,7 +576,7 @@ pulse_output_open(struct audio_output *ao, AudioFormat &audio_format,
}
}
if (!pulse_output_wait_connection(po, error_r)) {
if (!pulse_output_wait_connection(po, error)) {
pa_threaded_mainloop_unlock(po->mainloop);
return false;
}
@@ -600,22 +591,20 @@ pulse_output_open(struct audio_output *ao, AudioFormat &audio_format,
/* create a stream .. */
if (!pulse_output_setup_stream(po, &ss, error_r)) {
if (!pulse_output_setup_stream(po, &ss, error)) {
pa_threaded_mainloop_unlock(po->mainloop);
return false;
}
/* .. and connect it (asynchronously) */
error = pa_stream_connect_playback(po->stream, po->sink,
nullptr, pa_stream_flags_t(0),
nullptr, nullptr);
if (error < 0) {
if (pa_stream_connect_playback(po->stream, po->sink,
nullptr, pa_stream_flags_t(0),
nullptr, nullptr) < 0) {
pulse_output_delete_stream(po);
g_set_error(error_r, pulse_output_quark(), 0,
"pa_stream_connect_playback() has failed: %s",
pa_strerror(pa_context_errno(po->context)));
SetError(error, po->context,
"pa_stream_connect_playback() has failed");
pa_threaded_mainloop_unlock(po->mainloop);
return false;
}
@@ -661,7 +650,7 @@ pulse_output_close(struct audio_output *ao)
* @return true on success, false on error
*/
static bool
pulse_output_wait_stream(PulseOutput *po, GError **error_r)
pulse_output_wait_stream(PulseOutput *po, Error &error)
{
while (true) {
switch (pa_stream_get_state(po->stream)) {
@@ -671,10 +660,8 @@ pulse_output_wait_stream(PulseOutput *po, GError **error_r)
case PA_STREAM_FAILED:
case PA_STREAM_TERMINATED:
case PA_STREAM_UNCONNECTED:
g_set_error(error_r, pulse_output_quark(),
pa_context_errno(po->context),
"failed to connect the stream: %s",
pa_strerror(pa_context_errno(po->context)));
SetError(error, po->context,
"failed to connect the stream");
return false;
case PA_STREAM_CREATING:
@@ -689,7 +676,7 @@ pulse_output_wait_stream(PulseOutput *po, GError **error_r)
*/
static bool
pulse_output_stream_pause(PulseOutput *po, bool pause,
GError **error_r)
Error &error)
{
pa_operation *o;
@@ -700,16 +687,12 @@ pulse_output_stream_pause(PulseOutput *po, bool pause,
o = pa_stream_cork(po->stream, pause,
pulse_output_stream_success_cb, po);
if (o == nullptr) {
g_set_error(error_r, pulse_output_quark(), 0,
"pa_stream_cork() has failed: %s",
pa_strerror(pa_context_errno(po->context)));
SetError(error, po->context, "pa_stream_cork() has failed");
return false;
}
if (!pulse_wait_for_operation(po->mainloop, o)) {
g_set_error(error_r, pulse_output_quark(), 0,
"pa_stream_cork() has failed: %s",
pa_strerror(pa_context_errno(po->context)));
SetError(error, po->context, "pa_stream_cork() has failed");
return false;
}
@@ -736,10 +719,9 @@ pulse_output_delay(struct audio_output *ao)
static size_t
pulse_output_play(struct audio_output *ao, const void *chunk, size_t size,
GError **error_r)
Error &error)
{
PulseOutput *po = (PulseOutput *)ao;
int error;
assert(po->mainloop != nullptr);
assert(po->stream != nullptr);
@@ -748,7 +730,7 @@ pulse_output_play(struct audio_output *ao, const void *chunk, size_t size,
/* check if the stream is (already) connected */
if (!pulse_output_wait_stream(po, error_r)) {
if (!pulse_output_wait_stream(po, error)) {
pa_threaded_mainloop_unlock(po->mainloop);
return 0;
}
@@ -758,7 +740,7 @@ pulse_output_play(struct audio_output *ao, const void *chunk, size_t size,
/* unpause if previously paused */
if (pa_stream_is_corked(po->stream) &&
!pulse_output_stream_pause(po, false, error_r)) {
!pulse_output_stream_pause(po, false, error)) {
pa_threaded_mainloop_unlock(po->mainloop);
return 0;
}
@@ -768,8 +750,7 @@ pulse_output_play(struct audio_output *ao, const void *chunk, size_t size,
while (po->writable == 0) {
if (pa_stream_is_suspended(po->stream)) {
pa_threaded_mainloop_unlock(po->mainloop);
g_set_error(error_r, pulse_output_quark(), 0,
"suspended");
error.Set(pulse_output_domain, "suspended");
return 0;
}
@@ -777,8 +758,7 @@ pulse_output_play(struct audio_output *ao, const void *chunk, size_t size,
if (pa_stream_get_state(po->stream) != PA_STREAM_READY) {
pa_threaded_mainloop_unlock(po->mainloop);
g_set_error(error_r, pulse_output_quark(), 0,
"disconnected");
error.Set(pulse_output_domain, "disconnected");
return 0;
}
}
@@ -791,12 +771,11 @@ pulse_output_play(struct audio_output *ao, const void *chunk, size_t size,
po->writable -= size;
error = pa_stream_write(po->stream, chunk, size, nullptr,
0, PA_SEEK_RELATIVE);
int result = pa_stream_write(po->stream, chunk, size, nullptr,
0, PA_SEEK_RELATIVE);
pa_threaded_mainloop_unlock(po->mainloop);
if (error < 0) {
g_set_error(error_r, pulse_output_quark(), error,
"%s", pa_strerror(error));
if (result < 0) {
SetError(error, po->context, "pa_stream_write() failed");
return 0;
}
@@ -839,7 +818,6 @@ static bool
pulse_output_pause(struct audio_output *ao)
{
PulseOutput *po = (PulseOutput *)ao;
GError *error = nullptr;
assert(po->mainloop != nullptr);
assert(po->stream != nullptr);
@@ -848,10 +826,10 @@ pulse_output_pause(struct audio_output *ao)
/* check if the stream is (already/still) connected */
if (!pulse_output_wait_stream(po, &error)) {
Error error;
if (!pulse_output_wait_stream(po, error)) {
pa_threaded_mainloop_unlock(po->mainloop);
g_warning("%s", error->message);
g_error_free(error);
g_warning("%s", error.GetMessage());
return false;
}
@@ -860,10 +838,9 @@ pulse_output_pause(struct audio_output *ao)
/* cork the stream */
if (!pa_stream_is_corked(po->stream) &&
!pulse_output_stream_pause(po, true, &error)) {
!pulse_output_stream_pause(po, true, error)) {
pa_threaded_mainloop_unlock(po->mainloop);
g_warning("%s", error->message);
g_error_free(error);
g_warning("%s", error.GetMessage());
return false;
}
@@ -878,11 +855,12 @@ pulse_output_test_default_device(void)
bool success;
const config_param empty;
PulseOutput *po = (PulseOutput *)pulse_output_init(empty, nullptr);
PulseOutput *po = (PulseOutput *)
pulse_output_init(empty, IgnoreError());
if (po == nullptr)
return false;
success = pulse_output_wait_connection(po, nullptr);
success = pulse_output_wait_connection(po, IgnoreError());
pulse_output_finish(&po->base);
return success;

View File

@@ -20,11 +20,10 @@
#ifndef MPD_PULSE_OUTPUT_PLUGIN_HXX
#define MPD_PULSE_OUTPUT_PLUGIN_HXX
#include "gerror.h"
struct PulseOutput;
struct PulseMixer;
struct pa_cvolume;
class Error;
extern const struct audio_output_plugin pulse_output_plugin;
@@ -42,6 +41,6 @@ pulse_output_clear_mixer(PulseOutput *po, PulseMixer *pm);
bool
pulse_output_set_volume(PulseOutput *po,
const struct pa_cvolume *volume, GError **error_r);
const struct pa_cvolume *volume, Error &error);
#endif

View File

@@ -22,6 +22,9 @@
#include "OutputAPI.hxx"
#include "EncoderPlugin.hxx"
#include "EncoderList.hxx"
#include "ConfigError.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
#include "system/fd_util.h"
#include "open.h"
@@ -57,7 +60,7 @@ struct RecorderOutput {
*/
char buffer[32768];
bool Initialize(const config_param &param, GError **error_r) {
bool Initialize(const config_param &param, Error &error_r) {
return ao_base_init(&base, &recorder_output_plugin, param,
error_r);
}
@@ -66,27 +69,20 @@ struct RecorderOutput {
ao_base_finish(&base);
}
bool Configure(const config_param &param, GError **error_r);
bool Configure(const config_param &param, Error &error);
bool WriteToFile(const void *data, size_t length, GError **error_r);
bool WriteToFile(const void *data, size_t length, Error &error);
/**
* Writes pending data from the encoder to the output file.
*/
bool EncoderToFile(GError **error_r);
bool EncoderToFile(Error &error);
};
/**
* The quark used for GError.domain.
*/
static inline GQuark
recorder_output_quark(void)
{
return g_quark_from_static_string("recorder_output");
}
static constexpr Domain recorder_output_domain("recorder_output");
inline bool
RecorderOutput::Configure(const config_param &param, GError **error_r)
RecorderOutput::Configure(const config_param &param, Error &error)
{
/* read configuration */
@@ -94,21 +90,20 @@ RecorderOutput::Configure(const config_param &param, GError **error_r)
param.GetBlockValue("encoder", "vorbis");
const auto encoder_plugin = encoder_plugin_get(encoder_name);
if (encoder_plugin == nullptr) {
g_set_error(error_r, recorder_output_quark(), 0,
"No such encoder: %s", encoder_name);
error.Format(config_domain,
"No such encoder: %s", encoder_name);
return false;
}
path = param.GetBlockValue("path");
if (path == nullptr) {
g_set_error(error_r, recorder_output_quark(), 0,
"'path' not configured");
error.Set(config_domain, "'path' not configured");
return false;
}
/* initialize encoder */
encoder = encoder_init(*encoder_plugin, param, error_r);
encoder = encoder_init(*encoder_plugin, param, error);
if (encoder == nullptr)
return false;
@@ -116,16 +111,16 @@ RecorderOutput::Configure(const config_param &param, GError **error_r)
}
static audio_output *
recorder_output_init(const config_param &param, GError **error_r)
recorder_output_init(const config_param &param, Error &error)
{
RecorderOutput *recorder = new RecorderOutput();
if (!recorder->Initialize(param, error_r)) {
if (!recorder->Initialize(param, error)) {
delete recorder;
return nullptr;
}
if (!recorder->Configure(param, error_r)) {
if (!recorder->Configure(param, error)) {
recorder->Deinitialize();
delete recorder;
return nullptr;
@@ -145,7 +140,7 @@ recorder_output_finish(struct audio_output *ao)
}
inline bool
RecorderOutput::WriteToFile(const void *_data, size_t length, GError **error_r)
RecorderOutput::WriteToFile(const void *_data, size_t length, Error &error)
{
assert(length > 0);
@@ -159,20 +154,18 @@ RecorderOutput::WriteToFile(const void *_data, size_t length, GError **error_r)
return true;
} else if (nbytes == 0) {
/* shouldn't happen for files */
g_set_error(error_r, recorder_output_quark(), 0,
"write() returned 0");
error.Set(recorder_output_domain,
"write() returned 0");
return false;
} else if (errno != EINTR) {
g_set_error(error_r, recorder_output_quark(), 0,
"Failed to write to '%s': %s",
path, g_strerror(errno));
error.FormatErrno("Failed to write to '%s'", path);
return false;
}
}
}
inline bool
RecorderOutput::EncoderToFile(GError **error_r)
RecorderOutput::EncoderToFile(Error &error)
{
assert(fd >= 0);
@@ -185,7 +178,7 @@ RecorderOutput::EncoderToFile(GError **error_r)
/* write everything into the file */
if (!WriteToFile(buffer, size, error_r))
if (!WriteToFile(buffer, size, error))
return false;
}
}
@@ -193,7 +186,7 @@ RecorderOutput::EncoderToFile(GError **error_r)
static bool
recorder_output_open(struct audio_output *ao,
AudioFormat &audio_format,
GError **error_r)
Error &error)
{
RecorderOutput *recorder = (RecorderOutput *)ao;
@@ -203,21 +196,19 @@ recorder_output_open(struct audio_output *ao,
O_CREAT|O_WRONLY|O_TRUNC|O_BINARY,
0666);
if (recorder->fd < 0) {
g_set_error(error_r, recorder_output_quark(), 0,
"Failed to create '%s': %s",
recorder->path, g_strerror(errno));
error.FormatErrno("Failed to create '%s'", recorder->path);
return false;
}
/* open the encoder */
if (!encoder_open(recorder->encoder, audio_format, error_r)) {
if (!encoder_open(recorder->encoder, audio_format, error)) {
close(recorder->fd);
unlink(recorder->path);
return false;
}
if (!recorder->EncoderToFile(error_r)) {
if (!recorder->EncoderToFile(error)) {
encoder_close(recorder->encoder);
close(recorder->fd);
unlink(recorder->path);
@@ -234,8 +225,8 @@ recorder_output_close(struct audio_output *ao)
/* flush the encoder and write the rest to the file */
if (encoder_end(recorder->encoder, nullptr))
recorder->EncoderToFile(nullptr);
if (encoder_end(recorder->encoder, IgnoreError()))
recorder->EncoderToFile(IgnoreError());
/* now really close everything */
@@ -246,12 +237,12 @@ recorder_output_close(struct audio_output *ao)
static size_t
recorder_output_play(struct audio_output *ao, const void *chunk, size_t size,
GError **error_r)
Error &error)
{
RecorderOutput *recorder = (RecorderOutput *)ao;
return encoder_write(recorder->encoder, chunk, size, error_r) &&
recorder->EncoderToFile(error_r)
return encoder_write(recorder->encoder, chunk, size, error) &&
recorder->EncoderToFile(error)
? size : 0;
}

View File

@@ -23,6 +23,8 @@
#include "OutputAPI.hxx"
#include "MixerList.hxx"
#include "thread/Mutex.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
#include <glib.h>
@@ -58,11 +60,7 @@ struct RoarOutput {
}
};
static inline GQuark
roar_output_quark(void)
{
return g_quark_from_static_string("roar_output");
}
static constexpr Domain roar_output_domain("roar_output");
static int
roar_output_get_volume_locked(RoarOutput *roar)
@@ -120,11 +118,11 @@ roar_configure(RoarOutput *self, const config_param &param)
}
static struct audio_output *
roar_init(const config_param &param, GError **error_r)
roar_init(const config_param &param, Error &error)
{
RoarOutput *self = new RoarOutput();
if (!ao_base_init(&self->base, &roar_output_plugin, param, error_r)) {
if (!ao_base_init(&self->base, &roar_output_plugin, param, error)) {
delete self;
return nullptr;
}
@@ -178,15 +176,15 @@ roar_use_audio_format(struct roar_audio_info *info,
}
static bool
roar_open(struct audio_output *ao, AudioFormat &audio_format, GError **error)
roar_open(struct audio_output *ao, AudioFormat &audio_format, Error &error)
{
RoarOutput *self = (RoarOutput *)ao;
const ScopeLock protect(self->mutex);
if (roar_simple_connect(&(self->con), self->host, self->name) < 0)
{
g_set_error(error, roar_output_quark(), 0,
"Failed to connect to Roar server");
error.Set(roar_output_domain,
"Failed to connect to Roar server");
return false;
}
@@ -194,8 +192,7 @@ roar_open(struct audio_output *ao, AudioFormat &audio_format, GError **error)
if (self->vss == nullptr || self->err != ROAR_ERROR_NONE)
{
g_set_error(error, roar_output_quark(), 0,
"Failed to connect to server");
error.Set(roar_output_domain, "Failed to connect to server");
return false;
}
@@ -204,7 +201,7 @@ roar_open(struct audio_output *ao, AudioFormat &audio_format, GError **error)
if (roar_vs_stream(self->vss, &(self->info), ROAR_DIR_PLAY,
&(self->err)) < 0)
{
g_set_error(error, roar_output_quark(), 0, "Failed to start stream");
error.Set(roar_output_domain, "Failed to start stream");
return false;
}
roar_vs_role(self->vss, self->role, &(self->err));
@@ -264,21 +261,22 @@ roar_cancel(struct audio_output *ao)
}
static size_t
roar_play(struct audio_output *ao, const void *chunk, size_t size, GError **error)
roar_play(struct audio_output *ao, const void *chunk, size_t size,
Error &error)
{
RoarOutput *self = (RoarOutput *)ao;
ssize_t rc;
if (self->vss == nullptr)
{
g_set_error(error, roar_output_quark(), 0, "Connection is invalid");
error.Set(roar_output_domain, "Connection is invalid");
return 0;
}
rc = roar_vs_write(self->vss, chunk, size, &(self->err));
if ( rc <= 0 )
{
g_set_error(error, roar_output_quark(), 0, "Failed to play data");
error.Set(roar_output_domain, "Failed to play data");
return 0;
}

View File

@@ -22,6 +22,9 @@
#include "OutputAPI.hxx"
#include "EncoderPlugin.hxx"
#include "EncoderList.hxx"
#include "ConfigError.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
#include "mpd_error.h"
#include <shout/shout.h>
@@ -66,28 +69,21 @@ struct ShoutOutput final {
shout_free(shout_conn);
}
bool Initialize(const config_param &param, GError **error_r) {
bool Initialize(const config_param &param, Error &error) {
return ao_base_init(&base, &shout_output_plugin, param,
error_r);
error);
}
void Deinitialize() {
ao_base_finish(&base);
}
bool Configure(const config_param &param, GError **error_r);
bool Configure(const config_param &param, Error &error);
};
static int shout_init_count;
/**
* The quark used for GError.domain.
*/
static inline GQuark
shout_output_quark(void)
{
return g_quark_from_static_string("shout_output");
}
static constexpr Domain shout_output_domain("shout_output");
static const EncoderPlugin *
shout_encoder_plugin_get(const char *name)
@@ -113,13 +109,13 @@ require_block_string(const config_param &param, const char *name)
}
inline bool
ShoutOutput::Configure(const config_param &param, GError **error_r)
ShoutOutput::Configure(const config_param &param, Error &error)
{
const AudioFormat audio_format = base.config_audio_format;
if (!audio_format.IsFullyDefined()) {
g_set_error(error_r, shout_output_quark(), 0,
"Need full audio format specification");
error.Set(config_domain,
"Need full audio format specification");
return nullptr;
}
@@ -127,8 +123,7 @@ ShoutOutput::Configure(const config_param &param, GError **error_r)
const char *mount = require_block_string(param, "mount");
unsigned port = param.GetBlockValue("port", 0u);
if (port == 0) {
g_set_error(error_r, shout_output_quark(), 0,
"shout port must be configured");
error.Set(config_domain, "shout port must be configured");
return false;
}
@@ -145,24 +140,24 @@ ShoutOutput::Configure(const config_param &param, GError **error_r)
quality = strtod(value, &test);
if (*test != '\0' || quality < -1.0 || quality > 10.0) {
g_set_error(error_r, shout_output_quark(), 0,
"shout quality \"%s\" is not a number in the "
"range -1 to 10, line %i",
value, param.line);
error.Format(config_domain,
"shout quality \"%s\" is not a number in the "
"range -1 to 10, line %i",
value, param.line);
return false;
}
if (param.GetBlockValue("bitrate") != nullptr) {
g_set_error(error_r, shout_output_quark(), 0,
"quality and bitrate are "
"both defined");
error.Set(config_domain,
"quality and bitrate are "
"both defined");
return false;
}
} else {
value = param.GetBlockValue("bitrate");
if (value == nullptr) {
g_set_error(error_r, shout_output_quark(), 0,
"neither bitrate nor quality defined");
error.Set(config_domain,
"neither bitrate nor quality defined");
return false;
}
@@ -170,8 +165,8 @@ ShoutOutput::Configure(const config_param &param, GError **error_r)
bitrate = strtol(value, &test, 10);
if (*test != '\0' || bitrate <= 0) {
g_set_error(error_r, shout_output_quark(), 0,
"bitrate must be a positive integer");
error.Set(config_domain,
"bitrate must be a positive integer");
return false;
}
}
@@ -179,13 +174,13 @@ ShoutOutput::Configure(const config_param &param, GError **error_r)
const char *encoding = param.GetBlockValue("encoding", "ogg");
const auto encoder_plugin = shout_encoder_plugin_get(encoding);
if (encoder_plugin == nullptr) {
g_set_error(error_r, shout_output_quark(), 0,
"couldn't find shout encoder plugin \"%s\"",
encoding);
error.Format(config_domain,
"couldn't find shout encoder plugin \"%s\"",
encoding);
return false;
}
encoder = encoder_init(*encoder_plugin, param, error_r);
encoder = encoder_init(*encoder_plugin, param, error);
if (encoder == nullptr)
return false;
@@ -200,9 +195,9 @@ ShoutOutput::Configure(const config_param &param, GError **error_r)
if (value != nullptr) {
if (0 == strcmp(value, "shoutcast") &&
0 != strcmp(encoding, "mp3")) {
g_set_error(error_r, shout_output_quark(), 0,
"you cannot stream \"%s\" to shoutcast, use mp3",
encoding);
error.Format(config_domain,
"you cannot stream \"%s\" to shoutcast, use mp3",
encoding);
return false;
} else if (0 == strcmp(value, "shoutcast"))
protocol = SHOUT_PROTOCOL_ICY;
@@ -211,10 +206,10 @@ ShoutOutput::Configure(const config_param &param, GError **error_r)
else if (0 == strcmp(value, "icecast2"))
protocol = SHOUT_PROTOCOL_HTTP;
else {
g_set_error(error_r, shout_output_quark(), 0,
"shout protocol \"%s\" is not \"shoutcast\" or "
"\"icecast1\"or \"icecast2\"",
value);
error.Format(config_domain,
"shout protocol \"%s\" is not \"shoutcast\" or "
"\"icecast1\"or \"icecast2\"",
value);
return false;
}
} else {
@@ -232,8 +227,7 @@ ShoutOutput::Configure(const config_param &param, GError **error_r)
!= SHOUTERR_SUCCESS ||
shout_set_protocol(shout_conn, protocol) != SHOUTERR_SUCCESS ||
shout_set_agent(shout_conn, "MPD") != SHOUTERR_SUCCESS) {
g_set_error(error_r, shout_output_quark(), 0,
"%s", shout_get_error(shout_conn));
error.Set(shout_output_domain, shout_get_error(shout_conn));
return false;
}
@@ -242,22 +236,19 @@ ShoutOutput::Configure(const config_param &param, GError **error_r)
value = param.GetBlockValue("genre");
if (value != nullptr && shout_set_genre(shout_conn, value)) {
g_set_error(error_r, shout_output_quark(), 0,
"%s", shout_get_error(shout_conn));
error.Set(shout_output_domain, shout_get_error(shout_conn));
return false;
}
value = param.GetBlockValue("description");
if (value != nullptr && shout_set_description(shout_conn, value)) {
g_set_error(error_r, shout_output_quark(), 0,
"%s", shout_get_error(shout_conn));
error.Set(shout_output_domain, shout_get_error(shout_conn));
return false;
}
value = param.GetBlockValue("url");
if (value != nullptr && shout_set_url(shout_conn, value)) {
g_set_error(error_r, shout_output_quark(), 0,
"%s", shout_get_error(shout_conn));
error.Set(shout_output_domain, shout_get_error(shout_conn));
return false;
}
@@ -287,15 +278,15 @@ ShoutOutput::Configure(const config_param &param, GError **error_r)
}
static struct audio_output *
my_shout_init_driver(const config_param &param, GError **error_r)
my_shout_init_driver(const config_param &param, Error &error)
{
ShoutOutput *sd = new ShoutOutput();
if (!sd->Initialize(param, error_r)) {
if (!sd->Initialize(param, error)) {
delete sd;
return nullptr;
}
if (!sd->Configure(param, error_r)) {
if (!sd->Configure(param, error)) {
sd->Deinitialize();
delete sd;
return nullptr;
@@ -310,7 +301,7 @@ my_shout_init_driver(const config_param &param, GError **error_r)
}
static bool
handle_shout_error(ShoutOutput *sd, int err, GError **error)
handle_shout_error(ShoutOutput *sd, int err, Error &error)
{
switch (err) {
case SHOUTERR_SUCCESS:
@@ -318,19 +309,19 @@ handle_shout_error(ShoutOutput *sd, int err, GError **error)
case SHOUTERR_UNCONNECTED:
case SHOUTERR_SOCKET:
g_set_error(error, shout_output_quark(), err,
"Lost shout connection to %s:%i: %s",
shout_get_host(sd->shout_conn),
shout_get_port(sd->shout_conn),
shout_get_error(sd->shout_conn));
error.Format(shout_output_domain, err,
"Lost shout connection to %s:%i: %s",
shout_get_host(sd->shout_conn),
shout_get_port(sd->shout_conn),
shout_get_error(sd->shout_conn));
return false;
default:
g_set_error(error, shout_output_quark(), err,
"connection to %s:%i error: %s",
shout_get_host(sd->shout_conn),
shout_get_port(sd->shout_conn),
shout_get_error(sd->shout_conn));
error.Format(shout_output_domain, err,
"connection to %s:%i error: %s",
shout_get_host(sd->shout_conn),
shout_get_port(sd->shout_conn),
shout_get_error(sd->shout_conn));
return false;
}
@@ -338,7 +329,7 @@ handle_shout_error(ShoutOutput *sd, int err, GError **error)
}
static bool
write_page(ShoutOutput *sd, GError **error)
write_page(ShoutOutput *sd, Error &error)
{
assert(sd->encoder != nullptr);
@@ -359,8 +350,8 @@ write_page(ShoutOutput *sd, GError **error)
static void close_shout_conn(ShoutOutput * sd)
{
if (sd->encoder != nullptr) {
if (encoder_end(sd->encoder, nullptr))
write_page(sd, nullptr);
if (encoder_end(sd->encoder, IgnoreError()))
write_page(sd, IgnoreError());
encoder_close(sd->encoder);
}
@@ -406,7 +397,7 @@ my_shout_close_device(struct audio_output *ao)
}
static bool
shout_connect(ShoutOutput *sd, GError **error)
shout_connect(ShoutOutput *sd, Error &error)
{
switch (shout_open(sd->shout_conn)) {
case SHOUTERR_SUCCESS:
@@ -414,18 +405,18 @@ shout_connect(ShoutOutput *sd, GError **error)
return true;
default:
g_set_error(error, shout_output_quark(), 0,
"problem opening connection to shout server %s:%i: %s",
shout_get_host(sd->shout_conn),
shout_get_port(sd->shout_conn),
shout_get_error(sd->shout_conn));
error.Format(shout_output_domain,
"problem opening connection to shout server %s:%i: %s",
shout_get_host(sd->shout_conn),
shout_get_port(sd->shout_conn),
shout_get_error(sd->shout_conn));
return false;
}
}
static bool
my_shout_open_device(struct audio_output *ao, AudioFormat &audio_format,
GError **error)
Error &error)
{
ShoutOutput *sd = (ShoutOutput *)ao;
@@ -460,7 +451,7 @@ my_shout_delay(struct audio_output *ao)
static size_t
my_shout_play(struct audio_output *ao, const void *chunk, size_t size,
GError **error)
Error &error)
{
ShoutOutput *sd = (ShoutOutput *)ao;
@@ -475,7 +466,7 @@ my_shout_pause(struct audio_output *ao)
{
static char silence[1020];
return my_shout_play(ao, silence, sizeof(silence), nullptr);
return my_shout_play(ao, silence, sizeof(silence), IgnoreError());
}
static void
@@ -508,24 +499,17 @@ static void my_shout_set_tag(struct audio_output *ao,
const Tag *tag)
{
ShoutOutput *sd = (ShoutOutput *)ao;
GError *error = nullptr;
if (sd->encoder->plugin.tag != nullptr) {
/* encoder plugin supports stream tags */
if (!encoder_pre_tag(sd->encoder, &error)) {
g_warning("%s", error->message);
g_error_free(error);
Error error;
if (!encoder_pre_tag(sd->encoder, error) ||
!write_page(sd, error) ||
!encoder_tag(sd->encoder, tag, error)) {
g_warning("%s", error.GetMessage());
return;
}
if (!write_page(sd, nullptr))
return;
if (!encoder_tag(sd->encoder, tag, &error)) {
g_warning("%s", error->message);
g_error_free(error);
}
} else {
/* no stream tag support: fall back to icy-metadata */
char song[1024];
@@ -538,7 +522,7 @@ static void my_shout_set_tag(struct audio_output *ao,
}
}
write_page(sd, nullptr);
write_page(sd, IgnoreError());
}
const struct audio_output_plugin shout_output_plugin = {

View File

@@ -21,8 +21,7 @@
#include "SolarisOutputPlugin.hxx"
#include "OutputAPI.hxx"
#include "system/fd_util.h"
#include <glib.h>
#include "util/Error.hxx"
#include <sys/stropts.h>
#include <sys/types.h>
@@ -61,7 +60,7 @@ struct SolarisOutput {
int fd;
bool Initialize(const config_param &param, GError **error_r) {
bool Initialize(const config_param &param, Error &error_r) {
return ao_base_init(&base, &solaris_output_plugin, param,
error_r);
}
@@ -71,15 +70,6 @@ struct SolarisOutput {
}
};
/**
* The quark used for GError.domain.
*/
static inline GQuark
solaris_output_quark(void)
{
return g_quark_from_static_string("solaris_output");
}
static bool
solaris_output_test_default_device(void)
{
@@ -90,7 +80,7 @@ solaris_output_test_default_device(void)
}
static struct audio_output *
solaris_output_init(const config_param &param, GError **error_r)
solaris_output_init(const config_param &param, Error &error_r)
{
SolarisOutput *so = new SolarisOutput();
if (!so->Initialize(param, error_r)) {
@@ -114,7 +104,7 @@ solaris_output_finish(struct audio_output *ao)
static bool
solaris_output_open(struct audio_output *ao, AudioFormat &audio_format,
GError **error)
Error &error)
{
SolarisOutput *so = (SolarisOutput *)ao;
struct audio_info info;
@@ -128,9 +118,8 @@ solaris_output_open(struct audio_output *ao, AudioFormat &audio_format,
so->fd = open_cloexec(so->device, O_WRONLY|O_NONBLOCK, 0);
if (so->fd < 0) {
g_set_error(error, solaris_output_quark(), errno,
"Failed to open %s: %s",
so->device, g_strerror(errno));
error.FormatErrno("Failed to open %s",
so->device);
return false;
}
@@ -144,8 +133,7 @@ solaris_output_open(struct audio_output *ao, AudioFormat &audio_format,
ret = ioctl(so->fd, AUDIO_GETINFO, &info);
if (ret < 0) {
g_set_error(error, solaris_output_quark(), errno,
"AUDIO_GETINFO failed: %s", g_strerror(errno));
error.SetErrno("AUDIO_GETINFO failed");
close(so->fd);
return false;
}
@@ -157,8 +145,7 @@ solaris_output_open(struct audio_output *ao, AudioFormat &audio_format,
ret = ioctl(so->fd, AUDIO_SETINFO, &info);
if (ret < 0) {
g_set_error(error, solaris_output_quark(), errno,
"AUDIO_SETINFO failed: %s", g_strerror(errno));
error.SetErrno("AUDIO_SETINFO failed");
close(so->fd);
return false;
}
@@ -176,15 +163,14 @@ solaris_output_close(struct audio_output *ao)
static size_t
solaris_output_play(struct audio_output *ao, const void *chunk, size_t size,
GError **error)
Error &error)
{
SolarisOutput *so = (SolarisOutput *)ao;
ssize_t nbytes;
nbytes = write(so->fd, chunk, size);
if (nbytes <= 0) {
g_set_error(error, solaris_output_quark(), errno,
"Write failed: %s", g_strerror(errno));
error.SetErrno("Write failed");
return 0;
}

View File

@@ -22,6 +22,8 @@
#include "OutputAPI.hxx"
#include "pcm/PcmBuffer.hxx"
#include "MixerList.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
#include <stdlib.h>
#include <string.h>
@@ -51,14 +53,7 @@ struct WinmmOutput {
unsigned next_buffer;
};
/**
* The quark used for GError.domain.
*/
static inline GQuark
winmm_output_quark(void)
{
return g_quark_from_static_string("winmm_output");
}
static constexpr Domain winmm_output_domain("winmm_output");
HWAVEOUT
winmm_output_get_handle(WinmmOutput *output)
@@ -73,7 +68,7 @@ winmm_output_test_default_device(void)
}
static bool
get_device_id(const char *device_name, UINT *device_id, GError **error_r)
get_device_id(const char *device_name, UINT *device_id, Error &error)
{
/* if device is not specified use wave mapper */
if (device_name == nullptr) {
@@ -108,22 +103,22 @@ get_device_id(const char *device_name, UINT *device_id, GError **error_r)
}
fail:
g_set_error(error_r, winmm_output_quark(), 0,
"device \"%s\" is not found", device_name);
error.Format(winmm_output_domain,
"device \"%s\" is not found", device_name);
return false;
}
static struct audio_output *
winmm_output_init(const config_param &param, GError **error_r)
winmm_output_init(const config_param &param, Error &error)
{
WinmmOutput *wo = new WinmmOutput();
if (!ao_base_init(&wo->base, &winmm_output_plugin, param, error_r)) {
if (!ao_base_init(&wo->base, &winmm_output_plugin, param, error)) {
g_free(wo);
return nullptr;
}
const char *device = param.GetBlockValue("device");
if (!get_device_id(device, &wo->device_id, error_r)) {
if (!get_device_id(device, &wo->device_id, error)) {
ao_base_finish(&wo->base);
g_free(wo);
return nullptr;
@@ -143,14 +138,13 @@ winmm_output_finish(struct audio_output *ao)
static bool
winmm_output_open(struct audio_output *ao, AudioFormat &audio_format,
GError **error_r)
Error &error)
{
WinmmOutput *wo = (WinmmOutput *)ao;
wo->event = CreateEvent(nullptr, false, false, nullptr);
if (wo->event == nullptr) {
g_set_error(error_r, winmm_output_quark(), 0,
"CreateEvent() failed");
error.Set(winmm_output_domain, "CreateEvent() failed");
return false;
}
@@ -186,8 +180,7 @@ winmm_output_open(struct audio_output *ao, AudioFormat &audio_format,
(DWORD_PTR)wo->event, 0, CALLBACK_EVENT);
if (result != MMSYSERR_NOERROR) {
CloseHandle(wo->event);
g_set_error(error_r, winmm_output_quark(), result,
"waveOutOpen() failed");
error.Set(winmm_output_domain, "waveOutOpen() failed");
return false;
}
@@ -219,7 +212,7 @@ winmm_output_close(struct audio_output *ao)
static bool
winmm_set_buffer(WinmmOutput *wo, WinmmBuffer *buffer,
const void *data, size_t size,
GError **error_r)
Error &error)
{
void *dest = buffer->buffer.Get(size);
assert(dest != nullptr);
@@ -233,8 +226,8 @@ winmm_set_buffer(WinmmOutput *wo, WinmmBuffer *buffer,
MMRESULT result = waveOutPrepareHeader(wo->handle, &buffer->hdr,
sizeof(buffer->hdr));
if (result != MMSYSERR_NOERROR) {
g_set_error(error_r, winmm_output_quark(), result,
"waveOutPrepareHeader() failed");
error.Set(winmm_output_domain, result,
"waveOutPrepareHeader() failed");
return false;
}
@@ -246,7 +239,7 @@ winmm_set_buffer(WinmmOutput *wo, WinmmBuffer *buffer,
*/
static bool
winmm_drain_buffer(WinmmOutput *wo, WinmmBuffer *buffer,
GError **error_r)
Error &error)
{
if ((buffer->hdr.dwFlags & WHDR_DONE) == WHDR_DONE)
/* already finished */
@@ -259,8 +252,8 @@ winmm_drain_buffer(WinmmOutput *wo, WinmmBuffer *buffer,
if (result == MMSYSERR_NOERROR)
return true;
else if (result != WAVERR_STILLPLAYING) {
g_set_error(error_r, winmm_output_quark(), result,
"waveOutUnprepareHeader() failed");
error.Set(winmm_output_domain, result,
"waveOutUnprepareHeader() failed");
return false;
}
@@ -270,14 +263,14 @@ winmm_drain_buffer(WinmmOutput *wo, WinmmBuffer *buffer,
}
static size_t
winmm_output_play(struct audio_output *ao, const void *chunk, size_t size, GError **error_r)
winmm_output_play(struct audio_output *ao, const void *chunk, size_t size, Error &error)
{
WinmmOutput *wo = (WinmmOutput *)ao;
/* get the next buffer from the ring and prepare it */
WinmmBuffer *buffer = &wo->buffers[wo->next_buffer];
if (!winmm_drain_buffer(wo, buffer, error_r) ||
!winmm_set_buffer(wo, buffer, chunk, size, error_r))
if (!winmm_drain_buffer(wo, buffer, error) ||
!winmm_set_buffer(wo, buffer, chunk, size, error))
return 0;
/* enqueue the buffer */
@@ -286,8 +279,8 @@ winmm_output_play(struct audio_output *ao, const void *chunk, size_t size, GErro
if (result != MMSYSERR_NOERROR) {
waveOutUnprepareHeader(wo->handle, &buffer->hdr,
sizeof(buffer->hdr));
g_set_error(error_r, winmm_output_quark(), result,
"waveOutWrite() failed");
error.Set(winmm_output_domain, result,
"waveOutWrite() failed");
return 0;
}
@@ -299,14 +292,14 @@ winmm_output_play(struct audio_output *ao, const void *chunk, size_t size, GErro
}
static bool
winmm_drain_all_buffers(WinmmOutput *wo, GError **error_r)
winmm_drain_all_buffers(WinmmOutput *wo, Error &error)
{
for (unsigned i = wo->next_buffer; i < G_N_ELEMENTS(wo->buffers); ++i)
if (!winmm_drain_buffer(wo, &wo->buffers[i], error_r))
if (!winmm_drain_buffer(wo, &wo->buffers[i], error))
return false;
for (unsigned i = 0; i < wo->next_buffer; ++i)
if (!winmm_drain_buffer(wo, &wo->buffers[i], error_r))
if (!winmm_drain_buffer(wo, &wo->buffers[i], error))
return false;
return true;
@@ -329,7 +322,7 @@ winmm_output_drain(struct audio_output *ao)
{
WinmmOutput *wo = (WinmmOutput *)ao;
if (!winmm_drain_all_buffers(wo, nullptr))
if (!winmm_drain_all_buffers(wo, IgnoreError()))
winmm_stop(wo);
}