Commit 76bfa3ec authored by Ken MacKay's avatar Ken MacKay Committed by Commit Bot

[Chromecast] Add 'other' content type

Add a new content type with no per-type volume control (only
per-stream).

Bug: internal b/78533406

Change-Id: If0d7280c54ba95fd583e7292814e476862d52335
Reviewed-on: https://chromium-review.googlesource.com/1026452
Commit-Queue: Kenneth MacKay <kmackay@chromium.org>
Reviewed-by: default avatarStephen Lanham <slan@chromium.org>
Reviewed-by: default avatarLuke Halliwell <halliwell@chromium.org>
Cr-Commit-Position: refs/heads/master@{#553755}
parent 85b28723
...@@ -19,6 +19,8 @@ const char* GetAudioContentTypeName(const AudioContentType type) { ...@@ -19,6 +19,8 @@ const char* GetAudioContentTypeName(const AudioContentType type) {
return "kAlarm"; return "kAlarm";
case AudioContentType::kCommunication: case AudioContentType::kCommunication:
return "kCommunication"; return "kCommunication";
case AudioContentType::kOther:
return "kOther";
default: default:
return "Unknown"; return "Unknown";
} }
......
...@@ -53,21 +53,23 @@ class AudioSinkAudioTrackImpl { ...@@ -53,21 +53,23 @@ class AudioSinkAudioTrackImpl {
// Mapping from Android's stream_type to Cast's AudioContentType (used for callback). // Mapping from Android's stream_type to Cast's AudioContentType (used for callback).
private static final SparseIntArray CAST_TYPE_TO_ANDROID_USAGE_TYPE_MAP = new SparseIntArray( private static final SparseIntArray CAST_TYPE_TO_ANDROID_USAGE_TYPE_MAP = new SparseIntArray(
3) { 4) {
{ {
append(AudioContentType.MEDIA, AudioAttributes.USAGE_MEDIA); append(AudioContentType.MEDIA, AudioAttributes.USAGE_MEDIA);
append(AudioContentType.ALARM, AudioAttributes.USAGE_ALARM); append(AudioContentType.ALARM, AudioAttributes.USAGE_ALARM);
append(AudioContentType.COMMUNICATION, AudioAttributes.USAGE_ASSISTANCE_SONIFICATION); append(AudioContentType.COMMUNICATION, AudioAttributes.USAGE_ASSISTANCE_SONIFICATION);
append(AudioContentType.OTHER, AudioAttributes.USAGE_VOICE_COMMUNICATION);
} }
}; };
private static final SparseIntArray CAST_TYPE_TO_ANDROID_CONTENT_TYPE_MAP = new SparseIntArray( private static final SparseIntArray CAST_TYPE_TO_ANDROID_CONTENT_TYPE_MAP = new SparseIntArray(
3) { 4) {
{ {
append(AudioContentType.MEDIA, AudioAttributes.CONTENT_TYPE_MUSIC); append(AudioContentType.MEDIA, AudioAttributes.CONTENT_TYPE_MUSIC);
// Note: ALARM uses the same as COMMUNICATON. // Note: ALARM uses the same as COMMUNICATON.
append(AudioContentType.ALARM, AudioAttributes.CONTENT_TYPE_SONIFICATION); append(AudioContentType.ALARM, AudioAttributes.CONTENT_TYPE_SONIFICATION);
append(AudioContentType.COMMUNICATION, AudioAttributes.CONTENT_TYPE_SONIFICATION); append(AudioContentType.COMMUNICATION, AudioAttributes.CONTENT_TYPE_SONIFICATION);
append(AudioContentType.OTHER, AudioAttributes.CONTENT_TYPE_SPEECH);
} }
}; };
......
...@@ -22,12 +22,14 @@ import org.chromium.chromecast.media.AudioContentType; ...@@ -22,12 +22,14 @@ import org.chromium.chromecast.media.AudioContentType;
/** /**
* Implements the java-side of the volume control logic running on Android when using CMA backend by * Implements the java-side of the volume control logic running on Android when using CMA backend by
* setting the volume levels and mute states directly in the OS using AudioManager. The following * setting the volume levels and mute states directly in the OS using AudioManager. kOther is mostly
* mapping is used between Cast's native AudioContentType and Android's internal stream types: * used for voice calls, so use Android's STREAM_VOICE_CALL. The following mapping is used between
* Cast's native AudioContentType and Android's internal stream types:
* *
* AudioContentType::kMedia -> AudioManager.STREAM_MUSIC * AudioContentType::kMedia -> AudioManager.STREAM_MUSIC
* AudioContentType::kAlarm -> AudioManager.STREAM_ALARM * AudioContentType::kAlarm -> AudioManager.STREAM_ALARM
* AudioContentType::kCommunication -> AudioManager.STREAM_SYSTEM * AudioContentType::kCommunication -> AudioManager.STREAM_SYSTEM
* AudioContentType::kOther -> AudioManager.STREAM_VOICE_CALL
* *
* In addition it listens to volume and mute state changes broadcasted by the system via (hidden) * In addition it listens to volume and mute state changes broadcasted by the system via (hidden)
* intents and reports detected changes back to the native volume controller code. * intents and reports detected changes back to the native volume controller code.
...@@ -120,11 +122,12 @@ class VolumeControl { ...@@ -120,11 +122,12 @@ class VolumeControl {
private static final String EXTRA_VOLUME_STREAM_TYPE = "android.media.EXTRA_VOLUME_STREAM_TYPE"; private static final String EXTRA_VOLUME_STREAM_TYPE = "android.media.EXTRA_VOLUME_STREAM_TYPE";
// Mapping from Android's stream_type to Cast's AudioContentType (used for callback). // Mapping from Android's stream_type to Cast's AudioContentType (used for callback).
private static final SparseIntArray ANDROID_TYPE_TO_CAST_TYPE_MAP = new SparseIntArray(3) { private static final SparseIntArray ANDROID_TYPE_TO_CAST_TYPE_MAP = new SparseIntArray(4) {
{ {
append(AudioManager.STREAM_MUSIC, AudioContentType.MEDIA); append(AudioManager.STREAM_MUSIC, AudioContentType.MEDIA);
append(AudioManager.STREAM_ALARM, AudioContentType.ALARM); append(AudioManager.STREAM_ALARM, AudioContentType.ALARM);
append(AudioManager.STREAM_SYSTEM, AudioContentType.COMMUNICATION); append(AudioManager.STREAM_SYSTEM, AudioContentType.COMMUNICATION);
append(AudioManager.STREAM_VOICE_CALL, AudioContentType.OTHER);
} }
}; };
...@@ -158,10 +161,11 @@ class VolumeControl { ...@@ -158,10 +161,11 @@ class VolumeControl {
mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE); mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
// Populate settings. // Populate settings.
mSettings = new SparseArray<Settings>(3); mSettings = new SparseArray<Settings>(4);
mSettings.append(AudioContentType.MEDIA, new Settings(AudioManager.STREAM_MUSIC)); mSettings.append(AudioContentType.MEDIA, new Settings(AudioManager.STREAM_MUSIC));
mSettings.append(AudioContentType.ALARM, new Settings(AudioManager.STREAM_ALARM)); mSettings.append(AudioContentType.ALARM, new Settings(AudioManager.STREAM_ALARM));
mSettings.append(AudioContentType.COMMUNICATION, new Settings(AudioManager.STREAM_SYSTEM)); mSettings.append(AudioContentType.COMMUNICATION, new Settings(AudioManager.STREAM_SYSTEM));
mSettings.append(AudioContentType.OTHER, new Settings(AudioManager.STREAM_VOICE_CALL));
registerIntentListeners(); registerIntentListeners();
} }
...@@ -174,7 +178,8 @@ class VolumeControl { ...@@ -174,7 +178,8 @@ class VolumeControl {
String action = intent.getAction(); String action = intent.getAction();
int type = intent.getIntExtra(EXTRA_VOLUME_STREAM_TYPE, -1); int type = intent.getIntExtra(EXTRA_VOLUME_STREAM_TYPE, -1);
if (type != AudioManager.STREAM_MUSIC && type != AudioManager.STREAM_ALARM if (type != AudioManager.STREAM_MUSIC && type != AudioManager.STREAM_ALARM
&& type != AudioManager.STREAM_SYSTEM) { && type != AudioManager.STREAM_SYSTEM
&& type != AudioManager.STREAM_VOICE_CALL) {
return; return;
} }
if (DEBUG_LEVEL >= 1) Log.i(TAG, "Got intent:" + action + " for type:" + type); if (DEBUG_LEVEL >= 1) Log.i(TAG, "Got intent:" + action + " for type:" + type);
......
...@@ -31,15 +31,16 @@ public final class VolumeMap { ...@@ -31,15 +31,16 @@ public final class VolumeMap {
private static AudioManager sAudioManager = null; private static AudioManager sAudioManager = null;
// Mapping from Android's stream_type to Cast's AudioContentType (used for callback). // Mapping from Android's stream_type to Cast's AudioContentType (used for callback).
private static final SparseIntArray ANDROID_TYPE_TO_CAST_TYPE_MAP = new SparseIntArray(3) { private static final SparseIntArray ANDROID_TYPE_TO_CAST_TYPE_MAP = new SparseIntArray(4) {
{ {
append(AudioManager.STREAM_MUSIC, AudioContentType.MEDIA); append(AudioManager.STREAM_MUSIC, AudioContentType.MEDIA);
append(AudioManager.STREAM_ALARM, AudioContentType.ALARM); append(AudioManager.STREAM_ALARM, AudioContentType.ALARM);
append(AudioManager.STREAM_SYSTEM, AudioContentType.COMMUNICATION); append(AudioManager.STREAM_SYSTEM, AudioContentType.COMMUNICATION);
append(AudioManager.STREAM_VOICE_CALL, AudioContentType.OTHER);
} }
}; };
private static final SparseIntArray MAX_VOLUME_INDEX = new SparseIntArray(3) { private static final SparseIntArray MAX_VOLUME_INDEX = new SparseIntArray(4) {
{ {
append(AudioManager.STREAM_MUSIC, append(AudioManager.STREAM_MUSIC,
getAudioManager().getStreamMaxVolume(AudioManager.STREAM_MUSIC)); getAudioManager().getStreamMaxVolume(AudioManager.STREAM_MUSIC));
...@@ -47,6 +48,8 @@ public final class VolumeMap { ...@@ -47,6 +48,8 @@ public final class VolumeMap {
getAudioManager().getStreamMaxVolume(AudioManager.STREAM_ALARM)); getAudioManager().getStreamMaxVolume(AudioManager.STREAM_ALARM));
append(AudioManager.STREAM_SYSTEM, append(AudioManager.STREAM_SYSTEM,
getAudioManager().getStreamMaxVolume(AudioManager.STREAM_SYSTEM)); getAudioManager().getStreamMaxVolume(AudioManager.STREAM_SYSTEM));
append(AudioManager.STREAM_VOICE_CALL,
getAudioManager().getStreamMaxVolume(AudioManager.STREAM_VOICE_CALL));
} }
}; };
......
...@@ -112,6 +112,11 @@ float VolumeControlAndroid::GetVolume(AudioContentType type) { ...@@ -112,6 +112,11 @@ float VolumeControlAndroid::GetVolume(AudioContentType type) {
} }
void VolumeControlAndroid::SetVolume(AudioContentType type, float level) { void VolumeControlAndroid::SetVolume(AudioContentType type, float level) {
if (type == AudioContentType::kOther) {
NOTREACHED() << "Can't set volume for content type kOther";
return;
}
level = std::max(0.0f, std::min(level, 1.0f)); level = std::max(0.0f, std::min(level, 1.0f));
// The input level value is in the kMedia (MUSIC) volume table domain. // The input level value is in the kMedia (MUSIC) volume table domain.
float mapped_level = float mapped_level =
...@@ -128,6 +133,11 @@ bool VolumeControlAndroid::IsMuted(AudioContentType type) { ...@@ -128,6 +133,11 @@ bool VolumeControlAndroid::IsMuted(AudioContentType type) {
} }
void VolumeControlAndroid::SetMuted(AudioContentType type, bool muted) { void VolumeControlAndroid::SetMuted(AudioContentType type, bool muted) {
if (type == AudioContentType::kOther) {
NOTREACHED() << "Can't set mute state for content type kOther";
return;
}
thread_.task_runner()->PostTask( thread_.task_runner()->PostTask(
FROM_HERE, base::BindOnce(&VolumeControlAndroid::SetMutedOnThread, FROM_HERE, base::BindOnce(&VolumeControlAndroid::SetMutedOnThread,
base::Unretained(this), type, muted, base::Unretained(this), type, muted,
...@@ -135,6 +145,11 @@ void VolumeControlAndroid::SetMuted(AudioContentType type, bool muted) { ...@@ -135,6 +145,11 @@ void VolumeControlAndroid::SetMuted(AudioContentType type, bool muted) {
} }
void VolumeControlAndroid::SetOutputLimit(AudioContentType type, float limit) { void VolumeControlAndroid::SetOutputLimit(AudioContentType type, float limit) {
if (type == AudioContentType::kOther) {
NOTREACHED() << "Can't set output limit for content type kOther";
return;
}
// The input limit is in the kMedia (MUSIC) volume table domain. // The input limit is in the kMedia (MUSIC) volume table domain.
limit = std::max(0.0f, std::min(limit, 1.0f)); limit = std::max(0.0f, std::min(limit, 1.0f));
float limit_db = VolumeToDbFSByContentType(AudioContentType::kMedia, limit); float limit_db = VolumeToDbFSByContentType(AudioContentType::kMedia, limit);
...@@ -185,6 +200,14 @@ void VolumeControlAndroid::InitializeOnThread() { ...@@ -185,6 +200,14 @@ void VolumeControlAndroid::InitializeOnThread() {
<< " volume=" << volumes_[type] << " (" << volume_db << ")" << " volume=" << volumes_[type] << " (" << volume_db << ")"
<< " mute=" << muted_[type]; << " mute=" << muted_[type];
} }
// The kOther content type should not have any type-wide volume control or
// mute (volume control for kOther is per-stream only). Therefore, ensure
// that the global volume and mute state fo kOther is initialized correctly
// (100% volume, and not muted).
SetVolumeOnThread(AudioContentType::kOther, 1.0f, false /* from_android */);
SetMutedOnThread(AudioContentType::kOther, false, false /* from_android */);
initialize_complete_event_.Signal(); initialize_complete_event_.Signal();
} }
...@@ -255,12 +278,28 @@ void VolumeControlAndroid::SetMutedOnThread(AudioContentType type, ...@@ -255,12 +278,28 @@ void VolumeControlAndroid::SetMutedOnThread(AudioContentType type,
void VolumeControlAndroid::ReportVolumeChangeOnThread(AudioContentType type, void VolumeControlAndroid::ReportVolumeChangeOnThread(AudioContentType type,
float level) { float level) {
DCHECK(thread_.task_runner()->BelongsToCurrentThread()); DCHECK(thread_.task_runner()->BelongsToCurrentThread());
if (type == AudioContentType::kOther) {
// Volume for AudioContentType::kOther should stay at 1.0.
Java_VolumeControl_setVolume(base::android::AttachCurrentThread(),
j_volume_control_, static_cast<int>(type),
1.0f);
return;
}
SetVolumeOnThread(type, level, true /* from android */); SetVolumeOnThread(type, level, true /* from android */);
} }
void VolumeControlAndroid::ReportMuteChangeOnThread(AudioContentType type, void VolumeControlAndroid::ReportMuteChangeOnThread(AudioContentType type,
bool muted) { bool muted) {
DCHECK(thread_.task_runner()->BelongsToCurrentThread()); DCHECK(thread_.task_runner()->BelongsToCurrentThread());
if (type == AudioContentType::kOther) {
// Mute state for AudioContentType::kOther should always be false.
Java_VolumeControl_setMuted(base::android::AttachCurrentThread(),
j_volume_control_, static_cast<int>(type),
false);
return;
}
SetMutedOnThread(type, muted, true /* from_android */); SetMutedOnThread(type, muted, true /* from_android */);
} }
......
...@@ -43,6 +43,13 @@ void CastMediaShlib::RemoveDirectAudioSource(DirectAudioSourceToken* token) { ...@@ -43,6 +43,13 @@ void CastMediaShlib::RemoveDirectAudioSource(DirectAudioSourceToken* token) {
source->Remove(); source->Remove();
} }
// static
void CastMediaShlib::SetDirectAudioSourceVolume(DirectAudioSourceToken* token,
float multiplier) {
DirectMixerSource* source = static_cast<DirectMixerSource*>(token);
source->SetVolumeMultiplier(multiplier);
}
DirectMixerSource::DirectMixerSource(DirectAudioSource* direct_source, DirectMixerSource::DirectMixerSource(DirectAudioSource* direct_source,
const MediaPipelineDeviceParams& params, const MediaPipelineDeviceParams& params,
int playout_channel) int playout_channel)
......
...@@ -159,6 +159,8 @@ void MixerInput::SetVolumeMultiplier(float multiplier) { ...@@ -159,6 +159,8 @@ void MixerInput::SetVolumeMultiplier(float multiplier) {
void MixerInput::SetContentTypeVolume(float volume, int fade_ms) { void MixerInput::SetContentTypeVolume(float volume, int fade_ms) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(content_type_ != AudioContentType::kOther);
type_volume_multiplier_ = std::max(0.0f, std::min(volume, 1.0f)); type_volume_multiplier_ = std::max(0.0f, std::min(volume, 1.0f));
float target_volume = TargetVolume(); float target_volume = TargetVolume();
LOG(INFO) << device_id_ << "(" << source_ LOG(INFO) << device_id_ << "(" << source_
...@@ -175,6 +177,8 @@ void MixerInput::SetContentTypeVolume(float volume, int fade_ms) { ...@@ -175,6 +177,8 @@ void MixerInput::SetContentTypeVolume(float volume, int fade_ms) {
void MixerInput::SetMuted(bool muted) { void MixerInput::SetMuted(bool muted) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(content_type_ != AudioContentType::kOther);
mute_volume_multiplier_ = muted ? 0.0f : 1.0f; mute_volume_multiplier_ = muted ? 0.0f : 1.0f;
float target_volume = TargetVolume(); float target_volume = TargetVolume();
LOG(INFO) << device_id_ << "(" << source_ LOG(INFO) << device_id_ << "(" << source_
......
...@@ -219,6 +219,10 @@ StreamMixer::StreamMixer( ...@@ -219,6 +219,10 @@ StreamMixer::StreamMixer(
weak_factory_(this) { weak_factory_(this) {
VLOG(1) << __func__; VLOG(1) << __func__;
volume_info_[AudioContentType::kOther].volume = 1.0f;
volume_info_[AudioContentType::kOther].limit = 1.0f;
volume_info_[AudioContentType::kOther].muted = false;
if (mixer_thread_) { if (mixer_thread_) {
base::Thread::Options options; base::Thread::Options options;
options.priority = base::ThreadPriority::REALTIME_AUDIO; options.priority = base::ThreadPriority::REALTIME_AUDIO;
...@@ -547,6 +551,7 @@ void StreamMixer::AddInputOnThread(MixerInput::Source* input_source) { ...@@ -547,6 +551,7 @@ void StreamMixer::AddInputOnThread(MixerInput::Source* input_source) {
} }
auto type = input->content_type(); auto type = input->content_type();
if (type != AudioContentType::kOther) {
if (input->primary()) { if (input->primary()) {
input->SetContentTypeVolume(volume_info_[type].GetEffectiveVolume(), input->SetContentTypeVolume(volume_info_[type].GetEffectiveVolume(),
kUseDefaultFade); kUseDefaultFade);
...@@ -554,6 +559,7 @@ void StreamMixer::AddInputOnThread(MixerInput::Source* input_source) { ...@@ -554,6 +559,7 @@ void StreamMixer::AddInputOnThread(MixerInput::Source* input_source) {
input->SetContentTypeVolume(volume_info_[type].volume, kUseDefaultFade); input->SetContentTypeVolume(volume_info_[type].volume, kUseDefaultFade);
} }
input->SetMuted(volume_info_[type].muted); input->SetMuted(volume_info_[type].muted);
}
inputs_[input_source] = std::move(input); inputs_[input_source] = std::move(input);
UpdatePlayoutChannel(); UpdatePlayoutChannel();
...@@ -793,6 +799,8 @@ void StreamMixer::SetVolume(AudioContentType type, float level) { ...@@ -793,6 +799,8 @@ void StreamMixer::SetVolume(AudioContentType type, float level) {
void StreamMixer::SetVolumeOnThread(AudioContentType type, float level) { void StreamMixer::SetVolumeOnThread(AudioContentType type, float level) {
DCHECK(mixer_task_runner_->BelongsToCurrentThread()); DCHECK(mixer_task_runner_->BelongsToCurrentThread());
DCHECK(type != AudioContentType::kOther);
volume_info_[type].volume = level; volume_info_[type].volume = level;
float effective_volume = volume_info_[type].GetEffectiveVolume(); float effective_volume = volume_info_[type].GetEffectiveVolume();
for (const auto& input : inputs_) { for (const auto& input : inputs_) {
...@@ -816,6 +824,8 @@ void StreamMixer::SetMuted(AudioContentType type, bool muted) { ...@@ -816,6 +824,8 @@ void StreamMixer::SetMuted(AudioContentType type, bool muted) {
void StreamMixer::SetMutedOnThread(AudioContentType type, bool muted) { void StreamMixer::SetMutedOnThread(AudioContentType type, bool muted) {
DCHECK(mixer_task_runner_->BelongsToCurrentThread()); DCHECK(mixer_task_runner_->BelongsToCurrentThread());
DCHECK(type != AudioContentType::kOther);
volume_info_[type].muted = muted; volume_info_[type].muted = muted;
for (const auto& input : inputs_) { for (const auto& input : inputs_) {
if (input.second->content_type() == type) { if (input.second->content_type() == type) {
...@@ -833,6 +843,8 @@ void StreamMixer::SetOutputLimit(AudioContentType type, float limit) { ...@@ -833,6 +843,8 @@ void StreamMixer::SetOutputLimit(AudioContentType type, float limit) {
void StreamMixer::SetOutputLimitOnThread(AudioContentType type, float limit) { void StreamMixer::SetOutputLimitOnThread(AudioContentType type, float limit) {
DCHECK(mixer_task_runner_->BelongsToCurrentThread()); DCHECK(mixer_task_runner_->BelongsToCurrentThread());
DCHECK(type != AudioContentType::kOther);
LOG(INFO) << "Set volume limit for " << static_cast<int>(type) << " to " LOG(INFO) << "Set volume limit for " << static_cast<int>(type) << " to "
<< limit; << limit;
volume_info_[type].limit = limit; volume_info_[type].limit = limit;
......
...@@ -150,6 +150,11 @@ class VolumeControlInternal : public SystemVolumeControl::Delegate { ...@@ -150,6 +150,11 @@ class VolumeControlInternal : public SystemVolumeControl::Delegate {
} }
void SetVolume(AudioContentType type, float level) { void SetVolume(AudioContentType type, float level) {
if (type == AudioContentType::kOther) {
NOTREACHED() << "Can't set volume for content type kOther";
return;
}
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, base::BindOnce(&VolumeControlInternal::SetVolumeOnThread, FROM_HERE, base::BindOnce(&VolumeControlInternal::SetVolumeOnThread,
...@@ -163,6 +168,11 @@ class VolumeControlInternal : public SystemVolumeControl::Delegate { ...@@ -163,6 +168,11 @@ class VolumeControlInternal : public SystemVolumeControl::Delegate {
} }
void SetMuted(AudioContentType type, bool muted) { void SetMuted(AudioContentType type, bool muted) {
if (type == AudioContentType::kOther) {
NOTREACHED() << "Can't set mute state for content type kOther";
return;
}
thread_.task_runner()->PostTask( thread_.task_runner()->PostTask(
FROM_HERE, base::BindOnce(&VolumeControlInternal::SetMutedOnThread, FROM_HERE, base::BindOnce(&VolumeControlInternal::SetMutedOnThread,
base::Unretained(this), type, muted, base::Unretained(this), type, muted,
...@@ -170,6 +180,11 @@ class VolumeControlInternal : public SystemVolumeControl::Delegate { ...@@ -170,6 +180,11 @@ class VolumeControlInternal : public SystemVolumeControl::Delegate {
} }
void SetOutputLimit(AudioContentType type, float limit) { void SetOutputLimit(AudioContentType type, float limit) {
if (type == AudioContentType::kOther) {
NOTREACHED() << "Can't set output limit for content type kOther";
return;
}
if (BUILDFLAG(SYSTEM_OWNS_VOLUME)) { if (BUILDFLAG(SYSTEM_OWNS_VOLUME)) {
return; return;
} }
...@@ -219,12 +234,17 @@ class VolumeControlInternal : public SystemVolumeControl::Delegate { ...@@ -219,12 +234,17 @@ class VolumeControlInternal : public SystemVolumeControl::Delegate {
system_volume_control_->SetMuted(false); system_volume_control_->SetMuted(false);
} }
volumes_[AudioContentType::kOther] = 1.0;
muted_[AudioContentType::kOther] = false;
initialize_complete_event_.Signal(); initialize_complete_event_.Signal();
} }
void SetVolumeOnThread(AudioContentType type, float level, bool from_system) { void SetVolumeOnThread(AudioContentType type, float level, bool from_system) {
DCHECK(thread_.task_runner()->BelongsToCurrentThread()); DCHECK(thread_.task_runner()->BelongsToCurrentThread());
DCHECK(type != AudioContentType::kOther);
DCHECK(!from_system || type == AudioContentType::kMedia); DCHECK(!from_system || type == AudioContentType::kMedia);
{ {
base::AutoLock lock(volume_lock_); base::AutoLock lock(volume_lock_);
if (from_system && system_volume_control_->GetRoundtripVolume( if (from_system && system_volume_control_->GetRoundtripVolume(
...@@ -259,6 +279,8 @@ class VolumeControlInternal : public SystemVolumeControl::Delegate { ...@@ -259,6 +279,8 @@ class VolumeControlInternal : public SystemVolumeControl::Delegate {
void SetMutedOnThread(AudioContentType type, bool muted, bool from_system) { void SetMutedOnThread(AudioContentType type, bool muted, bool from_system) {
DCHECK(thread_.task_runner()->BelongsToCurrentThread()); DCHECK(thread_.task_runner()->BelongsToCurrentThread());
DCHECK(type != AudioContentType::kOther);
{ {
base::AutoLock lock(volume_lock_); base::AutoLock lock(volume_lock_);
if (muted == muted_[type]) { if (muted == muted_[type]) {
......
...@@ -151,6 +151,12 @@ class CHROMECAST_EXPORT CastMediaShlib { ...@@ -151,6 +151,12 @@ class CHROMECAST_EXPORT CastMediaShlib {
// AddDirectAudioSource(). // AddDirectAudioSource().
static void RemoveDirectAudioSource(DirectAudioSourceToken* token) static void RemoveDirectAudioSource(DirectAudioSourceToken* token)
__attribute__((__weak__)); __attribute__((__weak__));
// Sets the volume multiplier for a direct audio source, given the |token|
// that was returned by AddDirectAudioSource().
static void SetDirectAudioSourceVolume(DirectAudioSourceToken* token,
float multiplier)
__attribute__((__weak__));
}; };
} // namespace media } // namespace media
......
...@@ -20,11 +20,14 @@ enum class AudioContentType { ...@@ -20,11 +20,14 @@ enum class AudioContentType {
kMedia, // Normal audio playback; also used for system sound effects. kMedia, // Normal audio playback; also used for system sound effects.
kAlarm, // Alarm sounds. kAlarm, // Alarm sounds.
kCommunication, // Voice communication, eg assistant TTS. kCommunication, // Voice communication, eg assistant TTS.
kOther, // No content type volume control (only per-stream control).
}; };
// Observer for volume/mute state changes. This is useful to detect volume // Observer for volume/mute state changes. This is useful to detect volume
// changes that occur outside of cast_shell. Add/RemoveVolumeObserver() must not // changes that occur outside of cast_shell. Add/RemoveVolumeObserver() must not
// be called synchronously from OnVolumeChange() or OnMuteChange(). // be called synchronously from OnVolumeChange() or OnMuteChange(). Note that
// no volume/mute changes will occur for AudioContentType::kOther, so no
// observer methods will be called with that type.
class VolumeObserver { class VolumeObserver {
public: public:
// Called whenever the volume changes for a given stream |type|. May be called // Called whenever the volume changes for a given stream |type|. May be called
...@@ -64,12 +67,14 @@ class CHROMECAST_EXPORT VolumeControl { ...@@ -64,12 +67,14 @@ class CHROMECAST_EXPORT VolumeControl {
__attribute__((__weak__)); __attribute__((__weak__));
// Gets/sets the output volume for a given audio stream |type|. The volume // Gets/sets the output volume for a given audio stream |type|. The volume
// |level| is in the range [0.0, 1.0]. // |level| is in the range [0.0, 1.0]. AudioContentType::kOther is not a valid
// |type| for these methods.
static float GetVolume(AudioContentType type) __attribute__((__weak__)); static float GetVolume(AudioContentType type) __attribute__((__weak__));
static void SetVolume(AudioContentType type, float level) static void SetVolume(AudioContentType type, float level)
__attribute__((__weak__)); __attribute__((__weak__));
// Gets/sets the mute state for a given audio stream |type|. // Gets/sets the mute state for a given audio stream |type|.
// AudioContentType::kOther is not a valid |type| for these methods.
static bool IsMuted(AudioContentType type) __attribute__((__weak__)); static bool IsMuted(AudioContentType type) __attribute__((__weak__));
static void SetMuted(AudioContentType type, bool muted) static void SetMuted(AudioContentType type, bool muted)
__attribute__((__weak__)); __attribute__((__weak__));
...@@ -77,7 +82,8 @@ class CHROMECAST_EXPORT VolumeControl { ...@@ -77,7 +82,8 @@ class CHROMECAST_EXPORT VolumeControl {
// Limits the output volume for a given stream |type| to no more than |limit|. // Limits the output volume for a given stream |type| to no more than |limit|.
// This does not affect the logical volume for the stream type; the volume // This does not affect the logical volume for the stream type; the volume
// returned by GetVolume() should not change, and no OnVolumeChange() event // returned by GetVolume() should not change, and no OnVolumeChange() event
// should be sent to observers. // should be sent to observers. AudioContentType::kOther is not a valid |type|
// for this method.
static void SetOutputLimit(AudioContentType type, float limit) static void SetOutputLimit(AudioContentType type, float limit)
__attribute__((__weak__)); __attribute__((__weak__));
......
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