output/MultipleOutputs: wrap AudioOutputControl in std::unique_ptr<>

This commit is contained in:
Max Kellermann 2019-04-26 14:28:59 +02:00
parent b42f19f514
commit 376f4a2b16
3 changed files with 45 additions and 54 deletions

View File

@ -56,7 +56,7 @@ MultipleOutputs::GetVolume() const noexcept
unsigned ok = 0; unsigned ok = 0;
int total = 0; int total = 0;
for (auto *ao : outputs) { for (const auto &ao : outputs) {
int volume = output_mixer_get_volume(*ao); int volume = output_mixer_get_volume(*ao);
if (volume >= 0) { if (volume >= 0) {
total += volume; total += volume;
@ -99,7 +99,7 @@ MultipleOutputs::SetVolume(unsigned volume) noexcept
assert(volume <= 100); assert(volume <= 100);
bool success = false; bool success = false;
for (auto *ao : outputs) for (const auto &ao : outputs)
success = output_mixer_set_volume(*ao, volume) success = output_mixer_set_volume(*ao, volume)
|| success; || success;
@ -125,7 +125,7 @@ MultipleOutputs::GetSoftwareVolume() const noexcept
unsigned ok = 0; unsigned ok = 0;
int total = 0; int total = 0;
for (auto *ao : outputs) { for (const auto &ao : outputs) {
int volume = output_mixer_get_software_volume(*ao); int volume = output_mixer_get_software_volume(*ao);
if (volume >= 0) { if (volume >= 0) {
total += volume; total += volume;
@ -144,7 +144,7 @@ MultipleOutputs::SetSoftwareVolume(unsigned volume) noexcept
{ {
assert(volume <= PCM_VOLUME_1); assert(volume <= PCM_VOLUME_1);
for (auto *ao : outputs) { for (const auto &ao : outputs) {
auto *mixer = ao->GetMixer(); auto *mixer = ao->GetMixer();
if (mixer != nullptr && if (mixer != nullptr &&

View File

@ -42,10 +42,8 @@ MultipleOutputs::MultipleOutputs(MixerListener &_mixer_listener) noexcept
MultipleOutputs::~MultipleOutputs() noexcept MultipleOutputs::~MultipleOutputs() noexcept
{ {
/* parallel destruction */ /* parallel destruction */
for (auto *i : outputs) for (const auto &i : outputs)
i->BeginDestroy(); i->BeginDestroy();
for (auto *i : outputs)
delete i;
} }
static std::unique_ptr<FilteredAudioOutput> static std::unique_ptr<FilteredAudioOutput>
@ -68,7 +66,7 @@ try {
throw; throw;
} }
static AudioOutputControl * static std::unique_ptr<AudioOutputControl>
LoadOutputControl(EventLoop &event_loop, LoadOutputControl(EventLoop &event_loop,
const ReplayGainConfig &replay_gain_config, const ReplayGainConfig &replay_gain_config,
MixerListener &mixer_listener, MixerListener &mixer_listener,
@ -79,15 +77,8 @@ LoadOutputControl(EventLoop &event_loop,
auto output = LoadOutput(event_loop, replay_gain_config, auto output = LoadOutput(event_loop, replay_gain_config,
mixer_listener, mixer_listener,
block, defaults, filter_factory); block, defaults, filter_factory);
auto *control = new AudioOutputControl(std::move(output), client); auto control = std::make_unique<AudioOutputControl>(std::move(output), client);
control->Configure(block);
try {
control->Configure(block);
} catch (...) {
delete control;
throw;
}
return control; return control;
} }
@ -102,27 +93,26 @@ MultipleOutputs::Configure(EventLoop &event_loop,
for (const auto &block : config.GetBlockList(ConfigBlockOption::AUDIO_OUTPUT)) { for (const auto &block : config.GetBlockList(ConfigBlockOption::AUDIO_OUTPUT)) {
block.SetUsed(); block.SetUsed();
auto *output = LoadOutputControl(event_loop, auto output = LoadOutputControl(event_loop,
replay_gain_config, replay_gain_config,
mixer_listener, mixer_listener,
client, block, defaults, client, block, defaults,
&filter_factory); &filter_factory);
if (FindByName(output->GetName()) != nullptr) if (FindByName(output->GetName()) != nullptr)
throw FormatRuntimeError("output devices with identical " throw FormatRuntimeError("output devices with identical "
"names: %s", output->GetName()); "names: %s", output->GetName());
outputs.push_back(output); outputs.emplace_back(std::move(output));
} }
if (outputs.empty()) { if (outputs.empty()) {
/* auto-detect device */ /* auto-detect device */
const ConfigBlock empty; const ConfigBlock empty;
auto *output = LoadOutputControl(event_loop, outputs.emplace_back(LoadOutputControl(event_loop,
replay_gain_config, replay_gain_config,
mixer_listener, mixer_listener,
client, empty, defaults, client, empty, defaults,
nullptr); nullptr));
outputs.push_back(output);
} }
} }
@ -136,18 +126,18 @@ MultipleOutputs::AddNullOutput(EventLoop &event_loop,
ConfigBlock block; ConfigBlock block;
block.AddBlockParam("type", "null"); block.AddBlockParam("type", "null");
auto *output = LoadOutputControl(event_loop, replay_gain_config, outputs.emplace_back(LoadOutputControl(event_loop, replay_gain_config,
mixer_listener, mixer_listener,
client, block, defaults, nullptr); client, block, defaults,
outputs.push_back(output); nullptr));
} }
AudioOutputControl * AudioOutputControl *
MultipleOutputs::FindByName(const char *name) noexcept MultipleOutputs::FindByName(const char *name) noexcept
{ {
for (auto *i : outputs) for (const auto &i : outputs)
if (strcmp(i->GetName(), name) == 0) if (strcmp(i->GetName(), name) == 0)
return i; return i.get();
return nullptr; return nullptr;
} }
@ -157,7 +147,7 @@ MultipleOutputs::EnableDisable()
{ {
/* parallel execution */ /* parallel execution */
for (auto *ao : outputs) { for (const auto &ao : outputs) {
const std::lock_guard<Mutex> lock(ao->mutex); const std::lock_guard<Mutex> lock(ao->mutex);
ao->EnableDisableAsync(); ao->EnableDisableAsync();
} }
@ -168,7 +158,7 @@ MultipleOutputs::EnableDisable()
void void
MultipleOutputs::WaitAll() noexcept MultipleOutputs::WaitAll() noexcept
{ {
for (auto *ao : outputs) { for (const auto &ao : outputs) {
const std::lock_guard<Mutex> protect(ao->mutex); const std::lock_guard<Mutex> protect(ao->mutex);
ao->WaitForCommand(); ao->WaitForCommand();
} }
@ -177,7 +167,7 @@ MultipleOutputs::WaitAll() noexcept
void void
MultipleOutputs::AllowPlay() noexcept MultipleOutputs::AllowPlay() noexcept
{ {
for (auto *ao : outputs) for (const auto &ao : outputs)
ao->LockAllowPlay(); ao->LockAllowPlay();
} }
@ -189,7 +179,7 @@ MultipleOutputs::Update(bool force) noexcept
if (!input_audio_format.IsDefined()) if (!input_audio_format.IsDefined())
return false; return false;
for (auto *ao : outputs) for (const auto &ao : outputs)
ret = ao->LockUpdate(input_audio_format, *pipe, force) ret = ao->LockUpdate(input_audio_format, *pipe, force)
|| ret; || ret;
@ -199,7 +189,7 @@ MultipleOutputs::Update(bool force) noexcept
void void
MultipleOutputs::SetReplayGainMode(ReplayGainMode mode) noexcept MultipleOutputs::SetReplayGainMode(ReplayGainMode mode) noexcept
{ {
for (auto *ao : outputs) for (const auto &ao : outputs)
ao->SetReplayGainMode(mode); ao->SetReplayGainMode(mode);
} }
@ -216,7 +206,7 @@ MultipleOutputs::Play(MusicChunkPtr chunk)
pipe->Push(std::move(chunk)); pipe->Push(std::move(chunk));
for (auto *ao : outputs) for (const auto &ao : outputs)
ao->LockPlay(); ao->LockPlay();
} }
@ -243,7 +233,7 @@ MultipleOutputs::Open(const AudioFormat audio_format)
std::exception_ptr first_error; std::exception_ptr first_error;
for (auto *ao : outputs) { for (const auto &ao : outputs) {
const std::lock_guard<Mutex> lock(ao->mutex); const std::lock_guard<Mutex> lock(ao->mutex);
if (ao->IsEnabled()) if (ao->IsEnabled())
@ -274,7 +264,7 @@ MultipleOutputs::Open(const AudioFormat audio_format)
bool bool
MultipleOutputs::IsChunkConsumed(const MusicChunk *chunk) const noexcept MultipleOutputs::IsChunkConsumed(const MusicChunk *chunk) const noexcept
{ {
for (auto *ao : outputs) for (const auto &ao : outputs)
if (!ao->LockIsChunkConsumed(*chunk)) if (!ao->LockIsChunkConsumed(*chunk))
return false; return false;
@ -289,19 +279,19 @@ MultipleOutputs::ClearTailChunk(const MusicChunk *chunk,
assert(pipe->Contains(chunk)); assert(pipe->Contains(chunk));
for (unsigned i = 0, n = outputs.size(); i != n; ++i) { for (unsigned i = 0, n = outputs.size(); i != n; ++i) {
auto *ao = outputs[i]; auto &ao = *outputs[i];
/* this mutex will be unlocked by the caller when it's /* this mutex will be unlocked by the caller when it's
ready */ ready */
ao->mutex.lock(); ao.mutex.lock();
locked[i] = ao->IsOpen(); locked[i] = ao.IsOpen();
if (!locked[i]) { if (!locked[i]) {
ao->mutex.unlock(); ao.mutex.unlock();
continue; continue;
} }
ao->ClearTailChunk(*chunk); ao.ClearTailChunk(*chunk);
} }
} }
@ -356,7 +346,7 @@ MultipleOutputs::Pause() noexcept
{ {
Update(false); Update(false);
for (auto *ao : outputs) for (const auto &ao : outputs)
ao->LockPauseAsync(); ao->LockPauseAsync();
WaitAll(); WaitAll();
@ -365,7 +355,7 @@ MultipleOutputs::Pause() noexcept
void void
MultipleOutputs::Drain() noexcept MultipleOutputs::Drain() noexcept
{ {
for (auto *ao : outputs) for (const auto &ao : outputs)
ao->LockDrainAsync(); ao->LockDrainAsync();
WaitAll(); WaitAll();
@ -376,7 +366,7 @@ MultipleOutputs::Cancel() noexcept
{ {
/* send the cancel() command to all audio outputs */ /* send the cancel() command to all audio outputs */
for (auto *ao : outputs) for (const auto &ao : outputs)
ao->LockCancelAsync(); ao->LockCancelAsync();
WaitAll(); WaitAll();
@ -399,7 +389,7 @@ MultipleOutputs::Cancel() noexcept
void void
MultipleOutputs::Close() noexcept MultipleOutputs::Close() noexcept
{ {
for (auto *ao : outputs) for (const auto &ao : outputs)
ao->LockCloseWait(); ao->LockCloseWait();
pipe.reset(); pipe.reset();
@ -412,7 +402,7 @@ MultipleOutputs::Close() noexcept
void void
MultipleOutputs::Release() noexcept MultipleOutputs::Release() noexcept
{ {
for (auto *ao : outputs) for (const auto &ao : outputs)
ao->LockRelease(); ao->LockRelease();
pipe.reset(); pipe.reset();

View File

@ -34,6 +34,7 @@
#include "Chrono.hxx" #include "Chrono.hxx"
#include "util/Compiler.h" #include "util/Compiler.h"
#include <memory>
#include <vector> #include <vector>
#include <assert.h> #include <assert.h>
@ -48,7 +49,7 @@ struct ReplayGainConfig;
class MultipleOutputs final : public PlayerOutputs { class MultipleOutputs final : public PlayerOutputs {
MixerListener &mixer_listener; MixerListener &mixer_listener;
std::vector<AudioOutputControl *> outputs; std::vector<std::unique_ptr<AudioOutputControl>> outputs;
AudioFormat input_audio_format = AudioFormat::Undefined(); AudioFormat input_audio_format = AudioFormat::Undefined();