Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ ver 0.25 (not yet released)
* output
- alsa: use hardware pause if available
- pipewire: add option "reconnect_stream"
* mixer
- fix mixer idle events on non-default partitions
* tags
- new tag "DiscSubtitle"
* player
Expand Down
20 changes: 20 additions & 0 deletions src/output/Control.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ AudioOutputControl::AudioOutputControl(std::unique_ptr<FilteredAudioOutput> _out
always_off(block.GetBlockValue("always_off", false)),
enabled(block.GetBlockValue("enabled", true))
{
assert(output->mixer_listener == nullptr);
output->mixer_listener = this;
}

AudioOutputControl::~AudioOutputControl() noexcept
Expand Down Expand Up @@ -426,3 +428,21 @@ AudioOutputControl::StopThread() noexcept

assert(IsCommandFinished());
}

void
AudioOutputControl::OnMixerVolumeChanged(Mixer &_mixer, int volume) noexcept
{
const std::lock_guard lock{mutex};

if (mixer_listener != nullptr)
mixer_listener->OnMixerVolumeChanged(_mixer, volume);
}

void
AudioOutputControl::OnMixerChanged() noexcept
{
const std::lock_guard lock{mutex};

if (mixer_listener != nullptr)
mixer_listener->OnMixerChanged();
}
20 changes: 15 additions & 5 deletions src/output/Control.hxx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
// SPDX-License-Identifier: GPL-2.0-or-later
// Copyright The Music Player Daemon Project

#ifndef MPD_OUTPUT_CONTROL_HXX
#define MPD_OUTPUT_CONTROL_HXX
#pragma once

#include "Source.hxx"
#include "mixer/Listener.hxx"
#include "pcm/AudioFormat.hxx"
#include "thread/Thread.hxx"
#include "thread/Mutex.hxx"
Expand All @@ -29,7 +29,7 @@ class AudioOutputClient;
/**
* Controller for an #AudioOutput and its output thread.
*/
class AudioOutputControl {
class AudioOutputControl final : MixerListener {
const std::unique_ptr<FilteredAudioOutput> output;

/**
Expand All @@ -39,6 +39,8 @@ class AudioOutputControl {
*/
const std::string name;

MixerListener *mixer_listener = nullptr;

/**
* The PlayerControl object which "owns" this output. This
* object is needed to signal command completion.
Expand Down Expand Up @@ -310,6 +312,11 @@ public:
return *client;
}

void LockSetMixerListener(MixerListener &_mixer_listener) noexcept {
const std::lock_guard lock{mutex};
mixer_listener = &_mixer_listener;
}

void SetClient(AudioOutputClient &_client) noexcept {
assert(source_state == SourceState::CLOSED);

Expand Down Expand Up @@ -655,6 +662,9 @@ private:
* The OutputThread.
*/
void Task() noexcept;
};

#endif
private:
/* virtual methods from class MixerListener */
void OnMixerVolumeChanged(Mixer &mixer, int volume) noexcept override;
void OnMixerChanged() noexcept override;
};
14 changes: 14 additions & 0 deletions src/output/Filtered.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -201,3 +201,17 @@ FilteredAudioOutput::IteratePause()
{
return output->Pause();
}

void
FilteredAudioOutput::OnMixerVolumeChanged(Mixer &_mixer, int volume) noexcept
{
if (mixer_listener != nullptr)
mixer_listener->OnMixerVolumeChanged(_mixer, volume);
}

void
FilteredAudioOutput::OnMixerChanged() noexcept
{
if (mixer_listener != nullptr)
mixer_listener->OnMixerChanged();
}
23 changes: 15 additions & 8 deletions src/output/Filtered.hxx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
// SPDX-License-Identifier: GPL-2.0-or-later
// Copyright The Music Player Daemon Project

#ifndef MPD_FILTERED_AUDIO_OUTPUT_HXX
#define MPD_FILTERED_AUDIO_OUTPUT_HXX
#pragma once

#include "mixer/Listener.hxx"
#include "pcm/AudioFormat.hxx"
#include "filter/Observer.hxx"

Expand All @@ -25,7 +25,7 @@ struct AudioOutputDefaults;
struct ReplayGainConfig;
struct Tag;

