output: move functions into the AudioOutput struct

This commit is contained in:
Max Kellermann 2014-01-28 11:39:12 +01:00
parent cb7366f472
commit 4657a3bd0f
25 changed files with 290 additions and 338 deletions

View File

@ -963,9 +963,9 @@ OUTPUT_API_SRC = \
src/output/Internal.hxx \
src/output/Registry.cxx src/output/Registry.hxx \
src/output/MultipleOutputs.cxx src/output/MultipleOutputs.hxx \
src/output/OutputThread.cxx src/output/OutputThread.hxx \
src/output/OutputThread.cxx \
src/output/Domain.cxx src/output/Domain.hxx \
src/output/OutputControl.cxx src/output/OutputControl.hxx \
src/output/OutputControl.cxx \
src/output/OutputState.cxx src/output/OutputState.hxx \
src/output/OutputPrint.cxx src/output/OutputPrint.hxx \
src/output/OutputCommand.cxx src/output/OutputCommand.hxx \

View File

@ -147,14 +147,11 @@ audio_output_load_mixer(AudioOutput *ao,
}
bool
ao_base_init(AudioOutput *ao,
const config_param &param, Error &error)
AudioOutput::Configure(const config_param &param, Error &error)
{
assert(ao != nullptr);
if (!param.IsNull()) {
ao->name = param.GetBlockValue(AUDIO_OUTPUT_NAME);
if (ao->name == nullptr) {
name = param.GetBlockValue(AUDIO_OUTPUT_NAME);
if (name == nullptr) {
error.Set(config_domain,
"Missing \"name\" configuration");
return false;
@ -163,26 +160,26 @@ ao_base_init(AudioOutput *ao,
const char *p = param.GetBlockValue(AUDIO_OUTPUT_FORMAT);
if (p != nullptr) {
bool success =
audio_format_parse(ao->config_audio_format,
audio_format_parse(config_audio_format,
p, true, error);
if (!success)
return false;
} else
ao->config_audio_format.Clear();
config_audio_format.Clear();
} else {
ao->name = "default detected output";
name = "default detected output";
ao->config_audio_format.Clear();
config_audio_format.Clear();
}
ao->tags = param.GetBlockValue("tags", true);
ao->always_on = param.GetBlockValue("always_on", false);
ao->enabled = param.GetBlockValue("enabled", true);
tags = param.GetBlockValue("tags", true);
always_on = param.GetBlockValue("always_on", false);
enabled = param.GetBlockValue("enabled", true);
/* set up the filter chain */
ao->filter = filter_chain_new();
assert(ao->filter != nullptr);
filter = filter_chain_new();
assert(filter != nullptr);
/* create the normalization filter (if configured) */
@ -192,12 +189,12 @@ ao_base_init(AudioOutput *ao,
IgnoreError());
assert(normalize_filter != nullptr);
filter_chain_append(*ao->filter, "normalize",
filter_chain_append(*filter, "normalize",
autoconvert_filter_new(normalize_filter));
}
Error filter_error;
filter_chain_parse(*ao->filter,
filter_chain_parse(*filter,
param.GetBlockValue(AUDIO_FILTERS, ""),
filter_error);
@ -206,7 +203,7 @@ ao_base_init(AudioOutput *ao,
if (filter_error.IsDefined())
FormatError(filter_error,
"Failed to initialize filter chain for '%s'",
ao->name);
name);
/* done */

View File

@ -23,6 +23,7 @@
#include "AudioFormat.hxx"
#include "pcm/PcmBuffer.hxx"
#include "pcm/PcmDither.hxx"
#include "ReplayGainInfo.hxx"
#include "thread/Mutex.hxx"
#include "thread/Cond.hxx"
#include "thread/Thread.hxx"
@ -266,6 +267,106 @@ struct AudioOutput {
AudioOutput(const AudioOutputPlugin &_plugin);
~AudioOutput();
bool Configure(const config_param &param, Error &error);
void StartThread();
void StopThread();
void Finish();
bool IsOpen() const {
return open;
}
bool IsCommandFinished() const {
return command == AO_COMMAND_NONE;
}
/**
* Waits for command completion.
*
* Caller must lock the mutex.
*/
void WaitForCommand();
/**
* Sends a command, but does not wait for completion.
*
* Caller must lock the mutex.
*/
void CommandAsync(audio_output_command cmd);
/**
* Sends a command to the #AudioOutput object and waits for
* completion.
*
* Caller must lock the mutex.
*/
void CommandWait(audio_output_command cmd);
/**
* Lock the #AudioOutput object and execute the command
* synchronously.
*/
void LockCommandWait(audio_output_command cmd);
/**
* Enables the device.
*/
void LockEnableWait();
/**
* Disables the device.
*/
void LockDisableWait();
void LockPauseAsync();
/**
* Same LockCloseWait(), but expects the lock to be
* held by the caller.
*/
void CloseWait();
void LockCloseWait();
/**
* Closes the audio output, but if the "always_on" flag is set, put it
* into pause mode instead.
*/
void LockRelease();
void SetReplayGainMode(ReplayGainMode mode);
/**
* Caller must lock the mutex.
*/
bool Open(const AudioFormat audio_format, const MusicPipe &mp);
/**
* Opens or closes the device, depending on the "enabled"
* flag.
*
* @return true if the device is open
*/
bool LockUpdate(const AudioFormat audio_format,
const MusicPipe &mp);
void LockPlay();
void LockDrainAsync();
/**
* Clear the "allow_play" flag and send the "CANCEL" command
* asynchronously. To finish the operation, the caller has to
* call LockAllowPlay().
*/
void LockCancelAsync();
/**
* Set the "allow_play" and signal the thread.
*/
void LockAllowPlay();
};
/**
@ -274,27 +375,11 @@ struct AudioOutput {
*/
extern struct notify audio_output_client_notify;
static inline bool
audio_output_is_open(const AudioOutput *ao)
{
return ao->open;
}
static inline bool
audio_output_command_is_finished(const AudioOutput *ao)
{
return ao->command == AO_COMMAND_NONE;
}
AudioOutput *
audio_output_new(const config_param &param,
PlayerControl &pc,
Error &error);
bool
ao_base_init(AudioOutput *ao,
const config_param &param, Error &error);
void
audio_output_free(AudioOutput *ao);

View File

@ -21,7 +21,6 @@
#include "MultipleOutputs.hxx"
#include "PlayerControl.hxx"
#include "Internal.hxx"
#include "OutputControl.hxx"
#include "Domain.hxx"
#include "MusicBuffer.hxx"
#include "MusicPipe.hxx"
@ -45,8 +44,8 @@ MultipleOutputs::MultipleOutputs()
MultipleOutputs::~MultipleOutputs()
{
for (auto i : outputs) {
audio_output_disable(i);
audio_output_finish(i);
i->LockDisableWait();
i->Finish();
}
}
@ -111,9 +110,9 @@ MultipleOutputs::EnableDisable()
if (ao->enabled != enabled) {
if (ao->enabled)
audio_output_enable(ao);
ao->LockEnableWait();
else
audio_output_disable(ao);
ao->LockDisableWait();
}
}
}
@ -123,8 +122,7 @@ MultipleOutputs::AllFinished() const
{
for (auto ao : outputs) {
const ScopeLock protect(ao->mutex);
if (audio_output_is_open(ao) &&
!audio_output_command_is_finished(ao))
if (ao->IsOpen() && !ao->IsCommandFinished())
return false;
}
@ -142,7 +140,7 @@ void
MultipleOutputs::AllowPlay()
{
for (auto ao : outputs)
audio_output_allow_play(ao);
ao->LockAllowPlay();
}
static void
@ -169,7 +167,7 @@ MultipleOutputs::Update()
return false;
for (auto ao : outputs)
ret = audio_output_update(ao, input_audio_format, *pipe)
ret = ao->LockUpdate(input_audio_format, *pipe)
|| ret;
return ret;
@ -179,7 +177,7 @@ void
MultipleOutputs::SetReplayGainMode(ReplayGainMode mode)
{
for (auto ao : outputs)
audio_output_set_replay_gain_mode(ao, mode);
ao->SetReplayGainMode(mode);
}
bool
@ -199,7 +197,7 @@ MultipleOutputs::Play(music_chunk *chunk, Error &error)
pipe->Push(chunk);
for (auto ao : outputs)
audio_output_play(ao);
ao->LockPlay();
return true;
}
@ -387,7 +385,7 @@ MultipleOutputs::Pause()
Update();
for (auto ao : outputs)
audio_output_pause(ao);
ao->LockPauseAsync();
WaitAll();
}
@ -396,7 +394,7 @@ void
MultipleOutputs::Drain()
{
for (auto ao : outputs)
audio_output_drain_async(ao);
ao->LockDrainAsync();
WaitAll();
}
@ -407,7 +405,7 @@ MultipleOutputs::Cancel()
/* send the cancel() command to all audio outputs */
for (auto ao : outputs)
audio_output_cancel(ao);
ao->LockCancelAsync();
WaitAll();
@ -430,7 +428,7 @@ void
MultipleOutputs::Close()
{
for (auto ao : outputs)
audio_output_close(ao);
ao->LockCloseWait();
if (pipe != nullptr) {
assert(buffer != nullptr);
@ -451,7 +449,7 @@ void
MultipleOutputs::Release()
{
for (auto ao : outputs)
audio_output_release(ao);
ao->LockRelease();
if (pipe != nullptr) {
assert(buffer != nullptr);

View File

@ -1,4 +1,3 @@
/*
* Copyright (C) 2003-2014 The Music Player Daemon Project
* http://www.musicpd.org
@ -19,8 +18,6 @@
*/
#include "config.h"
#include "OutputControl.hxx"
#include "OutputThread.hxx"
#include "Internal.hxx"
#include "OutputPlugin.hxx"
#include "Domain.hxx"
@ -38,126 +35,97 @@ static constexpr unsigned REOPEN_AFTER = 10;
struct notify audio_output_client_notify;
/**
* Waits for command completion.
*
* @param ao the #AudioOutput instance; must be locked
*/
static void ao_command_wait(AudioOutput *ao)
void
AudioOutput::WaitForCommand()
{
while (ao->command != AO_COMMAND_NONE) {
ao->mutex.unlock();
while (!IsCommandFinished()) {
mutex.unlock();
audio_output_client_notify.Wait();
ao->mutex.lock();
mutex.lock();
}
}
/**
* Sends a command to the #AudioOutput object, but does not wait for
* completion.
*
* @param ao the #AudioOutput instance; must be locked
*/
static void ao_command_async(AudioOutput *ao,
enum audio_output_command cmd)
void
AudioOutput::CommandAsync(audio_output_command cmd)
{
assert(ao->command == AO_COMMAND_NONE);
ao->command = cmd;
ao->cond.signal();
}
assert(IsCommandFinished());
/**
* Sends a command to the #AudioOutput object and waits for
* completion.
*
* @param ao the #AudioOutput instance; must be locked
*/
static void
ao_command(AudioOutput *ao, enum audio_output_command cmd)
{
ao_command_async(ao, cmd);
ao_command_wait(ao);
}
/**
* Lock the #AudioOutput object and execute the command
* synchronously.
*/
static void
ao_lock_command(AudioOutput *ao, enum audio_output_command cmd)
{
const ScopeLock protect(ao->mutex);
ao_command(ao, cmd);
command = cmd;
cond.signal();
}
void
audio_output_set_replay_gain_mode(AudioOutput *ao,
ReplayGainMode mode)
AudioOutput::CommandWait(audio_output_command cmd)
{
if (ao->replay_gain_filter != nullptr)
replay_gain_filter_set_mode(ao->replay_gain_filter, mode);
if (ao->other_replay_gain_filter != nullptr)
replay_gain_filter_set_mode(ao->other_replay_gain_filter, mode);
CommandAsync(cmd);
WaitForCommand();
}
void
audio_output_enable(AudioOutput *ao)
AudioOutput::LockCommandWait(audio_output_command cmd)
{
if (!ao->thread.IsDefined()) {
if (ao->plugin.enable == nullptr) {
const ScopeLock protect(mutex);
CommandWait(cmd);
}
void
AudioOutput::SetReplayGainMode(ReplayGainMode mode)
{
if (replay_gain_filter != nullptr)
replay_gain_filter_set_mode(replay_gain_filter, mode);
if (other_replay_gain_filter != nullptr)
replay_gain_filter_set_mode(other_replay_gain_filter, mode);
}
void
AudioOutput::LockEnableWait()
{
if (!thread.IsDefined()) {
if (plugin.enable == nullptr) {
/* don't bother to start the thread now if the
device doesn't even have a enable() method;
just assign the variable and we're done */
ao->really_enabled = true;
really_enabled = true;
return;
}
audio_output_thread_start(ao);
StartThread();
}
ao_lock_command(ao, AO_COMMAND_ENABLE);
LockCommandWait(AO_COMMAND_ENABLE);
}
void
audio_output_disable(AudioOutput *ao)
AudioOutput::LockDisableWait()
{
if (!ao->thread.IsDefined()) {
if (ao->plugin.disable == nullptr)
ao->really_enabled = false;
if (!thread.IsDefined()) {
if (plugin.disable == nullptr)
really_enabled = false;
else
/* if there's no thread yet, the device cannot
be enabled */
assert(!ao->really_enabled);
assert(!really_enabled);
return;
}
ao_lock_command(ao, AO_COMMAND_DISABLE);
LockCommandWait(AO_COMMAND_DISABLE);
}
/**
* Object must be locked (and unlocked) by the caller.
*/
static bool
audio_output_open(AudioOutput *ao,
const AudioFormat audio_format,
const MusicPipe &mp)
inline bool
AudioOutput::Open(const AudioFormat audio_format, const MusicPipe &mp)
{
bool open;
assert(ao != nullptr);
assert(ao->allow_play);
assert(allow_play);
assert(audio_format.IsValid());
ao->fail_timer.Reset();
fail_timer.Reset();
if (ao->open && audio_format == ao->in_audio_format) {
assert(ao->pipe == &mp ||
(ao->always_on && ao->pause));
if (open && audio_format == in_audio_format) {
assert(pipe == &mp || (always_on && pause));
if (ao->pause) {
ao->chunk = nullptr;
ao->pipe = ∓
if (pause) {
chunk = nullptr;
pipe = ∓
/* unpause with the CANCEL command; this is a
hack, but suits well for forcing the thread
@ -166,160 +134,162 @@ audio_output_open(AudioOutput *ao,
/* we're not using audio_output_cancel() here,
because that function is asynchronous */
ao_command(ao, AO_COMMAND_CANCEL);
CommandWait(AO_COMMAND_CANCEL);
}
return true;
}
ao->in_audio_format = audio_format;
ao->chunk = nullptr;
in_audio_format = audio_format;
chunk = nullptr;
ao->pipe = ∓
pipe = ∓
if (!ao->thread.IsDefined())
audio_output_thread_start(ao);
if (!thread.IsDefined())
StartThread();
ao_command(ao, ao->open ? AO_COMMAND_REOPEN : AO_COMMAND_OPEN);
open = ao->open;
CommandWait(open ? AO_COMMAND_REOPEN : AO_COMMAND_OPEN);
const bool open2 = open;
if (open && ao->mixer != nullptr) {
if (open2 && mixer != nullptr) {
Error error;
if (!mixer_open(ao->mixer, error))
if (!mixer_open(mixer, error))
FormatWarning(output_domain,
"Failed to open mixer for '%s'",
ao->name);
"Failed to open mixer for '%s'", name);
}
return open;
return open2;
}
/**
* Same as audio_output_close(), but expects the lock to be held by
* the caller.
*/
static void
audio_output_close_locked(AudioOutput *ao)
void
AudioOutput::CloseWait()
{
assert(ao != nullptr);
assert(ao->allow_play);
assert(allow_play);
if (ao->mixer != nullptr)
mixer_auto_close(ao->mixer);
if (mixer != nullptr)
mixer_auto_close(mixer);
assert(!ao->open || !ao->fail_timer.IsDefined());
assert(!open || !fail_timer.IsDefined());
if (ao->open)
ao_command(ao, AO_COMMAND_CLOSE);
if (open)
CommandWait(AO_COMMAND_CLOSE);
else
ao->fail_timer.Reset();
fail_timer.Reset();
}
bool
audio_output_update(AudioOutput *ao,
const AudioFormat audio_format,
AudioOutput::LockUpdate(const AudioFormat audio_format,
const MusicPipe &mp)
{
const ScopeLock protect(ao->mutex);
const ScopeLock protect(mutex);
if (ao->enabled && ao->really_enabled) {
if (ao->fail_timer.Check(REOPEN_AFTER * 1000)) {
return audio_output_open(ao, audio_format, mp);
if (enabled && really_enabled) {
if (fail_timer.Check(REOPEN_AFTER * 1000)) {
return Open(audio_format, mp);
}
} else if (audio_output_is_open(ao))
audio_output_close_locked(ao);
} else if (IsOpen())
CloseWait();
return false;
}
void
audio_output_play(AudioOutput *ao)
AudioOutput::LockPlay()
{
const ScopeLock protect(ao->mutex);
const ScopeLock protect(mutex);
assert(ao->allow_play);
assert(allow_play);
if (audio_output_is_open(ao) && !ao->in_playback_loop &&
!ao->woken_for_play) {
ao->woken_for_play = true;
ao->cond.signal();
if (IsOpen() && !in_playback_loop && !woken_for_play) {
woken_for_play = true;
cond.signal();
}
}
void audio_output_pause(AudioOutput *ao)
void
AudioOutput::LockPauseAsync()
{
if (ao->mixer != nullptr && ao->plugin.pause == nullptr)
if (mixer != nullptr && plugin.pause == nullptr)
/* the device has no pause mode: close the mixer,
unless its "global" flag is set (checked by
mixer_auto_close()) */
mixer_auto_close(ao->mixer);
mixer_auto_close(mixer);
const ScopeLock protect(ao->mutex);
const ScopeLock protect(mutex);
assert(ao->allow_play);
if (audio_output_is_open(ao))
ao_command_async(ao, AO_COMMAND_PAUSE);
assert(allow_play);
if (IsOpen())
CommandAsync(AO_COMMAND_PAUSE);
}
void
audio_output_drain_async(AudioOutput *ao)
AudioOutput::LockDrainAsync()
{
const ScopeLock protect(ao->mutex);
const ScopeLock protect(mutex);
assert(ao->allow_play);
if (audio_output_is_open(ao))
ao_command_async(ao, AO_COMMAND_DRAIN);
assert(allow_play);
if (IsOpen())
CommandAsync(AO_COMMAND_DRAIN);
}
void audio_output_cancel(AudioOutput *ao)
void
AudioOutput::LockCancelAsync()
{
const ScopeLock protect(ao->mutex);
const ScopeLock protect(mutex);
if (audio_output_is_open(ao)) {
ao->allow_play = false;
ao_command_async(ao, AO_COMMAND_CANCEL);
if (IsOpen()) {
allow_play = false;
CommandAsync(AO_COMMAND_CANCEL);
}
}
void
audio_output_allow_play(AudioOutput *ao)
AudioOutput::LockAllowPlay()
{
const ScopeLock protect(ao->mutex);
const ScopeLock protect(mutex);
ao->allow_play = true;
if (audio_output_is_open(ao))
ao->cond.signal();
allow_play = true;
if (IsOpen())
cond.signal();
}
void
audio_output_release(AudioOutput *ao)
AudioOutput::LockRelease()
{
if (ao->always_on)
audio_output_pause(ao);
if (always_on)
LockPauseAsync();
else
audio_output_close(ao);
LockCloseWait();
}
void audio_output_close(AudioOutput *ao)
void
AudioOutput::LockCloseWait()
{
assert(ao != nullptr);
assert(!ao->open || !ao->fail_timer.IsDefined());
assert(!open || !fail_timer.IsDefined());
const ScopeLock protect(ao->mutex);
audio_output_close_locked(ao);
const ScopeLock protect(mutex);
CloseWait();
}
void audio_output_finish(AudioOutput *ao)
void
AudioOutput::StopThread()
{
audio_output_close(ao);
assert(thread.IsDefined());
assert(allow_play);
assert(!ao->fail_timer.IsDefined());
if (ao->thread.IsDefined()) {
assert(ao->allow_play);
ao_lock_command(ao, AO_COMMAND_KILL);
ao->thread.Join();
}
audio_output_free(ao);
LockCommandWait(AO_COMMAND_KILL);
thread.Join();
}
void
AudioOutput::Finish()
{
LockCloseWait();
assert(!fail_timer.IsDefined());
if (thread.IsDefined())
StopThread();
audio_output_free(this);
}

View File

@ -20,75 +20,6 @@
#ifndef MPD_OUTPUT_CONTROL_HXX
#define MPD_OUTPUT_CONTROL_HXX
#include "ReplayGainInfo.hxx"
#include <stddef.h>
struct AudioOutput;
struct AudioFormat;
struct config_param;
class MusicPipe;
void
audio_output_set_replay_gain_mode(AudioOutput *ao,
ReplayGainMode mode);
/**
* Enables the device.
*/
void
audio_output_enable(AudioOutput *ao);
/**
* Disables the device.
*/
void
audio_output_disable(AudioOutput *ao);
/**
* Opens or closes the device, depending on the "enabled" flag.
*
* @return true if the device is open
*/
bool
audio_output_update(AudioOutput *ao,
AudioFormat audio_format,
const MusicPipe &mp);
void
audio_output_play(AudioOutput *ao);
void
audio_output_pause(AudioOutput *ao);
void
audio_output_drain_async(AudioOutput *ao);
/**
* Clear the "allow_play" flag and send the "CANCEL" command
* asynchronously. To finish the operation, the caller has to call
* audio_output_allow_play().
*/
void
audio_output_cancel(AudioOutput *ao);
/**
* Set the "allow_play" and signal the thread.
*/
void
audio_output_allow_play(AudioOutput *ao);
void
audio_output_close(AudioOutput *ao);
/**
* Closes the audio output, but if the "always_on" flag is set, put it
* into pause mode instead.
*/
void
audio_output_release(AudioOutput *ao);
void
audio_output_finish(AudioOutput *ao);
#endif

View File

@ -18,7 +18,6 @@
*/
#include "config.h"
#include "OutputThread.hxx"
#include "Internal.hxx"
#include "OutputAPI.hxx"
#include "Domain.hxx"
@ -680,11 +679,12 @@ audio_output_task(void *arg)
}
}
void audio_output_thread_start(AudioOutput *ao)
void
AudioOutput::StartThread()
{
assert(ao->command == AO_COMMAND_NONE);
assert(command == AO_COMMAND_NONE);
Error error;
if (!ao->thread.Start(audio_output_task, ao, error))
if (!thread.Start(audio_output_task, this, error))
FatalError(error);
}

View File

@ -1,28 +0,0 @@
/*
* Copyright (C) 2003-2014 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef MPD_OUTPUT_THREAD_HXX
#define MPD_OUTPUT_THREAD_HXX
struct AudioOutput;
void
audio_output_thread_start(AudioOutput *ao);
#endif

View File

@ -125,7 +125,7 @@ struct AlsaOutput {
}
bool Init(const config_param &param, Error &error) {
return ao_base_init(&base, param, error);
return base.Configure(param, error);
}
};

View File

@ -46,7 +46,7 @@ struct AoOutput {
:base(ao_output_plugin) {}
bool Initialize(const config_param &param, Error &error) {
return ao_base_init(&base, param, error);
return base.Configure(param, error);
}
bool Configure(const config_param &param, Error &error);

View File

@ -52,7 +52,7 @@ struct FifoOutput {
created(false) {}
bool Initialize(const config_param &param, Error &error) {
return ao_base_init(&base, param, error);
return base.Configure(param, error);
}
bool Create(Error &error);

View File

@ -137,7 +137,7 @@ HttpdOutput::Configure(const config_param &param, Error &error)
inline bool
HttpdOutput::Init(const config_param &param, Error &error)
{
return ao_base_init(&base, param, error);
return base.Configure(param, error);
}
static AudioOutput *

View File

@ -83,7 +83,7 @@ struct JackOutput {
:base(jack_output_plugin) {}
bool Initialize(const config_param &param, Error &error_r) {
return ao_base_init(&base, param, error_r);
return base.Configure(param, error_r);
}
};

View File

@ -33,7 +33,7 @@ struct NullOutput {
:base(null_output_plugin) {}
bool Initialize(const config_param &param, Error &error) {
return ao_base_init(&base, param, error);
return base.Configure(param, error);
}
};

View File

@ -84,7 +84,7 @@ static AudioOutput *
osx_output_init(const config_param &param, Error &error)
{
OSXOutput *oo = new OSXOutput();
if (!ao_base_init(&oo->base, param, error)) {
if (!oo->base.Configure(param, error)) {
delete oo;
return NULL;
}

View File

@ -52,7 +52,7 @@ struct OpenALOutput {
:base(openal_output_plugin) {}
bool Initialize(const config_param &param, Error &error_r) {
return ao_base_init(&base, param, error_r);
return base.Configure(param, error_r);
}
};

View File

@ -83,7 +83,7 @@ struct OssOutput {
fd(-1), device(nullptr) {}
bool Initialize(const config_param &param, Error &error_r) {
return ao_base_init(&base, param, error_r);
return base.Configure(param, error_r);
}
};

View File

@ -38,7 +38,7 @@ struct PipeOutput {
:base(pipe_output_plugin) {}
bool Initialize(const config_param &param, Error &error) {
return ao_base_init(&base, param, error);
return base.Configure(param, error);
}
bool Configure(const config_param &param, Error &error);

View File

@ -334,7 +334,7 @@ pulse_output_init(const config_param &param, Error &error)
g_setenv("PULSE_PROP_media.role", "music", true);
po = new PulseOutput();
if (!ao_base_init(&po->base, param, error)) {
if (!po->base.Configure(param, error)) {
delete po;
return nullptr;
}

View File

@ -61,7 +61,7 @@ struct RecorderOutput {
:base(recorder_output_plugin) {}
bool Initialize(const config_param &param, Error &error_r) {
return ao_base_init(&base, param, error_r);
return base.Configure(param, error_r);
}
bool Configure(const config_param &param, Error &error);

View File

@ -58,7 +58,7 @@ public:
}
bool Initialize(const config_param &param, Error &error) {
return ao_base_init(&base, param, error);
return base.Configure(param, error);
}
void Configure(const config_param &param);

View File

@ -69,7 +69,7 @@ struct ShoutOutput final {
}
bool Initialize(const config_param &param, Error &error) {
return ao_base_init(&base, param, error);
return base.Configure(param, error);
}
bool Configure(const config_param &param, Error &error);

View File

@ -61,7 +61,7 @@ struct SolarisOutput {
:base(solaris_output_plugin) {}
bool Initialize(const config_param &param, Error &error_r) {
return ao_base_init(&base, param, error_r);
return base.Configure(param, error_r);
}
};

View File

@ -52,7 +52,7 @@ struct WinmmOutput {
WinmmBuffer buffers[8];
unsigned next_buffer;
WinmmBuffer()
WinmmOutput()
:base(winmm_output_plugin) {}
};
@ -115,7 +115,7 @@ static AudioOutput *
winmm_output_init(const config_param &param, Error &error)
{
WinmmOutput *wo = new WinmmOutput();
if (!ao_base_init(&wo->base, param, error)) {
if (!wo->base.Configure(param, error)) {
delete wo;
return nullptr;
}

View File

@ -18,7 +18,6 @@
*/
#include "config.h"
#include "output/OutputControl.hxx"
#include "output/Internal.hxx"
#include "output/OutputPlugin.hxx"
#include "config/ConfigData.hxx"