mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 21:31:04 +00:00
Bug 876334 - Gecko should use AudioChannelType to control volume not stream types. r=mwu, r=baku
This commit is contained in:
parent
2d516da9c1
commit
cb96a38404
@ -62,35 +62,6 @@ var SettingsListener = {
|
||||
|
||||
SettingsListener.init();
|
||||
|
||||
// =================== Audio ====================
|
||||
let audioChannelSettings = [];
|
||||
|
||||
if ("nsIAudioManager" in Ci) {
|
||||
const nsIAudioManager = Ci.nsIAudioManager;
|
||||
audioChannelSettings = [
|
||||
// settings name, max value, apply to stream types
|
||||
['audio.volume.content', 15, [nsIAudioManager.STREAM_TYPE_SYSTEM, nsIAudioManager.STREAM_TYPE_MUSIC]],
|
||||
['audio.volume.notification', 15, [nsIAudioManager.STREAM_TYPE_RING, nsIAudioManager.STREAM_TYPE_NOTIFICATION]],
|
||||
['audio.volume.alarm', 15, [nsIAudioManager.STREAM_TYPE_ALARM]],
|
||||
['audio.volume.telephony', 5, [nsIAudioManager.STREAM_TYPE_VOICE_CALL]],
|
||||
['audio.volume.bt_sco', 15, [nsIAudioManager.STREAM_TYPE_BLUETOOTH_SCO]],
|
||||
];
|
||||
}
|
||||
|
||||
for each (let [setting, maxValue, streamTypes] in audioChannelSettings) {
|
||||
(function AudioStreamSettings(setting, maxValue, streamTypes) {
|
||||
SettingsListener.observe(setting, maxValue, function(value) {
|
||||
let audioManager = Services.audioManager;
|
||||
if (!audioManager)
|
||||
return;
|
||||
|
||||
for each(let streamType in streamTypes) {
|
||||
audioManager.setStreamVolumeIndex(streamType, Math.min(value, maxValue));
|
||||
}
|
||||
});
|
||||
})(setting, maxValue, streamTypes);
|
||||
}
|
||||
|
||||
// =================== Console ======================
|
||||
|
||||
SettingsListener.observe('debug.console.enabled', true, function(value) {
|
||||
|
@ -20,8 +20,12 @@
|
||||
#include "nsHashPropertyBag.h"
|
||||
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
#include "nsJSUtils.h"
|
||||
#include "nsCxPusher.h"
|
||||
#include "nsIAudioManager.h"
|
||||
#define NS_AUDIOMANAGER_CONTRACTID "@mozilla.org/telephony/audiomanager;1"
|
||||
#endif
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
using namespace mozilla::hal;
|
||||
@ -77,6 +81,10 @@ AudioChannelService::AudioChannelService()
|
||||
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
|
||||
if (obs) {
|
||||
obs->AddObserver(this, "ipc:content-shutdown", false);
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
// To monitor the volume settings based on audio channel.
|
||||
obs->AddObserver(this, "mozsettings-changed", false);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -484,41 +492,91 @@ AudioChannelService::ChannelName(AudioChannelType aType)
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
AudioChannelService::Observe(nsISupports* aSubject, const char* aTopic, const PRUnichar* data)
|
||||
AudioChannelService::Observe(nsISupports* aSubject, const char* aTopic, const PRUnichar* aData)
|
||||
{
|
||||
MOZ_ASSERT(!strcmp(aTopic, "ipc:content-shutdown"));
|
||||
|
||||
nsCOMPtr<nsIPropertyBag2> props = do_QueryInterface(aSubject);
|
||||
if (!props) {
|
||||
NS_WARNING("ipc:content-shutdown message without property bag as subject");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
uint64_t childID = 0;
|
||||
nsresult rv = props->GetPropertyAsUint64(NS_LITERAL_STRING("childID"),
|
||||
&childID);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
for (int32_t type = AUDIO_CHANNEL_INT_NORMAL;
|
||||
type < AUDIO_CHANNEL_INT_LAST;
|
||||
++type) {
|
||||
int32_t index;
|
||||
while ((index = mChannelCounters[type].IndexOf(childID)) != -1) {
|
||||
mChannelCounters[type].RemoveElementAt(index);
|
||||
}
|
||||
|
||||
if ((index = mActiveContentChildIDs.IndexOf(childID)) != -1) {
|
||||
mActiveContentChildIDs.RemoveElementAt(index);
|
||||
}
|
||||
if (!strcmp(aTopic, "ipc:content-shutdown")) {
|
||||
nsCOMPtr<nsIPropertyBag2> props = do_QueryInterface(aSubject);
|
||||
if (!props) {
|
||||
NS_WARNING("ipc:content-shutdown message without property bag as subject");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// We don't have to remove the agents from the mAgents hashtable because if
|
||||
// that table contains only agents running on the same process.
|
||||
uint64_t childID = 0;
|
||||
nsresult rv = props->GetPropertyAsUint64(NS_LITERAL_STRING("childID"),
|
||||
&childID);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
for (int32_t type = AUDIO_CHANNEL_INT_NORMAL;
|
||||
type < AUDIO_CHANNEL_INT_LAST;
|
||||
++type) {
|
||||
int32_t index;
|
||||
while ((index = mChannelCounters[type].IndexOf(childID)) != -1) {
|
||||
mChannelCounters[type].RemoveElementAt(index);
|
||||
}
|
||||
|
||||
SendAudioChannelChangedNotification(childID);
|
||||
Notify();
|
||||
} else {
|
||||
NS_WARNING("ipc:content-shutdown message without childID property");
|
||||
if ((index = mActiveContentChildIDs.IndexOf(childID)) != -1) {
|
||||
mActiveContentChildIDs.RemoveElementAt(index);
|
||||
}
|
||||
}
|
||||
|
||||
// We don't have to remove the agents from the mAgents hashtable because if
|
||||
// that table contains only agents running on the same process.
|
||||
|
||||
SendAudioChannelChangedNotification(childID);
|
||||
Notify();
|
||||
} else {
|
||||
NS_WARNING("ipc:content-shutdown message without childID property");
|
||||
}
|
||||
}
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
// To process the volume control on each audio channel according to
|
||||
// change of settings
|
||||
else if (!strcmp(aTopic, "mozsettings-changed")) {
|
||||
AutoSafeJSContext cx;
|
||||
nsDependentString dataStr(aData);
|
||||
JS::Rooted<JS::Value> val(cx);
|
||||
if (!JS_ParseJSON(cx, dataStr.get(), dataStr.Length(), &val) ||
|
||||
!val.isObject()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
JS::Rooted<JSObject*> obj(cx, &val.toObject());
|
||||
JS::Rooted<JS::Value> key(cx);
|
||||
if (!JS_GetProperty(cx, obj, "key", key.address()) ||
|
||||
!key.isString()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
JS::RootedString jsKey(cx, JS_ValueToString(cx, key));
|
||||
if (!jsKey) {
|
||||
return NS_OK;
|
||||
}
|
||||
nsDependentJSString keyStr;
|
||||
if (!keyStr.init(cx, jsKey) || keyStr.Find("audio.volume.", 0, false)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
JS::Rooted<JS::Value> value(cx);
|
||||
if (!JS_GetProperty(cx, obj, "value", value.address()) || !value.isInt32()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIAudioManager> audioManager = do_GetService(NS_AUDIOMANAGER_CONTRACTID);
|
||||
NS_ENSURE_TRUE(audioManager, NS_OK);
|
||||
|
||||
int32_t index = value.toInt32();
|
||||
if (keyStr.EqualsLiteral("audio.volume.content")) {
|
||||
audioManager->SetAudioChannelVolume(AUDIO_CHANNEL_CONTENT, index);
|
||||
} else if (keyStr.EqualsLiteral("audio.volume.notification")) {
|
||||
audioManager->SetAudioChannelVolume(AUDIO_CHANNEL_NOTIFICATION, index);
|
||||
} else if (keyStr.EqualsLiteral("audio.volume.alarm")) {
|
||||
audioManager->SetAudioChannelVolume(AUDIO_CHANNEL_ALARM, index);
|
||||
} else if (keyStr.EqualsLiteral("audio.volume.telephony")) {
|
||||
audioManager->SetAudioChannelVolume(AUDIO_CHANNEL_TELEPHONY, index);
|
||||
} else {
|
||||
MOZ_ASSERT("unexpected audio channel for volume control");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -258,16 +258,7 @@ NS_IMETHODIMP FMRadio::CanPlayChanged(bool canPlay)
|
||||
}
|
||||
|
||||
/* mute fm first, it should be better to stop&resume fm */
|
||||
if (canPlay) {
|
||||
audioManager->SetFmRadioAudioEnabled(true);
|
||||
int32_t volIdx = 0;
|
||||
// Restore fm volume, that value is sync as music type
|
||||
audioManager->GetStreamVolumeIndex(nsIAudioManager::STREAM_TYPE_MUSIC, &volIdx);
|
||||
audioManager->SetStreamVolumeIndex(nsIAudioManager::STREAM_TYPE_FM, volIdx);
|
||||
} else {
|
||||
audioManager->SetStreamVolumeIndex(nsIAudioManager::STREAM_TYPE_FM, 0);
|
||||
audioManager->SetFmRadioAudioEnabled(false);
|
||||
}
|
||||
audioManager->SetFmRadioAudioEnabled(canPlay);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -28,6 +28,9 @@
|
||||
#include "BluetoothCommon.h"
|
||||
#include "BluetoothProfileManagerBase.h"
|
||||
|
||||
#include "nsJSUtils.h"
|
||||
#include "nsCxPusher.h"
|
||||
|
||||
using namespace mozilla::dom::gonk;
|
||||
using namespace android;
|
||||
using namespace mozilla::hal;
|
||||
@ -63,21 +66,25 @@ static int sHeadsetState;
|
||||
static const int kBtSampleRate = 8000;
|
||||
static bool sSwitchDone = true;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
namespace gonk {
|
||||
class RecoverTask : public nsRunnable
|
||||
{
|
||||
public:
|
||||
RecoverTask() {}
|
||||
NS_IMETHODIMP Run() {
|
||||
nsCOMPtr<nsIAudioManager> am = do_GetService(NS_AUDIOMANAGER_CONTRACTID);
|
||||
NS_ENSURE_TRUE(am, NS_OK);
|
||||
for (int i = 0; i < AUDIO_STREAM_CNT; i++) {
|
||||
AudioSystem::initStreamVolume(static_cast<audio_stream_type_t>(i), 0,
|
||||
sMaxStreamVolumeTbl[i]);
|
||||
int32_t volidx = 0;
|
||||
am->GetStreamVolumeIndex(i, &volidx);
|
||||
am->SetStreamVolumeIndex(static_cast<audio_stream_type_t>(i),
|
||||
volidx);
|
||||
nsCOMPtr<nsIAudioManager> amService = do_GetService(NS_AUDIOMANAGER_CONTRACTID);
|
||||
NS_ENSURE_TRUE(amService, NS_OK);
|
||||
AudioManager *am = static_cast<AudioManager *>(amService.get());
|
||||
for (int loop = 0; loop < AUDIO_STREAM_CNT; loop++) {
|
||||
AudioSystem::initStreamVolume(static_cast<audio_stream_type_t>(loop), 0,
|
||||
sMaxStreamVolumeTbl[loop]);
|
||||
int32_t index;
|
||||
am->GetStreamVolumeIndex(loop, &index);
|
||||
am->SetStreamVolumeIndex(loop, index);
|
||||
}
|
||||
|
||||
if (sHeadsetState & AUDIO_DEVICE_OUT_WIRED_HEADSET)
|
||||
InternalSetAudioRoutes(SWITCH_STATE_HEADSET);
|
||||
else if (sHeadsetState & AUDIO_DEVICE_OUT_WIRED_HEADPHONE)
|
||||
@ -97,6 +104,9 @@ public:
|
||||
return NS_OK;
|
||||
}
|
||||
};
|
||||
} /* namespace gonk */
|
||||
} /* namespace dom */
|
||||
} /* namespace mozilla */
|
||||
|
||||
static void
|
||||
BinderDeadCallback(status_t aErr)
|
||||
@ -242,12 +252,47 @@ AudioManager::Observe(nsISupports* aSubject,
|
||||
AudioSystem::setParameters(0, cmd);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
NS_WARNING("Unexpected topic in AudioManager");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
// To process the volume control on each audio channel according to
|
||||
// change of settings
|
||||
else if (!strcmp(aTopic, "mozsettings-changed")) {
|
||||
AutoSafeJSContext cx;
|
||||
nsDependentString dataStr(aData);
|
||||
JS::Rooted<JS::Value> val(cx);
|
||||
if (!JS_ParseJSON(cx, dataStr.get(), dataStr.Length(), &val) ||
|
||||
!val.isObject()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
JS::Rooted<JSObject*> obj(cx, &val.toObject());
|
||||
JS::Rooted<JS::Value> key(cx);
|
||||
if (!JS_GetProperty(cx, obj, "key", key.address()) ||
|
||||
!key.isString()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
JS::RootedString jsKey(cx, JS_ValueToString(cx, key));
|
||||
if (!jsKey) {
|
||||
return NS_OK;
|
||||
}
|
||||
nsDependentJSString keyStr;
|
||||
if (!keyStr.init(cx, jsKey) || keyStr.EqualsLiteral("audio.volume.bt_sco")) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
JS::Rooted<JS::Value> value(cx);
|
||||
if (!JS_GetProperty(cx, obj, "value", value.address()) || !value.isInt32()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
int32_t index = value.toInt32();
|
||||
SetStreamVolumeIndex(AUDIO_STREAM_BLUETOOTH_SCO, index);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
NS_WARNING("Unexpected topic in AudioManager");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -300,6 +345,9 @@ AudioManager::AudioManager() : mPhoneState(PHONE_STATE_CURRENT),
|
||||
if (NS_FAILED(obs->AddObserver(this, BLUETOOTH_A2DP_STATUS_CHANGED_ID, false))) {
|
||||
NS_WARNING("Failed to add bluetooth a2dp status changed observer!");
|
||||
}
|
||||
if (NS_FAILED(obs->AddObserver(this, "mozsettings-changed", false))) {
|
||||
NS_WARNING("Failed to add mozsettings-changed oberver!");
|
||||
}
|
||||
|
||||
for (int loop = 0; loop < AUDIO_STREAM_CNT; loop++) {
|
||||
AudioSystem::initStreamVolume(static_cast<audio_stream_type_t>(loop), 0,
|
||||
@ -307,20 +355,12 @@ AudioManager::AudioManager() : mPhoneState(PHONE_STATE_CURRENT),
|
||||
mCurrentStreamVolumeTbl[loop] = sMaxStreamVolumeTbl[loop];
|
||||
}
|
||||
// Force publicnotification to output at maximal volume
|
||||
#if ANDROID_VERSION < 17
|
||||
AudioSystem::setStreamVolumeIndex(
|
||||
static_cast<audio_stream_type_t>(AUDIO_STREAM_ENFORCED_AUDIBLE),
|
||||
sMaxStreamVolumeTbl[AUDIO_STREAM_ENFORCED_AUDIBLE]);
|
||||
#else
|
||||
AudioSystem::setStreamVolumeIndex(
|
||||
static_cast<audio_stream_type_t>(AUDIO_STREAM_ENFORCED_AUDIBLE),
|
||||
sMaxStreamVolumeTbl[AUDIO_STREAM_ENFORCED_AUDIBLE],
|
||||
AUDIO_DEVICE_OUT_SPEAKER);
|
||||
#endif
|
||||
|
||||
SetStreamVolumeIndex(AUDIO_STREAM_ENFORCED_AUDIBLE,
|
||||
sMaxStreamVolumeTbl[AUDIO_STREAM_ENFORCED_AUDIBLE]);
|
||||
// Gecko only control stream volume not master so set to default value
|
||||
// directly.
|
||||
AudioSystem::setMasterVolume(1.0);
|
||||
|
||||
AudioSystem::setErrorCallback(BinderDeadCallback);
|
||||
}
|
||||
|
||||
@ -467,24 +507,8 @@ AudioManager::SetFmRadioAudioEnabled(bool aFmRadioAudioEnabled)
|
||||
InternalSetAudioRoutes(GetCurrentSwitchState(SWITCH_HEADPHONES));
|
||||
// sync volume with music after powering on fm radio
|
||||
if (aFmRadioAudioEnabled) {
|
||||
int32_t volIndex = 0;
|
||||
#if ANDROID_VERSION < 17
|
||||
AudioSystem::getStreamVolumeIndex(
|
||||
static_cast<audio_stream_type_t>(AUDIO_STREAM_MUSIC),
|
||||
&volIndex);
|
||||
AudioSystem::setStreamVolumeIndex(
|
||||
static_cast<audio_stream_type_t>(AUDIO_STREAM_FM),
|
||||
volIndex);
|
||||
#else
|
||||
AudioSystem::getStreamVolumeIndex(
|
||||
static_cast<audio_stream_type_t>(AUDIO_STREAM_MUSIC),
|
||||
&volIndex,
|
||||
AUDIO_DEVICE_OUT_DEFAULT);
|
||||
AudioSystem::setStreamVolumeIndex(
|
||||
static_cast<audio_stream_type_t>(AUDIO_STREAM_FM),
|
||||
volIndex,
|
||||
AUDIO_DEVICE_OUT_SPEAKER);
|
||||
#endif
|
||||
int32_t volIndex = mCurrentStreamVolumeTbl[AUDIO_STREAM_MUSIC];
|
||||
SetStreamVolumeIndex(AUDIO_STREAM_FM, volIndex);
|
||||
mCurrentStreamVolumeTbl[AUDIO_STREAM_FM] = volIndex;
|
||||
}
|
||||
return NS_OK;
|
||||
@ -494,48 +518,155 @@ AudioManager::SetFmRadioAudioEnabled(bool aFmRadioAudioEnabled)
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
AudioManager::SetStreamVolumeIndex(int32_t aStream, int32_t aIndex) {
|
||||
#if ANDROID_VERSION < 17
|
||||
status_t status =
|
||||
AudioSystem::setStreamVolumeIndex(
|
||||
static_cast<audio_stream_type_t>(aStream),
|
||||
aIndex);
|
||||
#else
|
||||
status_t status =
|
||||
AudioSystem::setStreamVolumeIndex(
|
||||
static_cast<audio_stream_type_t>(aStream),
|
||||
aIndex,
|
||||
AUDIO_DEVICE_OUT_SPEAKER);
|
||||
#endif
|
||||
AudioManager::SetAudioChannelVolume(int32_t aChannel, int32_t aIndex) {
|
||||
status_t status;
|
||||
|
||||
// sync fm volume with music stream type
|
||||
if (aStream == AUDIO_STREAM_MUSIC && IsDeviceOn(AUDIO_DEVICE_OUT_FM)) {
|
||||
#if ANDROID_VERSION < 17
|
||||
AudioSystem::setStreamVolumeIndex(
|
||||
static_cast<audio_stream_type_t>(AUDIO_STREAM_FM),
|
||||
aIndex);
|
||||
#else
|
||||
AudioSystem::setStreamVolumeIndex(
|
||||
static_cast<audio_stream_type_t>(AUDIO_STREAM_FM),
|
||||
aIndex,
|
||||
AUDIO_DEVICE_OUT_SPEAKER);
|
||||
#endif
|
||||
mCurrentStreamVolumeTbl[AUDIO_STREAM_FM] = aIndex;
|
||||
switch (aChannel) {
|
||||
case AUDIO_CHANNEL_CONTENT:
|
||||
status = SetStreamVolumeIndex(AUDIO_STREAM_MUSIC, aIndex);
|
||||
status += SetStreamVolumeIndex(AUDIO_STREAM_SYSTEM, aIndex);
|
||||
// sync FMRadio's volume with content channel.
|
||||
if (IsDeviceOn(AUDIO_DEVICE_OUT_FM)) {
|
||||
status += SetStreamVolumeIndex(AUDIO_STREAM_FM, aIndex);
|
||||
}
|
||||
break;
|
||||
case AUDIO_CHANNEL_NOTIFICATION:
|
||||
status = SetStreamVolumeIndex(AUDIO_STREAM_NOTIFICATION, aIndex);
|
||||
status += SetStreamVolumeIndex(AUDIO_STREAM_RING, aIndex);
|
||||
break;
|
||||
case AUDIO_CHANNEL_ALARM:
|
||||
status = SetStreamVolumeIndex(AUDIO_STREAM_ALARM, aIndex);
|
||||
break;
|
||||
case AUDIO_CHANNEL_TELEPHONY:
|
||||
status = SetStreamVolumeIndex(AUDIO_STREAM_VOICE_CALL, aIndex);
|
||||
break;
|
||||
default:
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
mCurrentStreamVolumeTbl[aStream] = aIndex;
|
||||
|
||||
return status ? NS_ERROR_FAILURE : NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
AudioManager::GetStreamVolumeIndex(int32_t aStream, int32_t* aIndex) {
|
||||
*aIndex = mCurrentStreamVolumeTbl[aStream];
|
||||
AudioManager::GetAudioChannelVolume(int32_t aChannel, int32_t* aIndex) {
|
||||
if (!aIndex) {
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
|
||||
switch (aChannel) {
|
||||
case AUDIO_CHANNEL_CONTENT:
|
||||
MOZ_ASSERT(mCurrentStreamVolumeTbl[AUDIO_STREAM_MUSIC] ==
|
||||
mCurrentStreamVolumeTbl[AUDIO_STREAM_SYSTEM]);
|
||||
*aIndex = mCurrentStreamVolumeTbl[AUDIO_STREAM_MUSIC];
|
||||
break;
|
||||
case AUDIO_CHANNEL_NOTIFICATION:
|
||||
MOZ_ASSERT(mCurrentStreamVolumeTbl[AUDIO_STREAM_NOTIFICATION] ==
|
||||
mCurrentStreamVolumeTbl[AUDIO_STREAM_RING]);
|
||||
*aIndex = mCurrentStreamVolumeTbl[AUDIO_STREAM_NOTIFICATION];
|
||||
break;
|
||||
case AUDIO_CHANNEL_ALARM:
|
||||
*aIndex = mCurrentStreamVolumeTbl[AUDIO_STREAM_ALARM];
|
||||
break;
|
||||
case AUDIO_CHANNEL_TELEPHONY:
|
||||
*aIndex = mCurrentStreamVolumeTbl[AUDIO_STREAM_VOICE_CALL];
|
||||
break;
|
||||
default:
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
AudioManager::GetMaxStreamVolumeIndex(int32_t aStream, int32_t* aMaxIndex) {
|
||||
*aMaxIndex = sMaxStreamVolumeTbl[aStream];
|
||||
return NS_OK;
|
||||
AudioManager::GetMaxAudioChannelVolume(int32_t aChannel, int32_t* aMaxIndex) {
|
||||
if (!aMaxIndex) {
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
|
||||
int32_t stream;
|
||||
switch (aChannel) {
|
||||
case AUDIO_CHANNEL_CONTENT:
|
||||
MOZ_ASSERT(sMaxStreamVolumeTbl[AUDIO_STREAM_MUSIC] ==
|
||||
sMaxStreamVolumeTbl[AUDIO_STREAM_SYSTEM]);
|
||||
stream = AUDIO_STREAM_MUSIC;
|
||||
break;
|
||||
case AUDIO_CHANNEL_NOTIFICATION:
|
||||
MOZ_ASSERT(sMaxStreamVolumeTbl[AUDIO_STREAM_NOTIFICATION] ==
|
||||
sMaxStreamVolumeTbl[AUDIO_STREAM_RING]);
|
||||
stream = AUDIO_STREAM_NOTIFICATION;
|
||||
break;
|
||||
case AUDIO_CHANNEL_ALARM:
|
||||
stream = AUDIO_STREAM_ALARM;
|
||||
break;
|
||||
case AUDIO_CHANNEL_TELEPHONY:
|
||||
stream = AUDIO_STREAM_VOICE_CALL;
|
||||
break;
|
||||
default:
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
*aMaxIndex = sMaxStreamVolumeTbl[stream];
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
status_t
|
||||
AudioManager::SetStreamVolumeIndex(int32_t aStream, int32_t aIndex) {
|
||||
if (aIndex < 0 || aIndex > sMaxStreamVolumeTbl[aStream]) {
|
||||
return BAD_VALUE;
|
||||
}
|
||||
|
||||
mCurrentStreamVolumeTbl[aStream] = aIndex;
|
||||
#if ANDROID_VERSION < 17
|
||||
return AudioSystem::setStreamVolumeIndex(
|
||||
static_cast<audio_stream_type_t>(aStream),
|
||||
aIndex);
|
||||
#else
|
||||
int device = 0;
|
||||
|
||||
if (aStream == AUDIO_STREAM_BLUETOOTH_SCO) {
|
||||
device = AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET;
|
||||
} else if (aStream == AUDIO_STREAM_FM) {
|
||||
device = AUDIO_DEVICE_OUT_FM;
|
||||
}
|
||||
|
||||
if (device != 0) {
|
||||
return AudioSystem::setStreamVolumeIndex(
|
||||
static_cast<audio_stream_type_t>(aStream),
|
||||
aIndex,
|
||||
device);
|
||||
}
|
||||
|
||||
status_t status = AudioSystem::setStreamVolumeIndex(
|
||||
static_cast<audio_stream_type_t>(aStream),
|
||||
aIndex,
|
||||
AUDIO_DEVICE_OUT_SPEAKER);
|
||||
status += AudioSystem::setStreamVolumeIndex(
|
||||
static_cast<audio_stream_type_t>(aStream),
|
||||
aIndex,
|
||||
AUDIO_DEVICE_OUT_WIRED_HEADSET);
|
||||
status += AudioSystem::setStreamVolumeIndex(
|
||||
static_cast<audio_stream_type_t>(aStream),
|
||||
aIndex,
|
||||
AUDIO_DEVICE_OUT_WIRED_HEADPHONE);
|
||||
status += AudioSystem::setStreamVolumeIndex(
|
||||
static_cast<audio_stream_type_t>(aStream),
|
||||
aIndex,
|
||||
AUDIO_DEVICE_OUT_EARPIECE);
|
||||
return status;
|
||||
#endif
|
||||
}
|
||||
|
||||
status_t
|
||||
AudioManager::GetStreamVolumeIndex(int32_t aStream, int32_t *aIndex) {
|
||||
if (!aIndex) {
|
||||
return BAD_VALUE;
|
||||
}
|
||||
|
||||
if (aStream <= AUDIO_STREAM_DEFAULT || aStream >= AUDIO_STREAM_MAX) {
|
||||
return BAD_VALUE;
|
||||
}
|
||||
|
||||
*aIndex = mCurrentStreamVolumeTbl[aStream];
|
||||
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
@ -38,7 +38,7 @@ typedef Observer<SwitchEvent> SwitchObserver;
|
||||
|
||||
namespace dom {
|
||||
namespace gonk {
|
||||
|
||||
class RecoverTask;
|
||||
class AudioManager : public nsIAudioManager
|
||||
, public nsIObserver
|
||||
{
|
||||
@ -50,10 +50,17 @@ public:
|
||||
AudioManager();
|
||||
~AudioManager();
|
||||
|
||||
// When audio backend is dead, recovery task needs to read all volume
|
||||
// settings then set back into audio backend.
|
||||
friend class RecoverTask;
|
||||
|
||||
protected:
|
||||
int32_t mPhoneState;
|
||||
int mCurrentStreamVolumeTbl[AUDIO_STREAM_CNT];
|
||||
|
||||
android::status_t SetStreamVolumeIndex(int32_t aStream, int32_t aIndex);
|
||||
android::status_t GetStreamVolumeIndex(int32_t aStream, int32_t *aIndex);
|
||||
|
||||
private:
|
||||
nsAutoPtr<mozilla::hal::SwitchObserver> mObserver;
|
||||
nsCOMPtr<AudioChannelAgent> mPhoneAudioAgent;
|
||||
|
@ -50,22 +50,8 @@ interface nsIAudioManager : nsISupports
|
||||
void setForceForUse(in long usage, in long force);
|
||||
long getForceForUse(in long usage);
|
||||
|
||||
/**
|
||||
* Control the volume of various audio streams
|
||||
*/
|
||||
const long STREAM_TYPE_VOICE_CALL = 0;
|
||||
const long STREAM_TYPE_SYSTEM = 1;
|
||||
const long STREAM_TYPE_RING = 2;
|
||||
const long STREAM_TYPE_MUSIC = 3;
|
||||
const long STREAM_TYPE_ALARM = 4;
|
||||
const long STREAM_TYPE_NOTIFICATION = 5;
|
||||
const long STREAM_TYPE_BLUETOOTH_SCO = 6;
|
||||
const long STREAM_TYPE_ENFORCED_AUDIBLE = 7;
|
||||
const long STREAM_TYPE_DTMF = 8;
|
||||
const long STREAM_TYPE_TTS = 9;
|
||||
const long STREAM_TYPE_FM = 10;
|
||||
|
||||
void setStreamVolumeIndex(in long stream, in long index);
|
||||
long getStreamVolumeIndex(in long stream);
|
||||
long getMaxStreamVolumeIndex(in long stream);
|
||||
/* The range of volume index is from 0 to N. Ex: 0 ~ 15 */
|
||||
void setAudioChannelVolume(in long channel, in long index);
|
||||
long getAudioChannelVolume(in long channel);
|
||||
long getMaxAudioChannelVolume(in long channel);
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user