output/MultipleOutputs: wrap AudioOutputControl in std::unique_ptr<>
This commit is contained in:
parent
b42f19f514
commit
376f4a2b16
@ -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 &&
|
||||||
|
@ -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();
|
||||||
|
@ -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();
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user