Commit d3e5ceb2 authored by Sergey Ulanov's avatar Sergey Ulanov Committed by Commit Bot

Move VolumeControl class out of ALSA directory

Moved VolumeControl from backend/alsa to backend directory. To remove
ALSA dependency added SystemVolumeControl interface that abstracts
functionaly implemented in AlsaVolumeControl.

Bug: 772488
Change-Id: I40575d873df00829b445dc8309ad0a61038009c8
Reviewed-on: https://chromium-review.googlesource.com/720076
Commit-Queue: Sergey Ulanov <sergeyu@chromium.org>
Reviewed-by: default avatarLuke Halliwell <halliwell@chromium.org>
Cr-Commit-Position: refs/heads/master@{#510014}
parent 7204375d
...@@ -12,7 +12,7 @@ declare_args() { ...@@ -12,7 +12,7 @@ declare_args() {
# ALSA version equal or later than 1.0.29 support this function. # ALSA version equal or later than 1.0.29 support this function.
use_alsa_monotonic_raw_tstamps = use_alsa && !is_cast_desktop_build use_alsa_monotonic_raw_tstamps = use_alsa && !is_cast_desktop_build
alsa_owns_volume = system_owns_volume =
use_alsa && !enable_assistant && chromecast_branding != "google" use_alsa && !enable_assistant && chromecast_branding != "google"
} }
...@@ -86,7 +86,7 @@ buildflag_header("audio_features") { ...@@ -86,7 +86,7 @@ buildflag_header("audio_features") {
flags = [ flags = [
"ALSA_MONOTONIC_RAW_TSTAMPS=$use_alsa_monotonic_raw_tstamps", "ALSA_MONOTONIC_RAW_TSTAMPS=$use_alsa_monotonic_raw_tstamps",
"ALSA_OWNS_VOLUME=$alsa_owns_volume", "SYSTEM_OWNS_VOLUME=$system_owns_volume",
] ]
} }
...@@ -114,8 +114,10 @@ source_set("audio") { ...@@ -114,8 +114,10 @@ source_set("audio") {
"stream_mixer_input.h", "stream_mixer_input.h",
"stream_mixer_input_impl.cc", "stream_mixer_input_impl.cc",
"stream_mixer_input_impl.h", "stream_mixer_input_impl.h",
"system_volume_control.h",
"video_decoder_null.cc", "video_decoder_null.cc",
"video_decoder_null.h", "video_decoder_null.h",
"volume_control.cc",
"volume_map.cc", "volume_map.cc",
"volume_map.h", "volume_map.h",
] ]
......
...@@ -34,7 +34,6 @@ source_set("alsa_cma_backend") { ...@@ -34,7 +34,6 @@ source_set("alsa_cma_backend") {
"alsa_wrapper.h", "alsa_wrapper.h",
"mixer_output_stream_alsa.cc", "mixer_output_stream_alsa.cc",
"mixer_output_stream_alsa.h", "mixer_output_stream_alsa.h",
"volume_control.cc",
] ]
libs = [ "asound" ] libs = [ "asound" ]
......
...@@ -218,7 +218,7 @@ AlsaVolumeControl::AlsaVolumeControl(Delegate* delegate) ...@@ -218,7 +218,7 @@ AlsaVolumeControl::AlsaVolumeControl(Delegate* delegate)
AlsaVolumeControl::~AlsaVolumeControl() = default; AlsaVolumeControl::~AlsaVolumeControl() = default;
float AlsaVolumeControl::VolumeThroughAlsa(float volume) { float AlsaVolumeControl::GetRoundtripVolume(float volume) {
if (volume_range_max_ == volume_range_min_) { if (volume_range_max_ == volume_range_min_) {
return 0.0f; return 0.0f;
} }
...@@ -312,7 +312,7 @@ void AlsaVolumeControl::OnFileCanWriteWithoutBlocking(int fd) { ...@@ -312,7 +312,7 @@ void AlsaVolumeControl::OnFileCanWriteWithoutBlocking(int fd) {
} }
void AlsaVolumeControl::OnVolumeOrMuteChanged() { void AlsaVolumeControl::OnVolumeOrMuteChanged() {
delegate_->OnAlsaVolumeOrMuteChange(GetVolume(), IsMuted()); delegate_->OnSystemVolumeOrMuteChange(GetVolume(), IsMuted());
} }
// static // static
...@@ -327,5 +327,11 @@ int AlsaVolumeControl::VolumeOrMuteChangeCallback(snd_mixer_elem_t* elem, ...@@ -327,5 +327,11 @@ int AlsaVolumeControl::VolumeOrMuteChangeCallback(snd_mixer_elem_t* elem,
return 0; return 0;
} }
// static
std::unique_ptr<SystemVolumeControl> SystemVolumeControl::Create(
Delegate* delegate) {
return std::make_unique<AlsaVolumeControl>(delegate);
}
} // namespace media } // namespace media
} // namespace chromecast } // namespace chromecast
...@@ -11,47 +11,25 @@ ...@@ -11,47 +11,25 @@
#include "base/macros.h" #include "base/macros.h"
#include "base/message_loop/message_loop.h" #include "base/message_loop/message_loop.h"
#include "chromecast/media/cma/backend/system_volume_control.h"
#include "media/audio/alsa/alsa_wrapper.h" #include "media/audio/alsa/alsa_wrapper.h"
namespace chromecast { namespace chromecast {
namespace media { namespace media {
// Handles setting the volume and mute state on the appropriate ALSA mixer // SystemVolumeControl implementation for ALSA.
// elements (based on command-line args); also detects changes to the mute state class AlsaVolumeControl : public SystemVolumeControl,
// or volume and informs a delegate. public base::MessageLoopForIO::Watcher {
// Must be created on an IO thread, and all methods must be called on that
// thread.
class AlsaVolumeControl : public base::MessageLoopForIO::Watcher {
public: public:
class Delegate {
public:
// Called whenever the ALSA volume or mute state have changed.
// Unfortunately it is not possible in all cases to differentiate between
// a volume change and a mute change, so the two events must be combined.
virtual void OnAlsaVolumeOrMuteChange(float new_volume, bool new_mute) = 0;
protected:
virtual ~Delegate() = default;
};
explicit AlsaVolumeControl(Delegate* delegate); explicit AlsaVolumeControl(Delegate* delegate);
~AlsaVolumeControl() override; ~AlsaVolumeControl() override;
// Returns the value that you would get if you called GetVolume() after // SystemVolumeControl interface.
// SetVolume(volume). float GetRoundtripVolume(float volume) override;
float VolumeThroughAlsa(float volume); float GetVolume() override;
void SetVolume(float level) override;
// Returns the current ALSA volume (0 <= volume <= 1). bool IsMuted() override;
float GetVolume(); void SetMuted(bool muted) override;
// Sets the ALSA volume to |level|; (0 <= level <= 1);
void SetVolume(float level);
// Returns |true| if ALSA is currently muted.
bool IsMuted();
// Sets the ALSA mute state to |muted|.
void SetMuted(bool muted);
private: private:
class ScopedAlsaMixer; class ScopedAlsaMixer;
......
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROMECAST_MEDIA_CMA_BACKEND_SYSTEM_VOLUME_CONTROL_H_
#define CHROMECAST_MEDIA_CMA_BACKEND_SYSTEM_VOLUME_CONTROL_H_
#include <memory>
#include "base/macros.h"
#include "base/message_loop/message_loop.h"
namespace chromecast {
namespace media {
// Handles setting the volume and mute state on the appropriate system mixer
// elements (based on command-line args); also detects changes to the mute state
// or volume and informs a delegate.
// Must be created on an IO thread, and all methods must be called on that
// thread.
class SystemVolumeControl {
public:
class Delegate {
public:
// Called whenever the system volume or mute state have changed.
// Unfortunately it is not possible in all cases to differentiate between
// a volume change and a mute change, so the two events must be combined.
virtual void OnSystemVolumeOrMuteChange(float new_volume,
bool new_mute) = 0;
protected:
virtual ~Delegate() = default;
};
static std::unique_ptr<SystemVolumeControl> Create(Delegate* delegate);
SystemVolumeControl() = default;
virtual ~SystemVolumeControl() = default;
// Returns the value that you would get if you called GetVolume() after
// SetVolume(volume).
virtual float GetRoundtripVolume(float volume) = 0;
// Returns the current system volume (0 <= volume <= 1).
virtual float GetVolume() = 0;
// Sets the system volume to |level| (0 <= level <= 1).
virtual void SetVolume(float level) = 0;
// Returns |true| if system is currently muted.
virtual bool IsMuted() = 0;
// Sets the system mute state to |muted|.
virtual void SetMuted(bool muted) = 0;
private:
DISALLOW_COPY_AND_ASSIGN(SystemVolumeControl);
};
} // namespace media
} // namespace chromecast
#endif // CHROMECAST_MEDIA_CMA_BACKEND_SYSTEM_VOLUME_CONTROL_H_
...@@ -28,11 +28,11 @@ ...@@ -28,11 +28,11 @@
#include "base/values.h" #include "base/values.h"
#include "chromecast/base/init_command_line_shlib.h" #include "chromecast/base/init_command_line_shlib.h"
#include "chromecast/base/serializers.h" #include "chromecast/base/serializers.h"
#include "chromecast/media/cma/backend/alsa/alsa_volume_control.h"
#include "chromecast/media/cma/backend/audio_features.h" #include "chromecast/media/cma/backend/audio_features.h"
#include "chromecast/media/cma/backend/cast_audio_json.h" #include "chromecast/media/cma/backend/cast_audio_json.h"
#include "chromecast/media/cma/backend/post_processing_pipeline_parser.h" #include "chromecast/media/cma/backend/post_processing_pipeline_parser.h"
#include "chromecast/media/cma/backend/stream_mixer.h" #include "chromecast/media/cma/backend/stream_mixer.h"
#include "chromecast/media/cma/backend/system_volume_control.h"
#include "chromecast/media/cma/backend/volume_map.h" #include "chromecast/media/cma/backend/volume_map.h"
namespace chromecast { namespace chromecast {
...@@ -71,7 +71,7 @@ std::string ContentTypeToDbFSKey(AudioContentType type) { ...@@ -71,7 +71,7 @@ std::string ContentTypeToDbFSKey(AudioContentType type) {
base::LazyInstance<VolumeMap>::Leaky g_volume_map = LAZY_INSTANCE_INITIALIZER; base::LazyInstance<VolumeMap>::Leaky g_volume_map = LAZY_INSTANCE_INITIALIZER;
class VolumeControlInternal : public AlsaVolumeControl::Delegate { class VolumeControlInternal : public SystemVolumeControl::Delegate {
public: public:
VolumeControlInternal() VolumeControlInternal()
: thread_("VolumeControl"), : thread_("VolumeControl"),
...@@ -152,9 +152,9 @@ class VolumeControlInternal : public AlsaVolumeControl::Delegate { ...@@ -152,9 +152,9 @@ class VolumeControlInternal : public AlsaVolumeControl::Delegate {
void SetVolume(AudioContentType type, float level) { void SetVolume(AudioContentType type, float level) {
level = std::max(0.0f, std::min(level, 1.0f)); level = std::max(0.0f, std::min(level, 1.0f));
thread_.task_runner()->PostTask( thread_.task_runner()->PostTask(
FROM_HERE, FROM_HERE, base::Bind(&VolumeControlInternal::SetVolumeOnThread,
base::Bind(&VolumeControlInternal::SetVolumeOnThread, base::Unretained(this), type, level,
base::Unretained(this), type, level, false /* from_alsa */)); false /* from_system */));
} }
bool IsMuted(AudioContentType type) { bool IsMuted(AudioContentType type) {
...@@ -164,13 +164,13 @@ class VolumeControlInternal : public AlsaVolumeControl::Delegate { ...@@ -164,13 +164,13 @@ class VolumeControlInternal : public AlsaVolumeControl::Delegate {
void SetMuted(AudioContentType type, bool muted) { void SetMuted(AudioContentType type, bool muted) {
thread_.task_runner()->PostTask( thread_.task_runner()->PostTask(
FROM_HERE, FROM_HERE, base::Bind(&VolumeControlInternal::SetMutedOnThread,
base::Bind(&VolumeControlInternal::SetMutedOnThread, base::Unretained(this), type, muted,
base::Unretained(this), type, muted, false /* from_alsa */)); false /* from_system */));
} }
void SetOutputLimit(AudioContentType type, float limit) { void SetOutputLimit(AudioContentType type, float limit) {
if (BUILDFLAG(ALSA_OWNS_VOLUME)) { if (BUILDFLAG(SYSTEM_OWNS_VOLUME)) {
return; return;
} }
limit = std::max(0.0f, std::min(limit, 1.0f)); limit = std::max(0.0f, std::min(limit, 1.0f));
...@@ -181,14 +181,14 @@ class VolumeControlInternal : public AlsaVolumeControl::Delegate { ...@@ -181,14 +181,14 @@ class VolumeControlInternal : public AlsaVolumeControl::Delegate {
private: private:
void InitializeOnThread() { void InitializeOnThread() {
DCHECK(thread_.task_runner()->BelongsToCurrentThread()); DCHECK(thread_.task_runner()->BelongsToCurrentThread());
alsa_volume_control_ = base::MakeUnique<AlsaVolumeControl>(this); system_volume_control_ = SystemVolumeControl::Create(this);
double dbfs; double dbfs;
for (auto type : {AudioContentType::kMedia, AudioContentType::kAlarm, for (auto type : {AudioContentType::kMedia, AudioContentType::kAlarm,
AudioContentType::kCommunication}) { AudioContentType::kCommunication}) {
CHECK(stored_values_.GetDouble(ContentTypeToDbFSKey(type), &dbfs)); CHECK(stored_values_.GetDouble(ContentTypeToDbFSKey(type), &dbfs));
volumes_[type] = VolumeControl::DbFSToVolume(dbfs); volumes_[type] = VolumeControl::DbFSToVolume(dbfs);
if (BUILDFLAG(ALSA_OWNS_VOLUME)) { if (BUILDFLAG(SYSTEM_OWNS_VOLUME)) {
// If ALSA owns volume, our internal mixer should not apply any scaling // If ALSA owns volume, our internal mixer should not apply any scaling
// multiplier. // multiplier.
StreamMixer::Get()->SetVolume(type, 1.0f); StreamMixer::Get()->SetVolume(type, 1.0f);
...@@ -200,28 +200,28 @@ class VolumeControlInternal : public AlsaVolumeControl::Delegate { ...@@ -200,28 +200,28 @@ class VolumeControlInternal : public AlsaVolumeControl::Delegate {
muted_[type] = false; muted_[type] = false;
} }
if (BUILDFLAG(ALSA_OWNS_VOLUME)) { if (BUILDFLAG(SYSTEM_OWNS_VOLUME)) {
// If ALSA owns the volume, then read the current volume and mute state // If ALSA owns the volume, then read the current volume and mute state
// from the ALSA mixer element(s). // from the ALSA mixer element(s).
volumes_[AudioContentType::kMedia] = alsa_volume_control_->GetVolume(); volumes_[AudioContentType::kMedia] = system_volume_control_->GetVolume();
muted_[AudioContentType::kMedia] = alsa_volume_control_->IsMuted(); muted_[AudioContentType::kMedia] = system_volume_control_->IsMuted();
} else { } else {
// Otherwise, make sure the ALSA mixer element correctly reflects the // Otherwise, make sure the ALSA mixer element correctly reflects the
// current volume state. // current volume state.
alsa_volume_control_->SetVolume(volumes_[AudioContentType::kMedia]); system_volume_control_->SetVolume(volumes_[AudioContentType::kMedia]);
alsa_volume_control_->SetMuted(false); system_volume_control_->SetMuted(false);
} }
initialize_complete_event_.Signal(); initialize_complete_event_.Signal();
} }
void SetVolumeOnThread(AudioContentType type, float level, bool from_alsa) { void SetVolumeOnThread(AudioContentType type, float level, bool from_system) {
DCHECK(thread_.task_runner()->BelongsToCurrentThread()); DCHECK(thread_.task_runner()->BelongsToCurrentThread());
DCHECK(!from_alsa || type == AudioContentType::kMedia); DCHECK(!from_system || type == AudioContentType::kMedia);
{ {
base::AutoLock lock(volume_lock_); base::AutoLock lock(volume_lock_);
if (from_alsa && alsa_volume_control_->VolumeThroughAlsa( if (from_system && system_volume_control_->GetRoundtripVolume(
volumes_[AudioContentType::kMedia]) == level) { volumes_[AudioContentType::kMedia]) == level) {
return; return;
} }
if (level == volumes_[type]) { if (level == volumes_[type]) {
...@@ -231,12 +231,12 @@ class VolumeControlInternal : public AlsaVolumeControl::Delegate { ...@@ -231,12 +231,12 @@ class VolumeControlInternal : public AlsaVolumeControl::Delegate {
} }
float dbfs = VolumeControl::VolumeToDbFS(level); float dbfs = VolumeControl::VolumeToDbFS(level);
if (!BUILDFLAG(ALSA_OWNS_VOLUME)) { if (!BUILDFLAG(SYSTEM_OWNS_VOLUME)) {
StreamMixer::Get()->SetVolume(type, DbFsToScale(dbfs)); StreamMixer::Get()->SetVolume(type, DbFsToScale(dbfs));
} }
if (!from_alsa && type == AudioContentType::kMedia) { if (!from_system && type == AudioContentType::kMedia) {
alsa_volume_control_->SetVolume(level); system_volume_control_->SetVolume(level);
} }
{ {
...@@ -250,7 +250,7 @@ class VolumeControlInternal : public AlsaVolumeControl::Delegate { ...@@ -250,7 +250,7 @@ class VolumeControlInternal : public AlsaVolumeControl::Delegate {
SerializeJsonToFile(storage_path_, stored_values_); SerializeJsonToFile(storage_path_, stored_values_);
} }
void SetMutedOnThread(AudioContentType type, bool muted, bool from_alsa) { void SetMutedOnThread(AudioContentType type, bool muted, bool from_system) {
DCHECK(thread_.task_runner()->BelongsToCurrentThread()); DCHECK(thread_.task_runner()->BelongsToCurrentThread());
{ {
base::AutoLock lock(volume_lock_); base::AutoLock lock(volume_lock_);
...@@ -260,12 +260,12 @@ class VolumeControlInternal : public AlsaVolumeControl::Delegate { ...@@ -260,12 +260,12 @@ class VolumeControlInternal : public AlsaVolumeControl::Delegate {
muted_[type] = muted; muted_[type] = muted;
} }
if (!BUILDFLAG(ALSA_OWNS_VOLUME)) { if (!BUILDFLAG(SYSTEM_OWNS_VOLUME)) {
StreamMixer::Get()->SetMuted(type, muted); StreamMixer::Get()->SetMuted(type, muted);
} }
if (!from_alsa && type == AudioContentType::kMedia) { if (!from_system && type == AudioContentType::kMedia) {
alsa_volume_control_->SetMuted(muted); system_volume_control_->SetMuted(muted);
} }
{ {
...@@ -276,12 +276,13 @@ class VolumeControlInternal : public AlsaVolumeControl::Delegate { ...@@ -276,12 +276,13 @@ class VolumeControlInternal : public AlsaVolumeControl::Delegate {
} }
} }
// AlsaVolumeControl::Delegate implementation: // SystemVolumeControl::Delegate implementation:
void OnAlsaVolumeOrMuteChange(float new_volume, bool new_mute) override { void OnSystemVolumeOrMuteChange(float new_volume, bool new_mute) override {
DCHECK(thread_.task_runner()->BelongsToCurrentThread()); DCHECK(thread_.task_runner()->BelongsToCurrentThread());
SetVolumeOnThread(AudioContentType::kMedia, new_volume, SetVolumeOnThread(AudioContentType::kMedia, new_volume,
true /* from_alsa */); true /* from_system */);
SetMutedOnThread(AudioContentType::kMedia, new_mute, true /* from_alsa */); SetMutedOnThread(AudioContentType::kMedia, new_mute,
true /* from_system */);
} }
base::FilePath storage_path_; base::FilePath storage_path_;
...@@ -297,7 +298,7 @@ class VolumeControlInternal : public AlsaVolumeControl::Delegate { ...@@ -297,7 +298,7 @@ class VolumeControlInternal : public AlsaVolumeControl::Delegate {
base::Thread thread_; base::Thread thread_;
base::WaitableEvent initialize_complete_event_; base::WaitableEvent initialize_complete_event_;
std::unique_ptr<AlsaVolumeControl> alsa_volume_control_; std::unique_ptr<SystemVolumeControl> system_volume_control_;
DISALLOW_COPY_AND_ASSIGN(VolumeControlInternal); DISALLOW_COPY_AND_ASSIGN(VolumeControlInternal);
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment