mixer/Control: move some code to Lock*() methods
This commit is contained in:
parent
b0873fbc90
commit
29eb3e9ebc
@ -170,7 +170,7 @@ ReplayGainFilter::Update()
|
||||
_volume = 100;
|
||||
|
||||
try {
|
||||
mixer_set_volume(*mixer, _volume);
|
||||
mixer->LockSetVolume(_volume);
|
||||
|
||||
/* invoke the mixer's listener manually, just
|
||||
in case the mixer implementation didn't do
|
||||
|
@ -45,7 +45,7 @@ output_mixer_get_volume(const AudioOutputControl &ao) noexcept
|
||||
return -1;
|
||||
|
||||
try {
|
||||
return mixer_get_volume(*mixer);
|
||||
return mixer->LockGetVolume();
|
||||
} catch (...) {
|
||||
FmtError(mixer_domain,
|
||||
"Failed to read mixer for '{}': {}",
|
||||
@ -99,7 +99,7 @@ output_mixer_set_volume(AudioOutputControl &ao, unsigned volume)
|
||||
return SetVolumeResult::DISABLED;
|
||||
|
||||
try {
|
||||
mixer_set_volume(*mixer, volume);
|
||||
mixer->LockSetVolume(volume);
|
||||
return SetVolumeResult::OK;
|
||||
} catch (...) {
|
||||
FmtError(mixer_domain,
|
||||
@ -157,7 +157,7 @@ output_mixer_get_software_volume(const AudioOutputControl &ao) noexcept
|
||||
if (mixer == nullptr || !mixer->IsPlugin(software_mixer_plugin))
|
||||
return -1;
|
||||
|
||||
return mixer_get_volume(*mixer);
|
||||
return mixer->LockGetVolume();
|
||||
}
|
||||
|
||||
int
|
||||
@ -191,6 +191,6 @@ MultipleOutputs::SetSoftwareVolume(unsigned volume) noexcept
|
||||
if (mixer != nullptr &&
|
||||
(mixer->IsPlugin(software_mixer_plugin) ||
|
||||
mixer->IsPlugin(null_mixer_plugin)))
|
||||
mixer_set_volume(*mixer, volume);
|
||||
mixer->LockSetVolume(volume);
|
||||
}
|
||||
}
|
||||
|
@ -41,92 +41,8 @@ mixer_free(Mixer *mixer) noexcept
|
||||
assert(mixer != nullptr);
|
||||
|
||||
/* mixers with the "global" flag set might still be open at
|
||||
this point (see mixer_auto_close()) */
|
||||
mixer_close(*mixer);
|
||||
this point (see Mixer::LockAutoClose()) */
|
||||
mixer->LockClose();
|
||||
|
||||
delete mixer;
|
||||
}
|
||||
|
||||
void
|
||||
mixer_open(Mixer &mixer)
|
||||
{
|
||||
const std::scoped_lock<Mutex> protect(mixer.mutex);
|
||||
|
||||
if (mixer.open)
|
||||
return;
|
||||
|
||||
try {
|
||||
mixer.Open();
|
||||
mixer.open = true;
|
||||
mixer.failure = {};
|
||||
} catch (...) {
|
||||
mixer.failure = std::current_exception();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
mixer_close_internal(Mixer &mixer) noexcept
|
||||
{
|
||||
assert(mixer.open);
|
||||
|
||||
mixer.Close();
|
||||
mixer.open = false;
|
||||
mixer.failure = {};
|
||||
}
|
||||
|
||||
void
|
||||
mixer_close(Mixer &mixer) noexcept
|
||||
{
|
||||
const std::scoped_lock<Mutex> protect(mixer.mutex);
|
||||
|
||||
if (mixer.open)
|
||||
mixer_close_internal(mixer);
|
||||
}
|
||||
|
||||
void
|
||||
mixer_auto_close(Mixer &mixer) noexcept
|
||||
{
|
||||
if (!mixer.IsGlobal())
|
||||
mixer_close(mixer);
|
||||
}
|
||||
|
||||
int
|
||||
mixer_get_volume(Mixer &mixer)
|
||||
{
|
||||
int volume;
|
||||
|
||||
if (mixer.IsGlobal() && !mixer.failure)
|
||||
mixer_open(mixer);
|
||||
|
||||
const std::scoped_lock<Mutex> protect(mixer.mutex);
|
||||
|
||||
if (mixer.open) {
|
||||
try {
|
||||
volume = mixer.GetVolume();
|
||||
} catch (...) {
|
||||
mixer_close_internal(mixer);
|
||||
mixer.failure = std::current_exception();
|
||||
throw;
|
||||
}
|
||||
} else
|
||||
volume = -1;
|
||||
|
||||
return volume;
|
||||
}
|
||||
|
||||
void
|
||||
mixer_set_volume(Mixer &mixer, unsigned volume)
|
||||
{
|
||||
assert(volume <= 100);
|
||||
|
||||
if (mixer.IsGlobal() && !mixer.failure)
|
||||
mixer_open(mixer);
|
||||
|
||||
const std::scoped_lock<Mutex> protect(mixer.mutex);
|
||||
|
||||
if (mixer.open)
|
||||
mixer.SetVolume(volume);
|
||||
else if (mixer.failure)
|
||||
std::rethrow_exception(mixer.failure);
|
||||
}
|
||||
|
@ -44,32 +44,4 @@ mixer_new(EventLoop &event_loop, const MixerPlugin &plugin,
|
||||
void
|
||||
mixer_free(Mixer *mixer) noexcept;
|
||||
|
||||
/**
|
||||
* Throws std::runtime_error on error.
|
||||
*/
|
||||
void
|
||||
mixer_open(Mixer &mixer);
|
||||
|
||||
void
|
||||
mixer_close(Mixer &mixer) noexcept;
|
||||
|
||||
/**
|
||||
* Close the mixer unless the plugin's "global" flag is set. This is
|
||||
* called when the #AudioOutput is closed.
|
||||
*/
|
||||
void
|
||||
mixer_auto_close(Mixer &mixer) noexcept;
|
||||
|
||||
/**
|
||||
* Throws std::runtime_error on error.
|
||||
*/
|
||||
int
|
||||
mixer_get_volume(Mixer &mixer);
|
||||
|
||||
/**
|
||||
* Throws std::runtime_error on error.
|
||||
*/
|
||||
void
|
||||
mixer_set_volume(Mixer &mixer, unsigned volume);
|
||||
|
||||
#endif
|
||||
|
103
src/mixer/Mixer.cxx
Normal file
103
src/mixer/Mixer.cxx
Normal file
@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Copyright 2003-2022 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.
|
||||
*/
|
||||
|
||||
#include "Mixer.hxx"
|
||||
|
||||
#include <cassert>
|
||||
|
||||
void
|
||||
Mixer::LockOpen()
|
||||
{
|
||||
const std::scoped_lock lock{mutex};
|
||||
|
||||
if (open)
|
||||
return;
|
||||
|
||||
_Open();
|
||||
}
|
||||
|
||||
void
|
||||
Mixer::_Open()
|
||||
{
|
||||
assert(!open);
|
||||
|
||||
try {
|
||||
Open();
|
||||
open = true;
|
||||
failure = {};
|
||||
} catch (...) {
|
||||
failure = std::current_exception();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Mixer::LockClose() noexcept
|
||||
{
|
||||
const std::scoped_lock lock{mutex};
|
||||
|
||||
if (open)
|
||||
_Close();
|
||||
}
|
||||
|
||||
void
|
||||
Mixer::_Close() noexcept
|
||||
{
|
||||
assert(open);
|
||||
|
||||
Close();
|
||||
open = false;
|
||||
failure = {};
|
||||
}
|
||||
|
||||
int
|
||||
Mixer::LockGetVolume()
|
||||
{
|
||||
if (IsGlobal() && !failure)
|
||||
LockOpen();
|
||||
|
||||
const std::scoped_lock lock{mutex};
|
||||
|
||||
if (open) {
|
||||
try {
|
||||
return GetVolume();
|
||||
} catch (...) {
|
||||
_Close();
|
||||
failure = std::current_exception();
|
||||
throw;
|
||||
}
|
||||
} else
|
||||
return -1;
|
||||
}
|
||||
|
||||
void
|
||||
Mixer::LockSetVolume(unsigned volume)
|
||||
{
|
||||
assert(volume <= 100);
|
||||
|
||||
if (IsGlobal() && !failure)
|
||||
LockOpen();
|
||||
|
||||
const std::scoped_lock lock{mutex};
|
||||
|
||||
if (open)
|
||||
SetVolume(volume);
|
||||
else if (failure)
|
||||
std::rethrow_exception(failure);
|
||||
}
|
@ -17,12 +17,10 @@
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef MPD_MIXER_INTERNAL_HXX
|
||||
#define MPD_MIXER_INTERNAL_HXX
|
||||
#pragma once
|
||||
|
||||
#include "MixerPlugin.hxx"
|
||||
#include "thread/Mutex.hxx"
|
||||
#include "util/Compiler.h"
|
||||
|
||||
#include <exception>
|
||||
|
||||
@ -68,6 +66,37 @@ public:
|
||||
return plugin.global;
|
||||
}
|
||||
|
||||
/**
|
||||
* Throws on error.
|
||||
*/
|
||||
void LockOpen();
|
||||
|
||||
void LockClose() noexcept;
|
||||
|
||||
/**
|
||||
* Close the mixer unless the plugin's "global" flag is set.
|
||||
* This is called when the #AudioOutput is closed.
|
||||
*/
|
||||
void LockAutoClose() noexcept {
|
||||
if (!IsGlobal())
|
||||
LockClose();
|
||||
}
|
||||
|
||||
/**
|
||||
* Throws on error.
|
||||
*/
|
||||
int LockGetVolume();
|
||||
|
||||
/**
|
||||
* Throws on error.
|
||||
*/
|
||||
void LockSetVolume(unsigned volume);
|
||||
|
||||
private:
|
||||
void _Open();
|
||||
void _Close() noexcept;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Open mixer device
|
||||
*
|
||||
@ -107,5 +136,3 @@ public:
|
||||
*/
|
||||
virtual void SetVolume(unsigned volume) = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -4,6 +4,7 @@ subdir('plugins')
|
||||
|
||||
mixer_glue = static_library(
|
||||
'mixer_glue',
|
||||
'Mixer.cxx',
|
||||
'Control.cxx',
|
||||
'Type.cxx',
|
||||
'All.cxx',
|
||||
|
@ -22,7 +22,7 @@
|
||||
#include "Client.hxx"
|
||||
#include "Domain.hxx"
|
||||
#include "lib/fmt/ExceptionFormatter.hxx"
|
||||
#include "mixer/Control.hxx"
|
||||
#include "mixer/Mixer.hxx"
|
||||
#include "config/Block.hxx"
|
||||
#include "Log.hxx"
|
||||
|
||||
@ -276,7 +276,7 @@ AudioOutputControl::Open(std::unique_lock<Mutex> &lock,
|
||||
if (open2 && output->mixer != nullptr) {
|
||||
const ScopeUnlock unlock(mutex);
|
||||
try {
|
||||
mixer_open(*output->mixer);
|
||||
output->mixer->LockOpen();
|
||||
} catch (...) {
|
||||
FmtError(output_domain,
|
||||
"Failed to open mixer for '{}': {}",
|
||||
@ -296,7 +296,7 @@ AudioOutputControl::CloseWait(std::unique_lock<Mutex> &lock) noexcept
|
||||
return;
|
||||
|
||||
if (output->mixer != nullptr)
|
||||
mixer_auto_close(*output->mixer);
|
||||
output->mixer->LockAutoClose();
|
||||
|
||||
assert(!open || !fail_timer.IsDefined());
|
||||
|
||||
@ -359,8 +359,8 @@ AudioOutputControl::LockPauseAsync() noexcept
|
||||
if (output && output->mixer != nullptr && !output->SupportsPause())
|
||||
/* the device has no pause mode: close the mixer,
|
||||
unless its "global" flag is set (checked by
|
||||
mixer_auto_close()) */
|
||||
mixer_auto_close(*output->mixer);
|
||||
Mixer::LockAutoClose()) */
|
||||
output->mixer->LockAutoClose();
|
||||
|
||||
if (output)
|
||||
output->Interrupt();
|
||||
@ -418,8 +418,8 @@ AudioOutputControl::LockRelease() noexcept
|
||||
(!always_on || !output->SupportsPause()))
|
||||
/* the device has no pause mode: close the mixer,
|
||||
unless its "global" flag is set (checked by
|
||||
mixer_auto_close()) */
|
||||
mixer_auto_close(*output->mixer);
|
||||
Mixer::LockAutoClose()) */
|
||||
output->mixer->LockAutoClose();
|
||||
|
||||
std::unique_lock<Mutex> lock(mutex);
|
||||
|
||||
|
@ -27,7 +27,7 @@
|
||||
#include "OutputCommand.hxx"
|
||||
#include "MultipleOutputs.hxx"
|
||||
#include "Client.hxx"
|
||||
#include "mixer/Control.hxx"
|
||||
#include "mixer/Mixer.hxx"
|
||||
#include "mixer/Memento.hxx"
|
||||
#include "Idle.hxx"
|
||||
|
||||
@ -75,7 +75,7 @@ audio_output_disable_index(MultipleOutputs &outputs,
|
||||
|
||||
auto *mixer = ao.GetMixer();
|
||||
if (mixer != nullptr) {
|
||||
mixer_close(*mixer);
|
||||
mixer->LockClose();
|
||||
mixer_memento.InvalidateHardwareVolume();
|
||||
idle_add(IDLE_MIXER);
|
||||
}
|
||||
@ -102,7 +102,7 @@ audio_output_toggle_index(MultipleOutputs &outputs,
|
||||
if (!enabled) {
|
||||
auto *mixer = ao.GetMixer();
|
||||
if (mixer != nullptr) {
|
||||
mixer_close(*mixer);
|
||||
mixer->LockClose();
|
||||
mixer_memento.InvalidateHardwareVolume();
|
||||
idle_add(IDLE_MIXER);
|
||||
}
|
||||
|
@ -19,6 +19,7 @@
|
||||
|
||||
#include "NullMixerListener.hxx"
|
||||
#include "mixer/Control.hxx"
|
||||
#include "mixer/Mixer.hxx"
|
||||
#include "mixer/plugins/AlsaMixerPlugin.hxx"
|
||||
#include "filter/Registry.hxx"
|
||||
#include "event/Loop.hxx"
|
||||
@ -57,10 +58,7 @@ try {
|
||||
mixer_listener,
|
||||
ConfigBlock());
|
||||
|
||||
mixer_open(*mixer);
|
||||
|
||||
volume = mixer_get_volume(*mixer);
|
||||
mixer_close(*mixer);
|
||||
volume = mixer->LockGetVolume();
|
||||
mixer_free(mixer);
|
||||
|
||||
assert(volume >= -1 && volume <= 100);
|
||||
|
@ -42,12 +42,6 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
void
|
||||
mixer_set_volume([[maybe_unused]] Mixer &mixer,
|
||||
[[maybe_unused]] unsigned volume)
|
||||
{
|
||||
}
|
||||
|
||||
static std::unique_ptr<PreparedFilter>
|
||||
LoadFilter(const ConfigData &config, const char *name)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user