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() {
# ALSA version equal or later than 1.0.29 support this function.
use_alsa_monotonic_raw_tstamps = use_alsa && !is_cast_desktop_build
alsa_owns_volume =
system_owns_volume =
use_alsa && !enable_assistant && chromecast_branding != "google"
}
......@@ -86,7 +86,7 @@ buildflag_header("audio_features") {
flags = [
"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") {
"stream_mixer_input.h",
"stream_mixer_input_impl.cc",
"stream_mixer_input_impl.h",
"system_volume_control.h",
"video_decoder_null.cc",
"video_decoder_null.h",
"volume_control.cc",
"volume_map.cc",
"volume_map.h",
]
......
......@@ -34,7 +34,6 @@ source_set("alsa_cma_backend") {
"alsa_wrapper.h",
"mixer_output_stream_alsa.cc",
"mixer_output_stream_alsa.h",
"volume_control.cc",
]
libs = [ "asound" ]
......
......@@ -218,7 +218,7 @@ AlsaVolumeControl::AlsaVolumeControl(Delegate* delegate)
AlsaVolumeControl::~AlsaVolumeControl() = default;
float AlsaVolumeControl::VolumeThroughAlsa(float volume) {
float AlsaVolumeControl::GetRoundtripVolume(float volume) {
if (volume_range_max_ == volume_range_min_) {
return 0.0f;
}
......@@ -312,7 +312,7 @@ void AlsaVolumeControl::OnFileCanWriteWithoutBlocking(int fd) {
}
void AlsaVolumeControl::OnVolumeOrMuteChanged() {
delegate_->OnAlsaVolumeOrMuteChange(GetVolume(), IsMuted());
delegate_->OnSystemVolumeOrMuteChange(GetVolume(), IsMuted());
}
// static
......@@ -327,5 +327,11 @@ int AlsaVolumeControl::VolumeOrMuteChangeCallback(snd_mixer_elem_t* elem,
return 0;
}
// static
std::unique_ptr<SystemVolumeControl> SystemVolumeControl::Create(
Delegate* delegate) {
return std::make_unique<AlsaVolumeControl>(delegate);
}
} // namespace media
} // namespace chromecast
......@@ -11,47 +11,25 @@
#include "base/macros.h"
#include "base/message_loop/message_loop.h"
#include "chromecast/media/cma/backend/system_volume_control.h"
#include "media/audio/alsa/alsa_wrapper.h"
namespace chromecast {
namespace media {
// Handles setting the volume and mute state on the appropriate ALSA 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 AlsaVolumeControl : public base::MessageLoopForIO::Watcher {
// SystemVolumeControl implementation for ALSA.
class AlsaVolumeControl : public SystemVolumeControl,
public base::MessageLoopForIO::Watcher {
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);
~AlsaVolumeControl() override;
// Returns the value that you would get if you called GetVolume() after
// SetVolume(volume).
float VolumeThroughAlsa(float volume);
// Returns the current ALSA volume (0 <= volume <= 1).
float GetVolume();
// 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);
// SystemVolumeControl interface.
float GetRoundtripVolume(float volume) override;
float GetVolume() override;
void SetVolume(float level) override;
bool IsMuted() override;
void SetMuted(bool muted) override;
private:
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 @@
#include "base/values.h"
#include "chromecast/base/init_command_line_shlib.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/cast_audio_json.h"
#include "chromecast/media/cma/backend/post_processing_pipeline_parser.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"
namespace chromecast {
......@@ -71,7 +71,7 @@ std::string ContentTypeToDbFSKey(AudioContentType type) {
base::LazyInstance<VolumeMap>::Leaky g_volume_map = LAZY_INSTANCE_INITIALIZER;
class VolumeControlInternal : public AlsaVolumeControl::Delegate {
class VolumeControlInternal : public SystemVolumeControl::Delegate {
public:
VolumeControlInternal()
: thread_("VolumeControl"),
......@@ -152,9 +152,9 @@ class VolumeControlInternal : public AlsaVolumeControl::Delegate {
void SetVolume(AudioContentType type, float level) {
level = std::max(0.0f, std::min(level, 1.0f));
thread_.task_runner()->PostTask(
FROM_HERE,
base::Bind(&VolumeControlInternal::SetVolumeOnThread,
base::Unretained(this), type, level, false /* from_alsa */));
FROM_HERE, base::Bind(&VolumeControlInternal::SetVolumeOnThread,
base::Unretained(this), type, level,
false /* from_system */));
}
bool IsMuted(AudioContentType type) {
......@@ -164,13 +164,13 @@ class VolumeControlInternal : public AlsaVolumeControl::Delegate {
void SetMuted(AudioContentType type, bool muted) {
thread_.task_runner()->PostTask(
FROM_HERE,
base::Bind(&VolumeControlInternal::SetMutedOnThread,
base::Unretained(this), type, muted, false /* from_alsa */));
FROM_HERE, base::Bind(&VolumeControlInternal::SetMutedOnThread,
base::Unretained(this), type, muted,
false /* from_system */));
}
void SetOutputLimit(AudioContentType type, float limit) {
if (BUILDFLAG(ALSA_OWNS_VOLUME)) {
if (BUILDFLAG(SYSTEM_OWNS_VOLUME)) {
return;
}
limit = std::max(0.0f, std::min(limit, 1.0f));
......@@ -181,14 +181,14 @@ class VolumeControlInternal : public AlsaVolumeControl::Delegate {
private:
void InitializeOnThread() {
DCHECK(thread_.task_runner()->BelongsToCurrentThread());
alsa_volume_control_ = base::MakeUnique<AlsaVolumeControl>(this);
system_volume_control_ = SystemVolumeControl::Create(this);
double dbfs;
for (auto type : {AudioContentType::kMedia, AudioContentType::kAlarm,
AudioContentType::kCommunication}) {
CHECK(stored_values_.GetDouble(ContentTypeToDbFSKey(type), &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
// multiplier.
StreamMixer::Get()->SetVolume(type, 1.0f);
......@@ -200,27 +200,27 @@ class VolumeControlInternal : public AlsaVolumeControl::Delegate {
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
// from the ALSA mixer element(s).
volumes_[AudioContentType::kMedia] = alsa_volume_control_->GetVolume();
muted_[AudioContentType::kMedia] = alsa_volume_control_->IsMuted();
volumes_[AudioContentType::kMedia] = system_volume_control_->GetVolume();
muted_[AudioContentType::kMedia] = system_volume_control_->IsMuted();
} else {
// Otherwise, make sure the ALSA mixer element correctly reflects the
// current volume state.
alsa_volume_control_->SetVolume(volumes_[AudioContentType::kMedia]);
alsa_volume_control_->SetMuted(false);
system_volume_control_->SetVolume(volumes_[AudioContentType::kMedia]);
system_volume_control_->SetMuted(false);
}
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(!from_alsa || type == AudioContentType::kMedia);
DCHECK(!from_system || type == AudioContentType::kMedia);
{
base::AutoLock lock(volume_lock_);
if (from_alsa && alsa_volume_control_->VolumeThroughAlsa(
if (from_system && system_volume_control_->GetRoundtripVolume(
volumes_[AudioContentType::kMedia]) == level) {
return;
}
......@@ -231,12 +231,12 @@ class VolumeControlInternal : public AlsaVolumeControl::Delegate {
}
float dbfs = VolumeControl::VolumeToDbFS(level);
if (!BUILDFLAG(ALSA_OWNS_VOLUME)) {
if (!BUILDFLAG(SYSTEM_OWNS_VOLUME)) {
StreamMixer::Get()->SetVolume(type, DbFsToScale(dbfs));
}
if (!from_alsa && type == AudioContentType::kMedia) {
alsa_volume_control_->SetVolume(level);
if (!from_system && type == AudioContentType::kMedia) {
system_volume_control_->SetVolume(level);
}
{
......@@ -250,7 +250,7 @@ class VolumeControlInternal : public AlsaVolumeControl::Delegate {
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());
{
base::AutoLock lock(volume_lock_);
......@@ -260,12 +260,12 @@ class VolumeControlInternal : public AlsaVolumeControl::Delegate {
muted_[type] = muted;
}
if (!BUILDFLAG(ALSA_OWNS_VOLUME)) {
if (!BUILDFLAG(SYSTEM_OWNS_VOLUME)) {
StreamMixer::Get()->SetMuted(type, muted);
}
if (!from_alsa && type == AudioContentType::kMedia) {
alsa_volume_control_->SetMuted(muted);
if (!from_system && type == AudioContentType::kMedia) {
system_volume_control_->SetMuted(muted);
}
{
......@@ -276,12 +276,13 @@ class VolumeControlInternal : public AlsaVolumeControl::Delegate {
}
}
// AlsaVolumeControl::Delegate implementation:
void OnAlsaVolumeOrMuteChange(float new_volume, bool new_mute) override {
// SystemVolumeControl::Delegate implementation:
void OnSystemVolumeOrMuteChange(float new_volume, bool new_mute) override {
DCHECK(thread_.task_runner()->BelongsToCurrentThread());
SetVolumeOnThread(AudioContentType::kMedia, new_volume,
true /* from_alsa */);
SetMutedOnThread(AudioContentType::kMedia, new_mute, true /* from_alsa */);
true /* from_system */);
SetMutedOnThread(AudioContentType::kMedia, new_mute,
true /* from_system */);
}
base::FilePath storage_path_;
......@@ -297,7 +298,7 @@ class VolumeControlInternal : public AlsaVolumeControl::Delegate {
base::Thread thread_;
base::WaitableEvent initialize_complete_event_;
std::unique_ptr<AlsaVolumeControl> alsa_volume_control_;
std::unique_ptr<SystemVolumeControl> system_volume_control_;
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