struct FilteredAudioOutput {
struct FilteredAudioOutput final : MixerListener {
const char *const plugin_name;

/**
Expand Down Expand Up @@ -53,6 +53,12 @@ public:
*/
Mixer *mixer = nullptr;

/**
* If not nullptr, then all #MixerListener calls are proxied
* to this object.
*/
MixerListener *mixer_listener = nullptr;

/**
* The configured audio format.
*/
Expand Down Expand Up @@ -127,7 +133,6 @@ public:
void Setup(EventLoop &event_loop,
const ReplayGainConfig &replay_gain_config,
const MixerPlugin *mixer_plugin,
MixerListener &mixer_listener,
const ConfigBlock &block,
const AudioOutputDefaults &defaults);

Expand Down Expand Up @@ -219,6 +224,11 @@ public:

void EndPause() noexcept{
}

private:
/* virtual methods from class MixerListener */
void OnMixerVolumeChanged(Mixer &mixer, int volume) noexcept override;
void OnMixerChanged() noexcept override;
};

/**
Expand All @@ -229,7 +239,4 @@ audio_output_new(EventLoop &event_loop, EventLoop &rt_event_loop,
const ReplayGainConfig &replay_gain_config,
const ConfigBlock &block,
const AudioOutputDefaults &defaults,
FilterFactory *filter_factory,
MixerListener &mixer_listener);

#endif
FilterFactory *filter_factory);
18 changes: 7 additions & 11 deletions src/output/Init.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,7 @@ audio_output_load_mixer(EventLoop &event_loop, FilteredAudioOutput &ao,
const ConfigBlock &block,
const MixerType mixer_type,
const MixerPlugin *plugin,
std::unique_ptr<PreparedFilter> &filter_chain,
MixerListener &listener)
std::unique_ptr<PreparedFilter> &filter_chain)
{
Mixer *mixer;

Expand All @@ -107,20 +106,20 @@ audio_output_load_mixer(EventLoop &event_loop, FilteredAudioOutput &ao,

case MixerType::NULL_:
return mixer_new(event_loop, null_mixer_plugin,
*ao.output, listener,
*ao.output, ao,
block);

case MixerType::HARDWARE:
if (plugin == nullptr)
return nullptr;

return mixer_new(event_loop, *plugin,
*ao.output, listener,
*ao.output, ao,
block);

case MixerType::SOFTWARE:
mixer = mixer_new(event_loop, software_mixer_plugin,
*ao.output, listener,
*ao.output, ao,
ConfigBlock());
assert(mixer != nullptr);

Expand Down Expand Up @@ -182,7 +181,6 @@ inline void
FilteredAudioOutput::Setup(EventLoop &event_loop,
const ReplayGainConfig &replay_gain_config,
const MixerPlugin *mixer_plugin,
MixerListener &mixer_listener,
const ConfigBlock &block,
const AudioOutputDefaults &defaults)
{
Expand Down Expand Up @@ -219,8 +217,7 @@ FilteredAudioOutput::Setup(EventLoop &event_loop,
mixer = audio_output_load_mixer(event_loop, *this, block,
mixer_type,
mixer_plugin,
prepared_filter,
mixer_listener);
prepared_filter);
} catch (...) {
FmtError(output_domain,
"Failed to initialize hardware mixer for {:?}: {}",
Expand Down Expand Up @@ -253,8 +250,7 @@ audio_output_new(EventLoop &normal_event_loop, EventLoop &rt_event_loop,
const ReplayGainConfig &replay_gain_config,
const ConfigBlock &block,
const AudioOutputDefaults &defaults,
FilterFactory *filter_factory,
MixerListener &mixer_listener)
FilterFactory *filter_factory)
{
const AudioOutputPlugin *plugin;

Expand Down Expand Up @@ -298,6 +294,6 @@ audio_output_new(EventLoop &normal_event_loop, EventLoop &rt_event_loop,
filter_factory);
f->Setup(event_loop, replay_gain_config,
plugin->mixer_plugin,
mixer_listener, block, defaults);
block, defaults);
return f;
}
12 changes: 5 additions & 7 deletions src/output/MultipleOutputs.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,13 @@ MultipleOutputs::~MultipleOutputs() noexcept
static std::unique_ptr<FilteredAudioOutput>
LoadOutput(EventLoop &event_loop, EventLoop &rt_event_loop,
const ReplayGainConfig &replay_gain_config,
MixerListener &mixer_listener,
const ConfigBlock &block,
const AudioOutputDefaults &defaults,
FilterFactory *filter_factory)
try {
return audio_output_new(event_loop, rt_event_loop, replay_gain_config, block,
defaults,
filter_factory,
mixer_listener);
filter_factory);
} catch (...) {
if (block.line > 0)
std::throw_with_nested(FmtRuntimeError("Failed to configure output in line {}",
Expand All @@ -57,14 +55,12 @@ try {
static std::unique_ptr<AudioOutputControl>
LoadOutputControl(EventLoop &event_loop, EventLoop &rt_event_loop,
const ReplayGainConfig &replay_gain_config,
MixerListener &mixer_listener,
AudioOutputClient &client, const ConfigBlock &block,
const AudioOutputDefaults &defaults,
FilterFactory *filter_factory)
{
auto output = LoadOutput(event_loop, rt_event_loop,
replay_gain_config,
mixer_listener,
block, defaults, filter_factory);
return std::make_unique<AudioOutputControl>(std::move(output),
client, block);
Expand All @@ -81,7 +77,6 @@ MultipleOutputs::Configure(EventLoop &event_loop, EventLoop &rt_event_loop,
config.WithEach(ConfigBlockOption::AUDIO_OUTPUT, [&, this](const auto &block){
auto output = LoadOutputControl(event_loop, rt_event_loop,
replay_gain_config,
mixer_listener,
client, block, defaults,
&filter_factory);
if (HasName(output->GetName()))
Expand All @@ -90,6 +85,7 @@ MultipleOutputs::Configure(EventLoop &event_loop, EventLoop &rt_event_loop,
output->GetName());

outputs.emplace_back(std::move(output));
outputs.back()->LockSetMixerListener(mixer_listener);
});

if (outputs.empty()) {
Expand All @@ -98,9 +94,9 @@ MultipleOutputs::Configure(EventLoop &event_loop, EventLoop &rt_event_loop,
outputs.emplace_back(LoadOutputControl(event_loop,
rt_event_loop,
replay_gain_config,
mixer_listener,
client, empty, defaults,
nullptr));
outputs.back()->LockSetMixerListener(mixer_listener);
}
}

Expand Down Expand Up @@ -169,6 +165,7 @@ MultipleOutputs::ReplaceDummy(std::size_t idx,

const std::lock_guard lock{mutex};
slot = std::move(src);
output.LockSetMixerListener(mixer_listener);
output.SetClient(client);
output.LockSetEnabled(enable);
output.SetReplayGainMode(replay_gain_mode);
Expand All @@ -187,6 +184,7 @@ MultipleOutputs::Add(std::unique_ptr<AudioOutputControl> &&src,
}

auto &output = *outputs.back();
output.LockSetMixerListener(mixer_listener);
output.SetClient(client);
output.LockSetEnabled(enable);
output.SetReplayGainMode(replay_gain_mode);
Expand Down
Loading