camera_effects: Host background blur effect
CameraEffectsController hosts the camera background blur effect, exposing it via the VC bubble. Bug: b/259585295 Change-Id: Ife30062e8482f094899a929e5506766a09455ba4 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4119258 Commit-Queue: Roger Tinkoff <rtinkoff@google.com> Reviewed-by: Alex Newcomer <newcomer@chromium.org> Cr-Commit-Position: refs/heads/main@{#1088880}
This commit is contained in:

committed by
Chromium LUCI CQ

parent
5d243e2d01
commit
473ee66968
ash
ash_strings.grd
ash_strings_grd
IDS_ASH_VIDEO_CONFERENCE_BUBBLE_BACKGROUND_BLUR_HEAVY.png.sha1IDS_ASH_VIDEO_CONFERENCE_BUBBLE_BACKGROUND_BLUR_LIGHT.png.sha1IDS_ASH_VIDEO_CONFERENCE_BUBBLE_BACKGROUND_BLUR_LOWEST.png.sha1IDS_ASH_VIDEO_CONFERENCE_BUBBLE_BACKGROUND_BLUR_MAXIMUM.png.sha1IDS_ASH_VIDEO_CONFERENCE_BUBBLE_BACKGROUND_BLUR_MEDIUM.png.sha1IDS_ASH_VIDEO_CONFERENCE_BUBBLE_BACKGROUND_BLUR_NAME.png.sha1IDS_ASH_VIDEO_CONFERENCE_BUBBLE_BACKGROUND_BLUR_OFF.png.sha1
system
camera
video_conference
@ -1447,13 +1447,34 @@ Style notes:
|
||||
Scanning
|
||||
</message>
|
||||
|
||||
<!-- Video Conference tray-->
|
||||
<!-- Video Conference tray/bubble -->
|
||||
<message name="IDS_ASH_VIDEO_CONFERENCE_TOGGLE_BUBBLE_BUTTON_TOOLTIP" desc="The tooltip for the toggle bubble button in the video conference tray.">
|
||||
Camera and audio controls
|
||||
</message>
|
||||
<message name="IDS_ASH_VIDEO_CONFERENCE_RETURN_TO_APP_SUMMARY_TEXT" desc="The summary text in the return to app panel of the video conference panel, specifying how many video conferencing apps are in used.">
|
||||
Used by <ph name="APP_COUNT">$1<ex>2</ex></ph> apps
|
||||
</message>
|
||||
<message name="IDS_ASH_VIDEO_CONFERENCE_BUBBLE_BACKGROUND_BLUR_NAME" desc="Text for name of the background blur effect in the VC bubble.">
|
||||
Background Blur
|
||||
</message>
|
||||
<message name="IDS_ASH_VIDEO_CONFERENCE_BUBBLE_BACKGROUND_BLUR_OFF" desc="Text for background blur 'off' setting, in the VC bubble.">
|
||||
Off
|
||||
</message>
|
||||
<message name="IDS_ASH_VIDEO_CONFERENCE_BUBBLE_BACKGROUND_BLUR_LOWEST" desc="Text for background blur 'lowest' setting, in the VC bubble.">
|
||||
Lowest
|
||||
</message>
|
||||
<message name="IDS_ASH_VIDEO_CONFERENCE_BUBBLE_BACKGROUND_BLUR_LIGHT" desc="Text for background blur 'light' setting, in the VC bubble.">
|
||||
Light
|
||||
</message>
|
||||
<message name="IDS_ASH_VIDEO_CONFERENCE_BUBBLE_BACKGROUND_BLUR_MEDIUM" desc="Text for background blur 'medium' setting, in the VC bubble.">
|
||||
Medium
|
||||
</message>
|
||||
<message name="IDS_ASH_VIDEO_CONFERENCE_BUBBLE_BACKGROUND_BLUR_HEAVY" desc="Text for background blur 'heavy' setting, in the VC bubble.">
|
||||
Heavy
|
||||
</message>
|
||||
<message name="IDS_ASH_VIDEO_CONFERENCE_BUBBLE_BACKGROUND_BLUR_MAXIMUM" desc="Text for background blur 'maximum' setting, in the VC bubble.">
|
||||
Maximum
|
||||
</message>
|
||||
|
||||
<!-- Phone Hub tray-->
|
||||
<message name="IDS_ASH_PHONE_HUB_TRAY_ACCESSIBLE_NAME" desc="The accessible name of the Phone Hub tray bubble for screen readers.">
|
||||
|
@ -0,0 +1 @@
|
||||
6244582b0cd0ef43796e6ff6e74058f7d6e90517
|
@ -0,0 +1 @@
|
||||
6244582b0cd0ef43796e6ff6e74058f7d6e90517
|
@ -0,0 +1 @@
|
||||
c79c38b0c43dc23f280615a1baa9ab6b0a1159fe
|
@ -0,0 +1 @@
|
||||
6244582b0cd0ef43796e6ff6e74058f7d6e90517
|
@ -0,0 +1 @@
|
||||
6244582b0cd0ef43796e6ff6e74058f7d6e90517
|
@ -0,0 +1 @@
|
||||
6244582b0cd0ef43796e6ff6e74058f7d6e90517
|
@ -0,0 +1 @@
|
||||
6244582b0cd0ef43796e6ff6e74058f7d6e90517
|
@ -5,23 +5,106 @@
|
||||
#include "ash/system/camera/camera_effects_controller.h"
|
||||
|
||||
#include "ash/constants/ash_pref_names.h"
|
||||
#include "ash/resources/vector_icons/vector_icons.h"
|
||||
#include "ash/session/session_controller_impl.h"
|
||||
#include "ash/shell.h"
|
||||
#include "ash/strings/grit/ash_strings.h"
|
||||
#include "ash/system/video_conference/effects/video_conference_tray_effects_manager.h"
|
||||
#include "ash/system/video_conference/effects/video_conference_tray_effects_manager_types.h"
|
||||
#include "ash/system/video_conference/video_conference_tray_controller.h"
|
||||
#include "base/check_is_test.h"
|
||||
#include "base/notreached.h"
|
||||
#include "base/task/bind_post_task.h"
|
||||
#include "base/task/single_thread_task_runner.h"
|
||||
#include "components/prefs/pref_change_registrar.h"
|
||||
#include "components/prefs/pref_registry_simple.h"
|
||||
#include "components/prefs/pref_service.h"
|
||||
#include "media/capture/video/chromeos/camera_hal_dispatcher_impl.h"
|
||||
#include "third_party/abseil-cpp/absl/types/optional.h"
|
||||
#include "ui/base/l10n/l10n_util.h"
|
||||
|
||||
namespace ash {
|
||||
|
||||
namespace {
|
||||
|
||||
// The value stored in pref to indicate that background blur is disabled.
|
||||
constexpr int kBackgroundBlurLevelForDisabling = -1;
|
||||
// A `std::pair` representation of the background blur state that
|
||||
// `CameraHalDispatcherImpl` expects:
|
||||
// - `BlurLevel` that specifies how much blur to apply
|
||||
// - `bool` that's 'true' if background blur is enabled, false otherwise
|
||||
using CameraHalBackgroundBlurState = std::pair<cros::mojom::BlurLevel, bool>;
|
||||
|
||||
// Returns 'true' if `pref_value` is an allowable value of
|
||||
// `CameraEffectsController::BackgroundBlurEffectState`, 'false' otherwise.
|
||||
bool IsValidBackgroundBlurState(int pref_value) {
|
||||
switch (pref_value) {
|
||||
case CameraEffectsController::BackgroundBlurEffectState::kOff:
|
||||
case CameraEffectsController::BackgroundBlurEffectState::kLowest:
|
||||
case CameraEffectsController::BackgroundBlurEffectState::kLight:
|
||||
case CameraEffectsController::BackgroundBlurEffectState::kMedium:
|
||||
case CameraEffectsController::BackgroundBlurEffectState::kHeavy:
|
||||
case CameraEffectsController::BackgroundBlurEffectState::kMaximum:
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Maps `effect_state` (assumed to be a value read out of
|
||||
// `prefs::kBackgroundBlur`) to a `CameraHalBackgroundBlurState` (that
|
||||
// `CameraHalDispatcherImpl` expects).
|
||||
CameraHalBackgroundBlurState MapBackgroundBlurEffectStateToCameraHalState(
|
||||
int effect_state) {
|
||||
DCHECK(IsValidBackgroundBlurState(effect_state));
|
||||
|
||||
switch (effect_state) {
|
||||
// For state `kOff`, the `bool` is 'false' because background blur is
|
||||
// disabled, `BlurLevel` is set to `kLowest` but its value doesn't matter.
|
||||
case CameraEffectsController::BackgroundBlurEffectState::kOff:
|
||||
return std::make_pair(cros::mojom::BlurLevel::kLowest, false);
|
||||
|
||||
// For states other than `kOff`, background blur is enabled so the `bool`
|
||||
// is set to 'true' and `effect_state` is mapped to a `BlurLevel`.
|
||||
case CameraEffectsController::BackgroundBlurEffectState::kLowest:
|
||||
return std::make_pair(cros::mojom::BlurLevel::kLowest, true);
|
||||
case CameraEffectsController::BackgroundBlurEffectState::kLight:
|
||||
return std::make_pair(cros::mojom::BlurLevel::kLight, true);
|
||||
case CameraEffectsController::BackgroundBlurEffectState::kMedium:
|
||||
return std::make_pair(cros::mojom::BlurLevel::kMedium, true);
|
||||
case CameraEffectsController::BackgroundBlurEffectState::kHeavy:
|
||||
return std::make_pair(cros::mojom::BlurLevel::kHeavy, true);
|
||||
case CameraEffectsController::BackgroundBlurEffectState::kMaximum:
|
||||
return std::make_pair(cros::mojom::BlurLevel::kMaximum, true);
|
||||
}
|
||||
|
||||
NOTREACHED();
|
||||
return std::make_pair(cros::mojom::BlurLevel::kLowest, false);
|
||||
}
|
||||
|
||||
// Maps the `CameraHalDispatcherImpl`-ready background blur state
|
||||
// `level`/`enabled` to `CameraEffectsController::BackgroundBlurEffectState`,
|
||||
// which is what's written to `prefs::kBackgroundBlur`.
|
||||
CameraEffectsController::BackgroundBlurEffectState
|
||||
MapBackgroundBlurCameraHalStateToEffectState(cros::mojom::BlurLevel level,
|
||||
bool enabled) {
|
||||
if (!enabled) {
|
||||
return CameraEffectsController::BackgroundBlurEffectState::kOff;
|
||||
}
|
||||
|
||||
switch (level) {
|
||||
case cros::mojom::BlurLevel::kLowest:
|
||||
return CameraEffectsController::BackgroundBlurEffectState::kLowest;
|
||||
case cros::mojom::BlurLevel::kLight:
|
||||
return CameraEffectsController::BackgroundBlurEffectState::kLight;
|
||||
case cros::mojom::BlurLevel::kMedium:
|
||||
return CameraEffectsController::BackgroundBlurEffectState::kMedium;
|
||||
case cros::mojom::BlurLevel::kHeavy:
|
||||
return CameraEffectsController::BackgroundBlurEffectState::kHeavy;
|
||||
case cros::mojom::BlurLevel::kMaximum:
|
||||
return CameraEffectsController::BackgroundBlurEffectState::kMaximum;
|
||||
}
|
||||
|
||||
NOTREACHED();
|
||||
return CameraEffectsController::BackgroundBlurEffectState::kLowest;
|
||||
}
|
||||
|
||||
// Gets blur level from chrome flag.
|
||||
cros::mojom::BlurLevel GetBlurLevelFromFlag() {
|
||||
@ -83,7 +166,15 @@ CameraEffectsController::CameraEffectsController() {
|
||||
weak_factory_.GetWeakPtr())));
|
||||
}
|
||||
|
||||
CameraEffectsController::~CameraEffectsController() = default;
|
||||
CameraEffectsController::~CameraEffectsController() {
|
||||
VideoConferenceTrayEffectsManager& effects_manager =
|
||||
VideoConferenceTrayController::Get()->effects_manager();
|
||||
if (effects_manager.IsDelegateRegistered(this)) {
|
||||
// The `VcEffectsDelegate` was registered, so must therefore be
|
||||
// unregistered.
|
||||
effects_manager.UnregisterDelegate(this);
|
||||
}
|
||||
}
|
||||
|
||||
bool CameraEffectsController::IsCameraEffectsSupported(
|
||||
cros::mojom::CameraEffect effect) {
|
||||
@ -118,15 +209,16 @@ void CameraEffectsController::RemoveObserver(Observer* observer) {
|
||||
// static
|
||||
void CameraEffectsController::RegisterProfilePrefs(
|
||||
PrefRegistrySimple* registry) {
|
||||
if (!IsCameraEffectsSupported())
|
||||
if (!IsCameraEffectsSupported()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// We have to register all camera effects prefs; because we need use them to
|
||||
// construct the cros::mojom::EffectsConfigPtr.
|
||||
registry->RegisterIntegerPref(prefs::kBackgroundBlur,
|
||||
GetInitialCameraEffects()->blur_enabled
|
||||
? static_cast<int>(GetBlurLevelFromFlag())
|
||||
: kBackgroundBlurLevelForDisabling);
|
||||
: BackgroundBlurEffectState::kOff);
|
||||
|
||||
registry->RegisterBooleanPref(prefs::kBackgroundReplace,
|
||||
GetInitialCameraEffects()->replace_enabled);
|
||||
@ -137,8 +229,10 @@ void CameraEffectsController::RegisterProfilePrefs(
|
||||
|
||||
void CameraEffectsController::OnActiveUserPrefServiceChanged(
|
||||
PrefService* pref_service) {
|
||||
if (pref_change_registrar_ && pref_service == pref_change_registrar_->prefs())
|
||||
if (pref_change_registrar_ &&
|
||||
pref_service == pref_change_registrar_->prefs()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Initial login and user switching in multi profiles.
|
||||
pref_change_registrar_ = std::make_unique<PrefChangeRegistrar>();
|
||||
@ -167,6 +261,50 @@ void CameraEffectsController::OnActiveUserPrefServiceChanged(
|
||||
// If the camera has started, it won't get the previous setting so call it
|
||||
// here too. If the camera service isn't ready it this call will be ignored.
|
||||
SetCameraEffects(GetEffectsConfigFromPref());
|
||||
|
||||
// If any effects have controls the user can access, this will create the
|
||||
// effects UI and register `CameraEffectsController`'s `VcEffectsDelegate`
|
||||
// interface.
|
||||
InitializeEffectControls();
|
||||
}
|
||||
|
||||
int CameraEffectsController::GetEffectState(int effect_id) {
|
||||
switch (effect_id) {
|
||||
case static_cast<int>(cros::mojom::CameraEffect::kBackgroundBlur):
|
||||
DCHECK(pref_change_registrar_ && pref_change_registrar_->prefs());
|
||||
|
||||
int pref_value =
|
||||
pref_change_registrar_->prefs()->GetInteger(prefs::kBackgroundBlur);
|
||||
if (!IsValidBackgroundBlurState(pref_value)) {
|
||||
LOG(ERROR)
|
||||
<< __FUNCTION__ << " value " << pref_value
|
||||
<< " is NOT a valid background blur effect state, returning kOff";
|
||||
return static_cast<int>(BackgroundBlurEffectState::kOff);
|
||||
}
|
||||
return pref_value;
|
||||
}
|
||||
|
||||
return VcEffectState::kUnusedId;
|
||||
}
|
||||
|
||||
void CameraEffectsController::OnEffectControlActivated(int effect_id,
|
||||
int value) {
|
||||
switch (effect_id) {
|
||||
case static_cast<int>(cros::mojom::CameraEffect::kBackgroundBlur):
|
||||
DCHECK(pref_change_registrar_ && pref_change_registrar_->prefs());
|
||||
if (!IsValidBackgroundBlurState(value)) {
|
||||
LOG(ERROR) << __FUNCTION__ << " value " << value
|
||||
<< " is not a valid background blur effect state";
|
||||
pref_change_registrar_->prefs()->SetInteger(
|
||||
prefs::kBackgroundBlur,
|
||||
static_cast<int>(BackgroundBlurEffectState::kOff));
|
||||
return;
|
||||
}
|
||||
|
||||
pref_change_registrar_->prefs()->SetInteger(prefs::kBackgroundBlur,
|
||||
value);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void CameraEffectsController::OnCameraEffectsPrefChanged(
|
||||
@ -264,16 +402,21 @@ void CameraEffectsController::OnNewCameraEffectsSet(
|
||||
cros::mojom::EffectsConfigPtr
|
||||
CameraEffectsController::GetEffectsConfigFromPref() {
|
||||
cros::mojom::EffectsConfigPtr effects = cros::mojom::EffectsConfig::New();
|
||||
const int background_level_in_pref =
|
||||
int background_blur_state_in_pref =
|
||||
pref_change_registrar_->prefs()->GetInteger(prefs::kBackgroundBlur);
|
||||
if (!IsValidBackgroundBlurState(background_blur_state_in_pref)) {
|
||||
LOG(ERROR) << __FUNCTION__ << " background_blur_state_in_pref "
|
||||
<< background_blur_state_in_pref
|
||||
<< " is NOT a valid background blur effect state, using kOff";
|
||||
background_blur_state_in_pref =
|
||||
static_cast<int>(BackgroundBlurEffectState::kOff);
|
||||
}
|
||||
|
||||
effects->blur_enabled =
|
||||
background_level_in_pref != kBackgroundBlurLevelForDisabling;
|
||||
|
||||
effects->blur_level =
|
||||
effects->blur_enabled
|
||||
? static_cast<cros::mojom::BlurLevel>(background_level_in_pref)
|
||||
: GetBlurLevelFromFlag();
|
||||
CameraHalBackgroundBlurState blur_state =
|
||||
MapBackgroundBlurEffectStateToCameraHalState(
|
||||
background_blur_state_in_pref);
|
||||
effects->blur_enabled = blur_state.second;
|
||||
effects->blur_level = blur_state.first;
|
||||
|
||||
effects->replace_enabled =
|
||||
pref_change_registrar_->prefs()->GetBoolean(prefs::kBackgroundReplace);
|
||||
@ -289,9 +432,9 @@ void CameraEffectsController::SetEffectsConfigToPref(
|
||||
if (new_config->blur_enabled != old_effects->blur_enabled ||
|
||||
new_config->blur_level != old_effects->blur_level) {
|
||||
pref_change_registrar_->prefs()->SetInteger(
|
||||
prefs::kBackgroundBlur, new_config->blur_enabled
|
||||
? static_cast<int>(new_config->blur_level)
|
||||
: kBackgroundBlurLevelForDisabling);
|
||||
prefs::kBackgroundBlur,
|
||||
MapBackgroundBlurCameraHalStateToEffectState(new_config->blur_level,
|
||||
new_config->blur_enabled));
|
||||
}
|
||||
|
||||
if (new_config->replace_enabled != old_effects->replace_enabled) {
|
||||
@ -305,4 +448,100 @@ void CameraEffectsController::SetEffectsConfigToPref(
|
||||
}
|
||||
}
|
||||
|
||||
bool CameraEffectsController::IsEffectControlAvailable(
|
||||
cros::mojom::CameraEffect effect /* = cros::mojom::CameraEffect::kNone*/) {
|
||||
if (!ash::features::IsVcControlsUiEnabled()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (effect) {
|
||||
case cros::mojom::CameraEffect::kNone:
|
||||
// Return 'true' if any effect is available.
|
||||
return IsCameraEffectsSupported(
|
||||
cros::mojom::CameraEffect::kBackgroundBlur);
|
||||
case cros::mojom::CameraEffect::kBackgroundBlur:
|
||||
return IsCameraEffectsSupported(
|
||||
cros::mojom::CameraEffect::kBackgroundBlur);
|
||||
case cros::mojom::CameraEffect::kBackgroundReplace:
|
||||
case cros::mojom::CameraEffect::kPortraitRelight:
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void CameraEffectsController::InitializeEffectControls() {
|
||||
if (VideoConferenceTrayController::Get()
|
||||
->effects_manager()
|
||||
.IsDelegateRegistered(this)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If background blur UI controls are present, construct the effect and its
|
||||
// states.
|
||||
if (IsEffectControlAvailable(cros::mojom::CameraEffect::kBackgroundBlur)) {
|
||||
auto effect = std::make_unique<VcHostedEffect>(
|
||||
VcEffectType::kSetValue,
|
||||
base::BindRepeating(
|
||||
&CameraEffectsController::GetEffectState, base::Unretained(this),
|
||||
static_cast<int>(cros::mojom::CameraEffect::kBackgroundBlur)));
|
||||
effect->set_label_text(l10n_util::GetStringUTF16(
|
||||
IDS_ASH_VIDEO_CONFERENCE_BUBBLE_BACKGROUND_BLUR_NAME));
|
||||
effect->set_id(
|
||||
static_cast<int>(cros::mojom::CameraEffect::kBackgroundBlur));
|
||||
AddBackgroundBlurStateToEffect(
|
||||
effect.get(),
|
||||
/*state_value=*/BackgroundBlurEffectState::kOff,
|
||||
/*string_id=*/IDS_ASH_VIDEO_CONFERENCE_BUBBLE_BACKGROUND_BLUR_OFF);
|
||||
AddBackgroundBlurStateToEffect(
|
||||
effect.get(),
|
||||
/*state_value=*/BackgroundBlurEffectState::kLowest,
|
||||
/*string_id=*/IDS_ASH_VIDEO_CONFERENCE_BUBBLE_BACKGROUND_BLUR_LOWEST);
|
||||
AddBackgroundBlurStateToEffect(
|
||||
effect.get(),
|
||||
/*state_value=*/BackgroundBlurEffectState::kLight,
|
||||
/*string_id=*/IDS_ASH_VIDEO_CONFERENCE_BUBBLE_BACKGROUND_BLUR_LIGHT);
|
||||
AddBackgroundBlurStateToEffect(
|
||||
effect.get(),
|
||||
/*state_value=*/BackgroundBlurEffectState::kMedium,
|
||||
/*string_id=*/IDS_ASH_VIDEO_CONFERENCE_BUBBLE_BACKGROUND_BLUR_MEDIUM);
|
||||
AddBackgroundBlurStateToEffect(
|
||||
effect.get(),
|
||||
/*state_value=*/BackgroundBlurEffectState::kHeavy,
|
||||
/*string_id=*/IDS_ASH_VIDEO_CONFERENCE_BUBBLE_BACKGROUND_BLUR_HEAVY);
|
||||
AddBackgroundBlurStateToEffect(
|
||||
effect.get(),
|
||||
/*state_value=*/BackgroundBlurEffectState::kMaximum,
|
||||
/*string_id=*/
|
||||
IDS_ASH_VIDEO_CONFERENCE_BUBBLE_BACKGROUND_BLUR_MAXIMUM);
|
||||
AddEffect(std::move(effect));
|
||||
}
|
||||
|
||||
// If *any* effects' UI controls are present, register with the effects
|
||||
// manager.
|
||||
if (IsEffectControlAvailable()) {
|
||||
VideoConferenceTrayController::Get()->effects_manager().RegisterDelegate(
|
||||
this);
|
||||
}
|
||||
}
|
||||
|
||||
void CameraEffectsController::AddBackgroundBlurStateToEffect(
|
||||
VcHostedEffect* effect,
|
||||
int state_value,
|
||||
int string_id) {
|
||||
DCHECK(effect);
|
||||
effect->AddState(std::make_unique<VcEffectState>(
|
||||
/*icon=*/nullptr,
|
||||
/*label_text=*/l10n_util::GetStringUTF16(string_id),
|
||||
/*accessible_name_id=*/string_id,
|
||||
/*button_callback=*/
|
||||
base::BindRepeating(
|
||||
&CameraEffectsController::OnEffectControlActivated,
|
||||
weak_factory_.GetWeakPtr(),
|
||||
/*effect_id=*/
|
||||
static_cast<int>(cros::mojom::CameraEffect::kBackgroundBlur),
|
||||
/*value=*/state_value),
|
||||
/*state=*/state_value));
|
||||
}
|
||||
|
||||
} // namespace ash
|
||||
|
@ -10,12 +10,12 @@
|
||||
#include "ash/ash_export.h"
|
||||
#include "ash/public/cpp/session/session_controller.h"
|
||||
#include "ash/public/cpp/session/session_observer.h"
|
||||
#include "ash/system/video_conference/effects/video_conference_tray_effects_delegate.h"
|
||||
#include "base/memory/weak_ptr.h"
|
||||
#include "base/observer_list.h"
|
||||
#include "base/observer_list_types.h"
|
||||
#include "base/scoped_observation.h"
|
||||
#include "media/capture/video/chromeos/mojom/effects_pipeline.mojom.h"
|
||||
#include "third_party/abseil-cpp/absl/types/optional.h"
|
||||
|
||||
class PrefRegistrySimple;
|
||||
class PrefService;
|
||||
@ -25,7 +25,8 @@ namespace ash {
|
||||
|
||||
// CameraEffectsController is the interface for any object in ash to
|
||||
// enable/change camera effects.
|
||||
class ASH_EXPORT CameraEffectsController : public SessionObserver {
|
||||
class ASH_EXPORT CameraEffectsController : public SessionObserver,
|
||||
public VcEffectsDelegate {
|
||||
public:
|
||||
// Observer that will be notified on camera effects change.
|
||||
class Observer : public base::CheckedObserver {
|
||||
@ -34,6 +35,17 @@ class ASH_EXPORT CameraEffectsController : public SessionObserver {
|
||||
cros::mojom::EffectsConfigPtr new_effects) = 0;
|
||||
};
|
||||
|
||||
// Enum that represents the value persisted to `prefs::kBackgroundBlur`,
|
||||
// which is the "ultimate source of truth" for the background blur setting.
|
||||
enum BackgroundBlurEffectState {
|
||||
kOff = -1,
|
||||
kLowest = 0,
|
||||
kLight = 1,
|
||||
kMedium = 2,
|
||||
kHeavy = 3,
|
||||
kMaximum = 4,
|
||||
};
|
||||
|
||||
CameraEffectsController();
|
||||
|
||||
CameraEffectsController(const CameraEffectsController&) = delete;
|
||||
@ -48,6 +60,11 @@ class ASH_EXPORT CameraEffectsController : public SessionObserver {
|
||||
static bool IsCameraEffectsSupported(
|
||||
cros::mojom::CameraEffect effect = cros::mojom::CameraEffect::kNone);
|
||||
|
||||
// Returns 'true' if UI controls for `effect` are available to the user,
|
||||
// 'false' otherwise.
|
||||
bool IsEffectControlAvailable(
|
||||
cros::mojom::CameraEffect effect = cros::mojom::CameraEffect::kNone);
|
||||
|
||||
// Returns currently applied camera effects.
|
||||
// Should only be called after user logs in.
|
||||
cros::mojom::EffectsConfigPtr GetCameraEffects();
|
||||
@ -62,6 +79,10 @@ class ASH_EXPORT CameraEffectsController : public SessionObserver {
|
||||
// SessionObserver:
|
||||
void OnActiveUserPrefServiceChanged(PrefService* pref_service) override;
|
||||
|
||||
// VcEffectsDelegate:
|
||||
int GetEffectState(int effect_id) override;
|
||||
void OnEffectControlActivated(int effect_id, int value) override;
|
||||
|
||||
void set_effect_result_for_testing(
|
||||
cros::mojom::SetEffectResult effect_result_for_testing) {
|
||||
effect_result_for_testing_ = effect_result_for_testing;
|
||||
@ -89,6 +110,16 @@ class ASH_EXPORT CameraEffectsController : public SessionObserver {
|
||||
// Update prefs with the value in `config`.
|
||||
void SetEffectsConfigToPref(cros::mojom::EffectsConfigPtr config);
|
||||
|
||||
// Performs any initializations needed for effects whose controls are exposed
|
||||
// via the UI.
|
||||
void InitializeEffectControls();
|
||||
|
||||
// Adds a `std::unique_ptr<VcEffectState>` to `effect`, where `effect` is
|
||||
// assumed to be that of camera background blur.
|
||||
void AddBackgroundBlurStateToEffect(VcHostedEffect* effect,
|
||||
int state_value,
|
||||
int string_id);
|
||||
|
||||
// Used to bypass the CameraHalDispatcherImpl::SetCameraEffects for testing
|
||||
// purpose. The value will be null for non-testing cases; and not null in
|
||||
// testing cases.
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include "ash/constants/ash_pref_names.h"
|
||||
#include "ash/session/session_controller_impl.h"
|
||||
#include "ash/shell.h"
|
||||
#include "ash/system/video_conference/fake_video_conference_tray_controller.h"
|
||||
#include "ash/test/ash_test_base.h"
|
||||
#include "base/test/scoped_feature_list.h"
|
||||
|
||||
@ -37,9 +38,22 @@ class CameraEffectsControllerTest : public NoSessionAshTestBase {
|
||||
// NoSessionAshTestBase:
|
||||
void SetUp() override {
|
||||
scoped_feature_list_.InitWithFeatures(
|
||||
{features::kVCBackgroundBlur},
|
||||
{features::kVcControlsUi, features::kVCBackgroundBlur},
|
||||
{features::kVCBackgroundReplace, features::kVCPortraitRelighting});
|
||||
|
||||
// Here we have to create the global instance of `CrasAudioHandler` before
|
||||
// `FakeVideoConferenceTrayController`, so we do it here and not in
|
||||
// `AshTestBase`.
|
||||
CrasAudioClient::InitializeFake();
|
||||
CrasAudioHandler::InitializeForTesting();
|
||||
|
||||
// Instantiates a fake controller (the real one is created in
|
||||
// ChromeBrowserMainExtraPartsAsh::PreProfileInit() which is not called in
|
||||
// ash unit tests).
|
||||
controller_ = std::make_unique<FakeVideoConferenceTrayController>();
|
||||
|
||||
set_create_global_cras_audio_handler(false);
|
||||
|
||||
AshTestBase::SetUp();
|
||||
|
||||
camera_effects_controller_ = Shell::Get()->camera_effects_controller();
|
||||
@ -49,6 +63,13 @@ class CameraEffectsControllerTest : public NoSessionAshTestBase {
|
||||
cros::mojom::SetEffectResult::kOk);
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
NoSessionAshTestBase::TearDown();
|
||||
controller_.reset();
|
||||
CrasAudioHandler::Shutdown();
|
||||
CrasAudioClient::Shutdown();
|
||||
}
|
||||
|
||||
// Enables/Disables pref values.
|
||||
void SetEnabledPref(const std::string& perf_name, bool enabled) {
|
||||
Shell::Get()->session_controller()->GetActivePrefService()->SetBoolean(
|
||||
@ -61,8 +82,21 @@ class CameraEffectsControllerTest : public NoSessionAshTestBase {
|
||||
prefs::kBackgroundBlur, level);
|
||||
}
|
||||
|
||||
// Retrieves the value of `prefs::kBackgroundBlur`.
|
||||
int GetBackgroundBlurPref() {
|
||||
return Shell::Get()
|
||||
->session_controller()
|
||||
->GetActivePrefService()
|
||||
->GetInteger(prefs::kBackgroundBlur);
|
||||
}
|
||||
|
||||
CameraEffectsController* camera_effects_controller() {
|
||||
return camera_effects_controller_;
|
||||
}
|
||||
|
||||
protected:
|
||||
CameraEffectsController* camera_effects_controller_ = nullptr;
|
||||
std::unique_ptr<FakeVideoConferenceTrayController> controller_;
|
||||
base::test::ScopedFeatureList scoped_feature_list_;
|
||||
};
|
||||
|
||||
@ -82,12 +116,19 @@ TEST_F(CameraEffectsControllerTest,
|
||||
cros::mojom::CameraEffect::kBackgroundReplace));
|
||||
EXPECT_FALSE(CameraEffectsController::IsCameraEffectsSupported(
|
||||
cros::mojom::CameraEffect::kPortraitRelight));
|
||||
|
||||
// No camera effects supported and VC controls UI not enabled, no camera
|
||||
// effects UI controls available.
|
||||
EXPECT_TRUE(camera_effects_controller());
|
||||
EXPECT_FALSE(camera_effects_controller()->IsEffectControlAvailable());
|
||||
EXPECT_FALSE(camera_effects_controller()->IsEffectControlAvailable(
|
||||
cros::mojom::CameraEffect::kBackgroundBlur));
|
||||
}
|
||||
|
||||
{
|
||||
base::test::ScopedFeatureList scoped_feature_list;
|
||||
scoped_feature_list.InitWithFeatures(
|
||||
{features::kVCBackgroundBlur},
|
||||
{features::kVcControlsUi, features::kVCBackgroundBlur},
|
||||
{features::kVCBackgroundReplace, features::kVCPortraitRelighting});
|
||||
|
||||
// BackgroundBlur should be supported.
|
||||
@ -98,6 +139,13 @@ TEST_F(CameraEffectsControllerTest,
|
||||
cros::mojom::CameraEffect::kBackgroundReplace));
|
||||
EXPECT_FALSE(CameraEffectsController::IsCameraEffectsSupported(
|
||||
cros::mojom::CameraEffect::kPortraitRelight));
|
||||
|
||||
// Camera effects are supported, VC controls UI enabled, so camera effects
|
||||
// UI controls are available, and background blur UI is available.
|
||||
EXPECT_TRUE(camera_effects_controller());
|
||||
EXPECT_TRUE(camera_effects_controller()->IsEffectControlAvailable());
|
||||
EXPECT_TRUE(camera_effects_controller()->IsEffectControlAvailable(
|
||||
cros::mojom::CameraEffect::kBackgroundBlur));
|
||||
}
|
||||
|
||||
{
|
||||
@ -445,5 +493,90 @@ TEST_F(CameraEffectsControllerTest, NotifyObserverTest) {
|
||||
camera_effects_controller_->RemoveObserver(&observer);
|
||||
}
|
||||
|
||||
TEST_F(CameraEffectsControllerTest, BackgroundBlurGetEffectState) {
|
||||
SimulateUserLogin("testuser@gmail.com");
|
||||
|
||||
// Pref value is `kBackgroundBlurLevelForDisabling` (off).
|
||||
SetBackgroundBlurPref(-1);
|
||||
EXPECT_EQ(camera_effects_controller_->GetEffectState(
|
||||
static_cast<int>(cros::mojom::CameraEffect::kBackgroundBlur)),
|
||||
CameraEffectsController::BackgroundBlurEffectState::kOff);
|
||||
|
||||
// Test all values of `cros::mojom::BlurLevel`.
|
||||
SetBackgroundBlurPref(static_cast<int>(cros::mojom::BlurLevel::kLowest));
|
||||
EXPECT_EQ(camera_effects_controller_->GetEffectState(
|
||||
static_cast<int>(cros::mojom::CameraEffect::kBackgroundBlur)),
|
||||
CameraEffectsController::BackgroundBlurEffectState::kLowest);
|
||||
SetBackgroundBlurPref(static_cast<int>(cros::mojom::BlurLevel::kLight));
|
||||
EXPECT_EQ(camera_effects_controller_->GetEffectState(
|
||||
static_cast<int>(cros::mojom::CameraEffect::kBackgroundBlur)),
|
||||
CameraEffectsController::BackgroundBlurEffectState::kLight);
|
||||
SetBackgroundBlurPref(static_cast<int>(cros::mojom::BlurLevel::kMedium));
|
||||
EXPECT_EQ(camera_effects_controller_->GetEffectState(
|
||||
static_cast<int>(cros::mojom::CameraEffect::kBackgroundBlur)),
|
||||
CameraEffectsController::BackgroundBlurEffectState::kMedium);
|
||||
SetBackgroundBlurPref(static_cast<int>(cros::mojom::BlurLevel::kHeavy));
|
||||
EXPECT_EQ(camera_effects_controller_->GetEffectState(
|
||||
static_cast<int>(cros::mojom::CameraEffect::kBackgroundBlur)),
|
||||
CameraEffectsController::BackgroundBlurEffectState::kHeavy);
|
||||
SetBackgroundBlurPref(static_cast<int>(cros::mojom::BlurLevel::kMaximum));
|
||||
EXPECT_EQ(camera_effects_controller_->GetEffectState(
|
||||
static_cast<int>(cros::mojom::CameraEffect::kBackgroundBlur)),
|
||||
CameraEffectsController::BackgroundBlurEffectState::kMaximum);
|
||||
|
||||
// Now verify with a pref value that isn't recognized as a valid background
|
||||
// blur state.
|
||||
SetBackgroundBlurPref(-999);
|
||||
EXPECT_EQ(camera_effects_controller_->GetEffectState(
|
||||
static_cast<int>(cros::mojom::CameraEffect::kBackgroundBlur)),
|
||||
CameraEffectsController::BackgroundBlurEffectState::kOff);
|
||||
}
|
||||
|
||||
TEST_F(CameraEffectsControllerTest, BackgroundBlurOnEffectControlActivated) {
|
||||
SimulateUserLogin("testuser@gmail.com");
|
||||
|
||||
// Activate `kOff`, verify that pref value is -1
|
||||
// (`kBackgroundBlurLevelForDisabling`).
|
||||
camera_effects_controller_->OnEffectControlActivated(
|
||||
static_cast<int>(cros::mojom::CameraEffect::kBackgroundBlur),
|
||||
CameraEffectsController::BackgroundBlurEffectState::kOff);
|
||||
EXPECT_EQ(GetBackgroundBlurPref(), -1);
|
||||
|
||||
// Activate the rest of the possible values of
|
||||
// `CameraEffectsController::BackgroundBlurEffectState`, verify that the pref
|
||||
// value is the expected value of `cros::mojom::BlurLevel`.
|
||||
camera_effects_controller_->OnEffectControlActivated(
|
||||
static_cast<int>(cros::mojom::CameraEffect::kBackgroundBlur),
|
||||
CameraEffectsController::BackgroundBlurEffectState::kLowest);
|
||||
EXPECT_EQ(GetBackgroundBlurPref(),
|
||||
static_cast<int>(cros::mojom::BlurLevel::kLowest));
|
||||
camera_effects_controller_->OnEffectControlActivated(
|
||||
static_cast<int>(cros::mojom::CameraEffect::kBackgroundBlur),
|
||||
CameraEffectsController::BackgroundBlurEffectState::kLight);
|
||||
EXPECT_EQ(GetBackgroundBlurPref(),
|
||||
static_cast<int>(cros::mojom::BlurLevel::kLight));
|
||||
camera_effects_controller_->OnEffectControlActivated(
|
||||
static_cast<int>(cros::mojom::CameraEffect::kBackgroundBlur),
|
||||
CameraEffectsController::BackgroundBlurEffectState::kMedium);
|
||||
EXPECT_EQ(GetBackgroundBlurPref(),
|
||||
static_cast<int>(cros::mojom::BlurLevel::kMedium));
|
||||
camera_effects_controller_->OnEffectControlActivated(
|
||||
static_cast<int>(cros::mojom::CameraEffect::kBackgroundBlur),
|
||||
CameraEffectsController::BackgroundBlurEffectState::kHeavy);
|
||||
EXPECT_EQ(GetBackgroundBlurPref(),
|
||||
static_cast<int>(cros::mojom::BlurLevel::kHeavy));
|
||||
camera_effects_controller_->OnEffectControlActivated(
|
||||
static_cast<int>(cros::mojom::CameraEffect::kBackgroundBlur),
|
||||
CameraEffectsController::BackgroundBlurEffectState::kMaximum);
|
||||
EXPECT_EQ(GetBackgroundBlurPref(),
|
||||
static_cast<int>(cros::mojom::BlurLevel::kMaximum));
|
||||
|
||||
// Passing an invalid background blur state is the same as activating
|
||||
// `kOff`.
|
||||
camera_effects_controller_->OnEffectControlActivated(
|
||||
static_cast<int>(cros::mojom::CameraEffect::kBackgroundBlur), -999);
|
||||
EXPECT_EQ(GetBackgroundBlurPref(), -1);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace ash
|
||||
|
@ -22,6 +22,10 @@ enum BubbleViewID {
|
||||
// `kMainBubbleView`.
|
||||
kSetValueEffectsView,
|
||||
|
||||
// Container view for a single "set-value" VC effect, a child of
|
||||
// `kSetValueEffectsView`.
|
||||
kSingleSetValueEffectView,
|
||||
|
||||
// Container view for all "toggle" VC effects, a child of `kMainBubbleView`.
|
||||
kToggleEffectsView,
|
||||
|
||||
|
@ -47,6 +47,8 @@ class BubbleViewTest : public AshTestBase {
|
||||
office_bunny_ =
|
||||
std::make_unique<fake_video_conference::OfficeBunnyEffect>();
|
||||
shaggy_fur_ = std::make_unique<fake_video_conference::ShaggyFurEffect>();
|
||||
super_cuteness_ =
|
||||
std::make_unique<fake_video_conference::SuperCutnessEffect>();
|
||||
|
||||
set_create_global_cras_audio_handler(false);
|
||||
AshTestBase::SetUp();
|
||||
@ -59,6 +61,7 @@ class BubbleViewTest : public AshTestBase {
|
||||
AshTestBase::TearDown();
|
||||
office_bunny_.reset();
|
||||
shaggy_fur_.reset();
|
||||
super_cuteness_.reset();
|
||||
controller_.reset();
|
||||
CrasAudioHandler::Shutdown();
|
||||
CrasAudioClient::Shutdown();
|
||||
@ -98,6 +101,11 @@ class BubbleViewTest : public AshTestBase {
|
||||
video_conference::BubbleViewID::kSetValueEffectsView);
|
||||
}
|
||||
|
||||
views::View* single_set_value_effect_view() {
|
||||
return bubble_view()->GetViewByID(
|
||||
video_conference::BubbleViewID::kSingleSetValueEffectView);
|
||||
}
|
||||
|
||||
views::View* return_to_app() {
|
||||
return bubble_view()->GetViewByID(
|
||||
video_conference::BubbleViewID::kReturnToApp);
|
||||
@ -116,11 +124,17 @@ class BubbleViewTest : public AshTestBase {
|
||||
return shaggy_fur_.get();
|
||||
}
|
||||
|
||||
ash::fake_video_conference::SuperCutnessEffect* super_cuteness() {
|
||||
return super_cuteness_.get();
|
||||
}
|
||||
|
||||
private:
|
||||
base::test::ScopedFeatureList scoped_feature_list_;
|
||||
std::unique_ptr<FakeVideoConferenceTrayController> controller_;
|
||||
std::unique_ptr<ash::fake_video_conference::OfficeBunnyEffect> office_bunny_;
|
||||
std::unique_ptr<ash::fake_video_conference::ShaggyFurEffect> shaggy_fur_;
|
||||
std::unique_ptr<ash::fake_video_conference::SuperCutnessEffect>
|
||||
super_cuteness_;
|
||||
};
|
||||
|
||||
TEST_F(BubbleViewTest, NoEffects) {
|
||||
@ -274,4 +288,42 @@ TEST_F(BubbleViewTest, SetValueButtonClicked) {
|
||||
EXPECT_EQ(shaggy_fur()->GetNumActivationsForTesting(1), 1);
|
||||
EXPECT_EQ(shaggy_fur()->GetNumActivationsForTesting(0), 1);
|
||||
}
|
||||
|
||||
TEST_F(BubbleViewTest, ValidEffectState) {
|
||||
// Verify that the delegate hosts a single effect which has at least two
|
||||
// values.
|
||||
EXPECT_EQ(super_cuteness()->GetNumEffects(), 1);
|
||||
EXPECT_GE(super_cuteness()->GetEffect(0)->GetNumStates(), 2);
|
||||
|
||||
// Add one set-value effect.
|
||||
controller()->effects_manager().RegisterDelegate(super_cuteness());
|
||||
|
||||
// Effect will NOT return an invalid state.
|
||||
super_cuteness()->set_has_invalid_effect_state_for_testing(false);
|
||||
|
||||
// Click to open the bubble, a single set-value effect view is
|
||||
// present/visible.
|
||||
LeftClickOn(toggle_bubble_button());
|
||||
views::View* effect_view = single_set_value_effect_view();
|
||||
EXPECT_TRUE(effect_view);
|
||||
EXPECT_TRUE(effect_view->GetVisible());
|
||||
}
|
||||
|
||||
TEST_F(BubbleViewTest, InvalidEffectState) {
|
||||
// Verify that the delegate hosts a single effect which has at least two
|
||||
// values.
|
||||
EXPECT_EQ(super_cuteness()->GetNumEffects(), 1);
|
||||
EXPECT_GE(super_cuteness()->GetEffect(0)->GetNumStates(), 2);
|
||||
|
||||
// Add one set-value effect.
|
||||
controller()->effects_manager().RegisterDelegate(super_cuteness());
|
||||
|
||||
// Effect WILL return an invalid state.
|
||||
super_cuteness()->set_has_invalid_effect_state_for_testing(true);
|
||||
|
||||
// Click to open the bubble, a single set-value effect view is NOT present.
|
||||
LeftClickOn(toggle_bubble_button());
|
||||
EXPECT_FALSE(single_set_value_effect_view());
|
||||
}
|
||||
|
||||
} // namespace ash::video_conference
|
@ -24,6 +24,7 @@ namespace {
|
||||
class ValueButtonContainer : public views::View {
|
||||
public:
|
||||
explicit ValueButtonContainer(const VcHostedEffect* effect) {
|
||||
SetID(BubbleViewID::kSingleSetValueEffectView);
|
||||
views::FlexLayout* layout =
|
||||
SetLayoutManager(std::make_unique<views::FlexLayout>());
|
||||
layout->SetOrientation(views::LayoutOrientation::kVertical);
|
||||
@ -34,8 +35,13 @@ class ValueButtonContainer : public views::View {
|
||||
AddChildView(std::make_unique<views::Label>(effect->label_text()));
|
||||
}
|
||||
|
||||
// Add a button for each state.
|
||||
// `effect` is expected to provide the current state of the effect, and
|
||||
// a `current_state` of `VcEffectState::kUnusedId` means it couldn't be
|
||||
// obtained.
|
||||
const int current_state = effect->get_state_callback().Run();
|
||||
DCHECK(current_state != VcEffectState::kUnusedId);
|
||||
|
||||
// Add a button for each state.
|
||||
for (int i = 0; i < effect->GetNumStates(); ++i) {
|
||||
const VcEffectState* state = effect->GetState(/*index=*/i);
|
||||
std::unique_ptr<views::RadioButton> state_button =
|
||||
@ -83,6 +89,15 @@ SetValueEffectsView::SetValueEffectsView(
|
||||
|
||||
if (controller->effects_manager().HasSetValueEffects()) {
|
||||
for (auto* effect : controller->effects_manager().GetSetValueEffects()) {
|
||||
// Make sure the current value of the effect can be obtained, and if it
|
||||
// can't then don't present its controls.
|
||||
if (effect->get_state_callback().Run() == VcEffectState::kUnusedId) {
|
||||
LOG(ERROR) << __FUNCTION__ << " effect with id (" << effect->id()
|
||||
<< ") label_text (" << effect->label_text()
|
||||
<< ") could not obtain its current value";
|
||||
continue;
|
||||
}
|
||||
|
||||
AddChildView(std::make_unique<ValueButtonContainer>(effect));
|
||||
}
|
||||
}
|
||||
|
@ -170,6 +170,10 @@ SuperCutnessEffect::SuperCutnessEffect() {
|
||||
SuperCutnessEffect::~SuperCutnessEffect() = default;
|
||||
|
||||
int SuperCutnessEffect::GetEffectState(int effect_id) {
|
||||
if (has_invalid_effect_state_for_testing_) {
|
||||
return VcEffectState::kUnusedId;
|
||||
}
|
||||
|
||||
return static_cast<int>(HowCute::kTeddyBear);
|
||||
}
|
||||
|
||||
|
@ -189,6 +189,13 @@ class ASH_EXPORT SuperCutnessEffect : public VcEffectsDelegate {
|
||||
// activated.
|
||||
int GetNumActivationsForTesting(int value);
|
||||
|
||||
void set_has_invalid_effect_state_for_testing(bool has_invalid_state) {
|
||||
has_invalid_effect_state_for_testing_ = has_invalid_state;
|
||||
}
|
||||
bool has_invalid_effect_state_for_testing() {
|
||||
return has_invalid_effect_state_for_testing_;
|
||||
}
|
||||
|
||||
private:
|
||||
// Adds a `std::unique_ptr<VcEffectState>` to `effect`.
|
||||
void AddStateToEffect(VcHostedEffect* effect,
|
||||
@ -199,6 +206,10 @@ class ASH_EXPORT SuperCutnessEffect : public VcEffectsDelegate {
|
||||
// `HowCute`.
|
||||
std::vector<int> num_activations_for_testing_;
|
||||
|
||||
// Set to 'true' for testing the case where a valid effect state cannot be
|
||||
// obtained.
|
||||
bool has_invalid_effect_state_for_testing_;
|
||||
|
||||
base::WeakPtrFactory<SuperCutnessEffect> weak_factory_{this};
|
||||
};
|
||||
|
||||
|
@ -47,7 +47,9 @@ class ASH_EXPORT VcEffectsDelegate {
|
||||
|
||||
// Invoked when the UI controls are being constructed, to get the actual
|
||||
// effect state. `effect_id` specifies the effect whose state is requested,
|
||||
// and can be ignored if only one effect is being hosted.
|
||||
// and can be ignored if only one effect is being hosted. If no state can be
|
||||
// determined for `effect_id`, this function should return
|
||||
// `VcEffectState::kUnusedId`.
|
||||
virtual int GetEffectState(int effect_id) = 0;
|
||||
|
||||
// Invoked anytime the user makes an adjustment. `effect_id` is the unique ID
|
||||
|
@ -21,10 +21,7 @@ VideoConferenceTrayEffectsManager::~VideoConferenceTrayEffectsManager() =
|
||||
void VideoConferenceTrayEffectsManager::RegisterDelegate(
|
||||
VcEffectsDelegate* delegate) {
|
||||
DCHECK(delegate);
|
||||
DCHECK(std::find_if(effect_delegates_.begin(), effect_delegates_.end(),
|
||||
[delegate](VcEffectsDelegate* d) {
|
||||
return delegate == d;
|
||||
}) == effect_delegates_.end());
|
||||
DCHECK(!IsDelegateRegistered(delegate));
|
||||
effect_delegates_.push_back(delegate);
|
||||
}
|
||||
|
||||
@ -37,6 +34,15 @@ void VideoConferenceTrayEffectsManager::UnregisterDelegate(
|
||||
DCHECK_EQ(num_items_erased, 1UL);
|
||||
}
|
||||
|
||||
bool VideoConferenceTrayEffectsManager::IsDelegateRegistered(
|
||||
VcEffectsDelegate* delegate) {
|
||||
DCHECK(delegate);
|
||||
return std::find_if(effect_delegates_.begin(), effect_delegates_.end(),
|
||||
[delegate](VcEffectsDelegate* d) {
|
||||
return delegate == d;
|
||||
}) != effect_delegates_.end();
|
||||
}
|
||||
|
||||
bool VideoConferenceTrayEffectsManager::HasToggleEffects() {
|
||||
return GetTotalToggleEffectButtons().size() > 0;
|
||||
}
|
||||
@ -49,8 +55,9 @@ VideoConferenceTrayEffectsManager::GetToggleEffectButtonTable() {
|
||||
EffectDataTable buttons;
|
||||
|
||||
int num_buttons = total_buttons.size();
|
||||
if (num_buttons == 0)
|
||||
if (num_buttons == 0) {
|
||||
return buttons;
|
||||
}
|
||||
|
||||
if (num_buttons <= 3) {
|
||||
// For 3 or fewer, `effects_buttons` is the entire row.
|
||||
@ -80,8 +87,9 @@ VideoConferenceTrayEffectsManager::GetSetValueEffects() {
|
||||
EffectDataVector effects;
|
||||
|
||||
for (auto* delegate : effect_delegates_) {
|
||||
for (auto* effect : delegate->GetEffects(VcEffectType::kSetValue))
|
||||
for (auto* effect : delegate->GetEffects(VcEffectType::kSetValue)) {
|
||||
effects.push_back(effect);
|
||||
}
|
||||
}
|
||||
|
||||
return effects;
|
||||
@ -92,8 +100,9 @@ VideoConferenceTrayEffectsManager::GetTotalToggleEffectButtons() {
|
||||
EffectDataVector effects;
|
||||
|
||||
for (auto* delegate : effect_delegates_) {
|
||||
for (auto* effect : delegate->GetEffects(VcEffectType::kToggle))
|
||||
for (auto* effect : delegate->GetEffects(VcEffectType::kToggle)) {
|
||||
effects.push_back(effect);
|
||||
}
|
||||
}
|
||||
|
||||
return effects;
|
||||
|
@ -32,6 +32,9 @@ class ASH_EXPORT VideoConferenceTrayEffectsManager {
|
||||
void RegisterDelegate(VcEffectsDelegate* delegate);
|
||||
void UnregisterDelegate(VcEffectsDelegate* delegate);
|
||||
|
||||
// Returns 'true' if `delegate` is registered, 'false' otherwise.
|
||||
bool IsDelegateRegistered(VcEffectsDelegate* delegate);
|
||||
|
||||
// A vector (or row) of `VcHostedEffect` objects of type
|
||||
// `VcEffectType::kToggle`.
|
||||
using EffectDataVector = std::vector<const VcHostedEffect*>;
|
||||
|
Reference in New Issue
Block a user