mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-27 23:02:20 +00:00
Bug 864327 - Support FM RDS in WebAPI, r=ehsan,pzhang,khuey
This commit is contained in:
parent
846b6645bf
commit
cfe3595579
@ -796,6 +796,7 @@ GK_ATOM(onMozMousePixelScroll, "onMozMousePixelScroll")
|
||||
GK_ATOM(onMozScrolledAreaChanged, "onMozScrolledAreaChanged")
|
||||
GK_ATOM(onmoznetworkupload, "onmoznetworkupload")
|
||||
GK_ATOM(onmoznetworkdownload, "onmoznetworkdownload")
|
||||
GK_ATOM(onnewrdsgroup, "onnewrdsgroup")
|
||||
GK_ATOM(onnoupdate, "onnoupdate")
|
||||
GK_ATOM(onobsolete, "onobsolete")
|
||||
GK_ATOM(ononline, "ononline")
|
||||
@ -812,11 +813,16 @@ GK_ATOM(onpairingconfirmationreq, "onpairingconfirmationreq")
|
||||
GK_ATOM(onpairingconsentreq, "onpairingconsentreq")
|
||||
GK_ATOM(onpaste, "onpaste")
|
||||
GK_ATOM(onpendingchange, "onpendingchange")
|
||||
GK_ATOM(onpichange, "onpichange")
|
||||
GK_ATOM(onpopuphidden, "onpopuphidden")
|
||||
GK_ATOM(onpopuphiding, "onpopuphiding")
|
||||
GK_ATOM(onpopupshowing, "onpopupshowing")
|
||||
GK_ATOM(onpopupshown, "onpopupshown")
|
||||
GK_ATOM(onpschange, "onpschange")
|
||||
GK_ATOM(onptychange, "onptychange")
|
||||
GK_ATOM(onradiostatechange, "onradiostatechange")
|
||||
GK_ATOM(onrdsdisabled, "onrdsdisabled")
|
||||
GK_ATOM(onrdsenabled, "onrdsenabled")
|
||||
GK_ATOM(onreaderror, "onreaderror")
|
||||
GK_ATOM(onreadsuccess, "onreadsuccess")
|
||||
GK_ATOM(onready, "onready")
|
||||
@ -831,6 +837,7 @@ GK_ATOM(onrequestmediaplaystatus, "onrequestmediaplaystatus")
|
||||
GK_ATOM(onreset, "onreset")
|
||||
GK_ATOM(onresuming, "onresuming")
|
||||
GK_ATOM(onresize, "onresize")
|
||||
GK_ATOM(onrtchange, "onrtchange")
|
||||
GK_ATOM(onscostatuschanged, "onscostatuschanged")
|
||||
GK_ATOM(onscroll, "onscroll")
|
||||
GK_ATOM(onselect, "onselect")
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "mozilla/dom/ContentChild.h"
|
||||
#include "mozilla/dom/PFMRadioChild.h"
|
||||
#include "mozilla/dom/FMRadioService.h"
|
||||
#include "mozilla/dom/TypedArray.h"
|
||||
#include "DOMRequest.h"
|
||||
#include "nsDOMClassInfo.h"
|
||||
#include "nsIDocShell.h"
|
||||
@ -105,6 +106,7 @@ NS_IMPL_ISUPPORTS_INHERITED0(FMRadioRequest, DOMRequest)
|
||||
|
||||
FMRadio::FMRadio()
|
||||
: mHeadphoneState(SWITCH_STATE_OFF)
|
||||
, mRdsGroupMask(0)
|
||||
, mAudioChannelAgentEnabled(false)
|
||||
, mHasInternalAntenna(false)
|
||||
, mIsShutdown(false)
|
||||
@ -220,6 +222,28 @@ FMRadio::Notify(const FMRadioEventType& aType)
|
||||
DispatchTrustedEvent(NS_LITERAL_STRING("disabled"));
|
||||
}
|
||||
break;
|
||||
case RDSEnabledChanged:
|
||||
if (RdsEnabled()) {
|
||||
DispatchTrustedEvent(NS_LITERAL_STRING("rdsenabled"));
|
||||
} else {
|
||||
DispatchTrustedEvent(NS_LITERAL_STRING("rdsdisabled"));
|
||||
}
|
||||
break;
|
||||
case PIChanged:
|
||||
DispatchTrustedEvent(NS_LITERAL_STRING("pichange"));
|
||||
break;
|
||||
case PSChanged:
|
||||
DispatchTrustedEvent(NS_LITERAL_STRING("pschange"));
|
||||
break;
|
||||
case RadiotextChanged:
|
||||
DispatchTrustedEvent(NS_LITERAL_STRING("rtchange"));
|
||||
break;
|
||||
case PTYChanged:
|
||||
DispatchTrustedEvent(NS_LITERAL_STRING("ptychange"));
|
||||
break;
|
||||
case NewRDSGroup:
|
||||
DispatchTrustedEvent(NS_LITERAL_STRING("newrdsgroup"));
|
||||
break;
|
||||
default:
|
||||
MOZ_CRASH();
|
||||
}
|
||||
@ -232,6 +256,12 @@ FMRadio::Enabled()
|
||||
return IFMRadioService::Singleton()->IsEnabled();
|
||||
}
|
||||
|
||||
bool
|
||||
FMRadio::RdsEnabled()
|
||||
{
|
||||
return IFMRadioService::Singleton()->IsRDSEnabled();
|
||||
}
|
||||
|
||||
bool
|
||||
FMRadio::AntennaAvailable() const
|
||||
{
|
||||
@ -265,6 +295,69 @@ FMRadio::ChannelWidth() const
|
||||
return IFMRadioService::Singleton()->GetChannelWidth();
|
||||
}
|
||||
|
||||
uint32_t
|
||||
FMRadio::RdsGroupMask() const
|
||||
{
|
||||
return mRdsGroupMask;
|
||||
}
|
||||
|
||||
void
|
||||
FMRadio::SetRdsGroupMask(uint32_t aRdsGroupMask)
|
||||
{
|
||||
mRdsGroupMask = aRdsGroupMask;
|
||||
IFMRadioService::Singleton()->SetRDSGroupMask(aRdsGroupMask);
|
||||
}
|
||||
|
||||
Nullable<unsigned short>
|
||||
FMRadio::GetPi() const
|
||||
{
|
||||
return IFMRadioService::Singleton()->GetPi();
|
||||
}
|
||||
|
||||
Nullable<uint8_t>
|
||||
FMRadio::GetPty() const
|
||||
{
|
||||
return IFMRadioService::Singleton()->GetPty();
|
||||
}
|
||||
|
||||
void
|
||||
FMRadio::GetPs(DOMString& aPsname) const
|
||||
{
|
||||
if (!IFMRadioService::Singleton()->GetPs(aPsname)) {
|
||||
aPsname.SetNull();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
FMRadio::GetRt(DOMString& aRadiotext) const
|
||||
{
|
||||
if (!IFMRadioService::Singleton()->GetRt(aRadiotext)) {
|
||||
aRadiotext.SetNull();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
FMRadio::GetRdsgroup(JSContext* cx, JS::MutableHandle<JSObject*> retval)
|
||||
{
|
||||
uint64_t group;
|
||||
if (!IFMRadioService::Singleton()->GetRdsgroup(group)) {
|
||||
return;
|
||||
}
|
||||
|
||||
JSObject *rdsgroup = Uint16Array::Create(cx, this, 4);
|
||||
uint16_t *data = JS_GetUint16ArrayData(rdsgroup);
|
||||
data[3] = group & 0xFFFF;
|
||||
group >>= 16;
|
||||
data[2] = group & 0xFFFF;
|
||||
group >>= 16;
|
||||
data[1] = group & 0xFFFF;
|
||||
group >>= 16;
|
||||
data[0] = group & 0xFFFF;
|
||||
|
||||
JS::ExposeObjectToActiveJS(rdsgroup);
|
||||
retval.set(rdsgroup);
|
||||
}
|
||||
|
||||
already_AddRefed<DOMRequest>
|
||||
FMRadio::Enable(double aFrequency)
|
||||
{
|
||||
@ -350,6 +443,32 @@ FMRadio::CancelSeek()
|
||||
return r.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<DOMRequest>
|
||||
FMRadio::EnableRDS()
|
||||
{
|
||||
nsCOMPtr<nsPIDOMWindow> win = GetOwner();
|
||||
if (!win) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsRefPtr<FMRadioRequest> r = new FMRadioRequest(win, this);
|
||||
IFMRadioService::Singleton()->EnableRDS(r);
|
||||
return r.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<DOMRequest>
|
||||
FMRadio::DisableRDS()
|
||||
{
|
||||
nsCOMPtr<nsPIDOMWindow> win = GetOwner();
|
||||
if (!win) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsRefPtr<FMRadioRequest> r = new FMRadioRequest(win, this);
|
||||
FMRadioService::Singleton()->DisableRDS(r);
|
||||
return r.forget();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
FMRadio::HandleEvent(nsIDOMEvent* aEvent)
|
||||
{
|
||||
|
@ -55,6 +55,8 @@ public:
|
||||
|
||||
static bool Enabled();
|
||||
|
||||
bool RdsEnabled();
|
||||
|
||||
bool AntennaAvailable() const;
|
||||
|
||||
Nullable<double> GetFrequency() const;
|
||||
@ -65,6 +67,20 @@ public:
|
||||
|
||||
double ChannelWidth() const;
|
||||
|
||||
uint32_t RdsGroupMask() const;
|
||||
|
||||
void SetRdsGroupMask(uint32_t aRdsGroupMask);
|
||||
|
||||
Nullable<unsigned short> GetPi() const;
|
||||
|
||||
Nullable<uint8_t> GetPty() const;
|
||||
|
||||
void GetPs(DOMString& aPsname) const;
|
||||
|
||||
void GetRt(DOMString& aRadiotext) const;
|
||||
|
||||
void GetRdsgroup(JSContext* cx, JS::MutableHandle<JSObject*> retval);
|
||||
|
||||
already_AddRefed<DOMRequest> Enable(double aFrequency);
|
||||
|
||||
already_AddRefed<DOMRequest> Disable();
|
||||
@ -77,10 +93,21 @@ public:
|
||||
|
||||
already_AddRefed<DOMRequest> CancelSeek();
|
||||
|
||||
already_AddRefed<DOMRequest> EnableRDS();
|
||||
|
||||
already_AddRefed<DOMRequest> DisableRDS();
|
||||
|
||||
IMPL_EVENT_HANDLER(enabled);
|
||||
IMPL_EVENT_HANDLER(disabled);
|
||||
IMPL_EVENT_HANDLER(rdsenabled);
|
||||
IMPL_EVENT_HANDLER(rdsdisabled);
|
||||
IMPL_EVENT_HANDLER(antennaavailablechange);
|
||||
IMPL_EVENT_HANDLER(frequencychange);
|
||||
IMPL_EVENT_HANDLER(pichange);
|
||||
IMPL_EVENT_HANDLER(ptychange);
|
||||
IMPL_EVENT_HANDLER(pschange);
|
||||
IMPL_EVENT_HANDLER(rtchange);
|
||||
IMPL_EVENT_HANDLER(newrdsgroup);
|
||||
|
||||
// nsIDOMEventListener
|
||||
NS_IMETHOD HandleEvent(nsIDOMEvent* aEvent);
|
||||
@ -92,6 +119,7 @@ private:
|
||||
void EnableAudioChannelAgent();
|
||||
|
||||
hal::SwitchState mHeadphoneState;
|
||||
uint32_t mRdsGroupMask;
|
||||
bool mAudioChannelAgentEnabled;
|
||||
bool mHasInternalAntenna;
|
||||
bool mIsShutdown;
|
||||
|
@ -30,7 +30,13 @@ BEGIN_FMRADIO_NAMESPACE
|
||||
enum FMRadioEventType
|
||||
{
|
||||
FrequencyChanged,
|
||||
EnabledChanged
|
||||
EnabledChanged,
|
||||
RDSEnabledChanged,
|
||||
PIChanged,
|
||||
PSChanged,
|
||||
PTYChanged,
|
||||
RadiotextChanged,
|
||||
NewRDSGroup
|
||||
};
|
||||
|
||||
typedef mozilla::Observer<FMRadioEventType> FMRadioEventObserver;
|
||||
|
@ -26,6 +26,8 @@
|
||||
#define MOZSETTINGS_CHANGED_ID "mozsettings-changed"
|
||||
#define SETTING_KEY_AIRPLANEMODE_ENABLED "airplaneMode.enabled"
|
||||
|
||||
#define DOM_PARSED_RDS_GROUPS ((0x2 << 30) | (0x3 << 4) | (0x3 << 0))
|
||||
|
||||
using namespace mozilla::hal;
|
||||
using mozilla::Preferences;
|
||||
|
||||
@ -49,9 +51,26 @@ FMRadioService::FMRadioService()
|
||||
, mState(Disabled)
|
||||
, mHasReadAirplaneModeSetting(false)
|
||||
, mAirplaneModeEnabled(false)
|
||||
, mRDSEnabled(false)
|
||||
, mPendingRequest(nullptr)
|
||||
, mObserverList(FMRadioEventObserverList())
|
||||
, mRDSGroupMask(0)
|
||||
, mLastPI(0)
|
||||
, mPI(0)
|
||||
, mPTY(0)
|
||||
, mPISet(false)
|
||||
, mPTYSet(false)
|
||||
, mRDSLock("FMRadioService::mRDSLock")
|
||||
, mPSNameState(0)
|
||||
, mRadiotextAB(false)
|
||||
, mRDSGroupSet(false)
|
||||
, mPSNameSet(false)
|
||||
, mRadiotextSet(false)
|
||||
{
|
||||
memset(mPSName, 0, sizeof(mPSName));
|
||||
memset(mRadiotext, 0, sizeof(mRadiotext));
|
||||
memset(mTempPSName, 0, sizeof(mTempPSName));
|
||||
memset(mTempRadiotext, 0, sizeof(mTempRadiotext));
|
||||
|
||||
// Read power state and frequency from Hal.
|
||||
mEnabled = IsFMRadioOn();
|
||||
@ -110,10 +129,12 @@ FMRadioService::FMRadioService()
|
||||
}
|
||||
|
||||
RegisterFMRadioObserver(this);
|
||||
RegisterFMRadioRDSObserver(this);
|
||||
}
|
||||
|
||||
FMRadioService::~FMRadioService()
|
||||
{
|
||||
UnregisterFMRadioRDSObserver(this);
|
||||
UnregisterFMRadioObserver(this);
|
||||
}
|
||||
|
||||
@ -277,6 +298,21 @@ private:
|
||||
FMRadioSeekDirection mDirection;
|
||||
};
|
||||
|
||||
class NotifyRunnable MOZ_FINAL : public nsRunnable
|
||||
{
|
||||
public:
|
||||
NotifyRunnable(FMRadioEventType aType) : mType(aType) { }
|
||||
|
||||
NS_IMETHOD Run()
|
||||
{
|
||||
FMRadioService::Singleton()->NotifyFMRadioEvent(mType);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
FMRadioEventType mType;
|
||||
};
|
||||
|
||||
void
|
||||
FMRadioService::TransitionState(const FMRadioResponseType& aResponse,
|
||||
FMRadioState aState)
|
||||
@ -374,6 +410,13 @@ FMRadioService::IsEnabled() const
|
||||
return IsFMRadioOn();
|
||||
}
|
||||
|
||||
bool
|
||||
FMRadioService::IsRDSEnabled() const
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!");
|
||||
return mRDSEnabled;
|
||||
}
|
||||
|
||||
double
|
||||
FMRadioService::GetFrequency() const
|
||||
{
|
||||
@ -407,6 +450,54 @@ FMRadioService::GetChannelWidth() const
|
||||
return mChannelWidthInKHz / 1000.0;
|
||||
}
|
||||
|
||||
Nullable<unsigned short>
|
||||
FMRadioService::GetPi() const
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!");
|
||||
if (!mPISet) {
|
||||
return Nullable<unsigned short>();
|
||||
}
|
||||
return Nullable<unsigned short>(mPI);
|
||||
}
|
||||
|
||||
Nullable<uint8_t>
|
||||
FMRadioService::GetPty() const
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!");
|
||||
if (!mPTYSet) {
|
||||
return Nullable<uint8_t>();
|
||||
}
|
||||
return Nullable<uint8_t>(mPTY);
|
||||
}
|
||||
|
||||
bool
|
||||
FMRadioService::GetPs(nsString& aPSName)
|
||||
{
|
||||
MutexAutoLock lock(mRDSLock);
|
||||
if (mPSNameSet) {
|
||||
aPSName = nsString(mPSName);
|
||||
}
|
||||
return mPSNameSet;
|
||||
}
|
||||
|
||||
bool
|
||||
FMRadioService::GetRt(nsString& aRadiotext)
|
||||
{
|
||||
MutexAutoLock lock(mRDSLock);
|
||||
if (mRadiotextSet) {
|
||||
aRadiotext = nsString(mRadiotext);
|
||||
}
|
||||
return mRadiotextSet;
|
||||
}
|
||||
|
||||
bool
|
||||
FMRadioService::GetRdsgroup(uint64_t& aRDSGroup)
|
||||
{
|
||||
MutexAutoLock lock(mRDSLock);
|
||||
aRDSGroup = mRDSGroup;
|
||||
return mRDSGroupSet;
|
||||
}
|
||||
|
||||
void
|
||||
FMRadioService::Enable(double aFrequencyInMHz,
|
||||
FMRadioReplyRunnable* aReplyRunnable)
|
||||
@ -679,6 +770,47 @@ FMRadioService::CancelSeek(FMRadioReplyRunnable* aReplyRunnable)
|
||||
NS_DispatchToMainThread(aReplyRunnable);
|
||||
}
|
||||
|
||||
void
|
||||
FMRadioService::SetRDSGroupMask(uint32_t aRDSGroupMask)
|
||||
{
|
||||
mRDSGroupMask = aRDSGroupMask;
|
||||
if (IsFMRadioOn()) {
|
||||
hal::EnableRDS(mRDSGroupMask | DOM_PARSED_RDS_GROUPS);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
FMRadioService::EnableRDS(FMRadioReplyRunnable* aReplyRunnable)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!");
|
||||
MOZ_ASSERT(aReplyRunnable);
|
||||
|
||||
mRDSEnabled = true;
|
||||
if (IsFMRadioOn()) {
|
||||
hal::EnableRDS(mRDSGroupMask | DOM_PARSED_RDS_GROUPS);
|
||||
}
|
||||
|
||||
aReplyRunnable->SetReply(SuccessResponse());
|
||||
NS_DispatchToMainThread(aReplyRunnable);
|
||||
NS_DispatchToMainThread(new NotifyRunnable(RDSEnabledChanged));
|
||||
}
|
||||
|
||||
void
|
||||
FMRadioService::DisableRDS(FMRadioReplyRunnable* aReplyRunnable)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!");
|
||||
MOZ_ASSERT(aReplyRunnable);
|
||||
|
||||
mRDSEnabled = false;
|
||||
if (IsFMRadioOn()) {
|
||||
hal::DisableRDS();
|
||||
}
|
||||
|
||||
aReplyRunnable->SetReply(SuccessResponse());
|
||||
NS_DispatchToMainThread(aReplyRunnable);
|
||||
NS_DispatchToMainThread(new NotifyRunnable(RDSEnabledChanged));
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
FMRadioService::Observe(nsISupports* aSubject,
|
||||
const char* aTopic,
|
||||
@ -760,10 +892,18 @@ FMRadioService::Notify(const FMRadioOperationInformation& aInfo)
|
||||
// The frequency was changed from '0' to some meaningful number, so we
|
||||
// should send the `FrequencyChanged` event manually.
|
||||
NotifyFMRadioEvent(FrequencyChanged);
|
||||
|
||||
if (mRDSEnabled) {
|
||||
hal::EnableRDS(mRDSGroupMask | DOM_PARSED_RDS_GROUPS);
|
||||
}
|
||||
break;
|
||||
case FM_RADIO_OPERATION_DISABLE:
|
||||
MOZ_ASSERT(mState == Disabling);
|
||||
|
||||
mPISet = false;
|
||||
mPTYSet = false;
|
||||
memset(mPSName, 0, sizeof(mPSName));
|
||||
memset(mRadiotext, 0, sizeof(mRadiotext));
|
||||
TransitionState(SuccessResponse(), Disabled);
|
||||
UpdatePowerState();
|
||||
break;
|
||||
@ -785,6 +925,274 @@ FMRadioService::Notify(const FMRadioOperationInformation& aInfo)
|
||||
}
|
||||
}
|
||||
|
||||
/* This is defined by the RDS standard */
|
||||
static const uint16_t sRDSToUnicodeMap[256] = {
|
||||
// The lower half differs from ASCII in 0x1F, 0x24, 0x5E, 0x7E
|
||||
// Most control characters are replaced with 0x20 (space)
|
||||
// 0x0-
|
||||
0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
|
||||
0x0020, 0x0009, 0x000A, 0x000B, 0x0020, 0x00D0, 0x0020, 0x0020,
|
||||
|
||||
// 0x1-
|
||||
0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
|
||||
0x0020, 0x0020, 0x0020, 0x001B, 0x0020, 0x0020, 0x0020, 0x00AD,
|
||||
|
||||
// 0x2-
|
||||
0x0020, 0x0021, 0x0022, 0x0023, 0x00A4, 0x0025, 0x0026, 0x0027,
|
||||
0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F,
|
||||
|
||||
// 0x3-
|
||||
0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
|
||||
0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F,
|
||||
|
||||
// 0x4-
|
||||
0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
|
||||
0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F,
|
||||
|
||||
// 0x5-
|
||||
0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
|
||||
0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x2015, 0x005F,
|
||||
|
||||
// 0x6-
|
||||
0x2551, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
|
||||
0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F,
|
||||
|
||||
// 0x7-
|
||||
0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
|
||||
0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x00AF, 0x007F,
|
||||
|
||||
// 0x8-
|
||||
0x00E1, 0x00E0, 0x00E9, 0x00E8, 0x00ED, 0x00EC, 0x00F3, 0x00F2,
|
||||
0x00FA, 0x00F9, 0x00D1, 0x00C7, 0x015E, 0x00DF, 0x00A1, 0x0132,
|
||||
|
||||
// 0x9-
|
||||
0x00E2, 0x00E4, 0x00EA, 0x00EB, 0x00EE, 0x00EF, 0x00F4, 0x00F6,
|
||||
0x00FB, 0x00FC, 0x00F1, 0x00E7, 0x015F, 0x011F, 0x0131, 0x0133,
|
||||
|
||||
// 0xA-
|
||||
0x00AA, 0x03B1, 0x00A9, 0x2030, 0x011E, 0x011B, 0x0148, 0x0151,
|
||||
0x03C0, 0x20AC, 0x00A3, 0x0024, 0x2190, 0x2191, 0x2192, 0x2193,
|
||||
|
||||
// 0xB-
|
||||
0x00BA, 0x00B9, 0x00B2, 0x00B3, 0x00B1, 0x0130, 0x0144, 0x0171,
|
||||
0x03BC, 0x00BF, 0x00F7, 0x00B0, 0x00BC, 0x00BD, 0x00BE, 0x00A7,
|
||||
|
||||
// 0xC-
|
||||
0x00C1, 0x00C0, 0x00C9, 0x00C8, 0x00CD, 0x00CC, 0x00D3, 0x00D2,
|
||||
0x00DA, 0x00D9, 0x0158, 0x010C, 0x0160, 0x017D, 0x00D0, 0x013F,
|
||||
|
||||
// 0xD-
|
||||
0x00C2, 0x00C4, 0x00CA, 0x00CB, 0x00CE, 0x00CF, 0x00D4, 0x00D6,
|
||||
0x00DB, 0x00DC, 0x0159, 0x010D, 0x0161, 0x017E, 0x0111, 0x0140,
|
||||
|
||||
// 0xE-
|
||||
0x00C3, 0x00C5, 0x00C6, 0x0152, 0x0177, 0x00DD, 0x00D5, 0x00D8,
|
||||
0x00DE, 0x014A, 0x0154, 0x0106, 0x015A, 0x0179, 0x0166, 0x00F0,
|
||||
|
||||
// 0xF-
|
||||
0x00E3, 0x00E5, 0x00E6, 0x0153, 0x0175, 0x00FD, 0x00F5, 0x00F8,
|
||||
0x00FE, 0x014B, 0x0155, 0x0107, 0x015B, 0x017A, 0x0167, 0x0020,
|
||||
};
|
||||
|
||||
void
|
||||
FMRadioService::Notify(const FMRadioRDSGroup& aRDSGroup)
|
||||
{
|
||||
uint16_t blocks[4];
|
||||
blocks[0] = aRDSGroup.blockA();
|
||||
blocks[1] = aRDSGroup.blockB();
|
||||
blocks[2] = aRDSGroup.blockC();
|
||||
blocks[3] = aRDSGroup.blockD();
|
||||
|
||||
/* Bit 11 in block B determines whether this is a type B group. */
|
||||
uint16_t lastPI = blocks[1] & (1 << 11) ? blocks[2] : mLastPI;
|
||||
|
||||
/* Update PI if it's not set or if we get two PI with the new value. */
|
||||
if ((mPI != blocks[0] && lastPI == blocks[0]) || !mPISet) {
|
||||
mPI = blocks[0];
|
||||
if (!mPISet) {
|
||||
mPSNameState = 0;
|
||||
mRadiotextState = 0;
|
||||
memset(mTempPSName, 0, sizeof(mTempPSName));
|
||||
memset(mTempRadiotext, 0, sizeof(mTempRadiotext));
|
||||
}
|
||||
mPISet = true;
|
||||
NS_DispatchToMainThread(new NotifyRunnable(PIChanged));
|
||||
}
|
||||
mLastPI = blocks[0];
|
||||
|
||||
/* PTY is also updated using the same logic as PI */
|
||||
uint16_t pty = (blocks[1] >> 5) & 0x1F;
|
||||
if ((mPTY != pty && pty == mLastPTY) || !mPTYSet) {
|
||||
mPTY = pty;
|
||||
mPTYSet = true;
|
||||
NS_DispatchToMainThread(new NotifyRunnable(PTYChanged));
|
||||
}
|
||||
mLastPTY = pty;
|
||||
|
||||
uint16_t grouptype = blocks[1] >> 11;
|
||||
switch (grouptype) {
|
||||
case 0: // 0a
|
||||
case 1: // 0b
|
||||
{
|
||||
uint16_t segmentAddr = (blocks[1] & 0x3);
|
||||
// mPSNameState is a bitmask that lets us ensure all segments
|
||||
// are received before updating the PS name.
|
||||
if (!segmentAddr) {
|
||||
mPSNameState = 1;
|
||||
} else {
|
||||
mPSNameState |= 1 << segmentAddr;
|
||||
}
|
||||
|
||||
uint16_t offset = segmentAddr << 1;
|
||||
mTempPSName[offset] = sRDSToUnicodeMap[blocks[3] >> 8];
|
||||
mTempPSName[offset + 1] = sRDSToUnicodeMap[blocks[3] & 0xFF];
|
||||
|
||||
if (mPSNameState != 0xF) {
|
||||
break;
|
||||
}
|
||||
|
||||
mPSNameState = 0;
|
||||
if (memcmp(mTempPSName, mPSName, sizeof(mTempPSName))) {
|
||||
MutexAutoLock lock(mRDSLock);
|
||||
mPSNameSet = true;
|
||||
memcpy(mPSName, mTempPSName, sizeof(mTempPSName));
|
||||
NS_DispatchToMainThread(new NotifyRunnable(PSChanged));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 4: // 2a Radiotext
|
||||
{
|
||||
uint16_t segmentAddr = (blocks[1] & 0xF);
|
||||
bool textAB = blocks[1] & (1 << 5);
|
||||
if (textAB != mRadiotextAB) {
|
||||
mRadiotextState = 0;
|
||||
memset(mTempRadiotext, 0, sizeof(mTempRadiotext));
|
||||
mRadiotextAB = textAB;
|
||||
MutexAutoLock lock(mRDSLock);
|
||||
memset(mRadiotext, 0, sizeof(mRadiotext));
|
||||
NS_DispatchToMainThread(new NotifyRunnable(RadiotextChanged));
|
||||
}
|
||||
|
||||
// mRadiotextState is a bitmask that lets us ensure all segments
|
||||
// are received before updating the radiotext.
|
||||
if (!segmentAddr) {
|
||||
mRadiotextState = 1;
|
||||
} else {
|
||||
mRadiotextState |= 1 << segmentAddr;
|
||||
}
|
||||
|
||||
uint8_t segment[4];
|
||||
segment[0] = blocks[2] >> 8;
|
||||
segment[1] = blocks[2] & 0xFF;
|
||||
segment[2] = blocks[3] >> 8;
|
||||
segment[3] = blocks[3] & 0xFF;
|
||||
|
||||
uint16_t offset = segmentAddr << 2;
|
||||
bool done = false;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (segment[i] == '\r') {
|
||||
mTempRadiotext[offset++] = 0;
|
||||
done = true;
|
||||
} else {
|
||||
mTempRadiotext[offset++] = sRDSToUnicodeMap[segment[i]];
|
||||
}
|
||||
}
|
||||
if (offset == 64) {
|
||||
done = true;
|
||||
}
|
||||
|
||||
if (!done ||
|
||||
(mRadiotextState + 1) != (1 << ((blocks[1] & 0xF) + 1)) ||
|
||||
!memcmp(mTempRadiotext, mRadiotext, sizeof(mTempRadiotext))) {
|
||||
break;
|
||||
}
|
||||
|
||||
MutexAutoLock lock(mRDSLock);
|
||||
mRadiotextSet = true;
|
||||
memcpy(mRadiotext, mTempRadiotext, sizeof(mTempRadiotext));
|
||||
NS_DispatchToMainThread(new NotifyRunnable(RadiotextChanged));
|
||||
break;
|
||||
}
|
||||
case 5: // 2b Radiotext
|
||||
{
|
||||
uint16_t segmentAddr = (blocks[1] & 0xF);
|
||||
bool textAB = blocks[1] & (1 << 5);
|
||||
if (textAB != mRadiotextAB) {
|
||||
mRadiotextState = 0;
|
||||
memset(mTempRadiotext, 0, sizeof(mTempRadiotext));
|
||||
mRadiotextAB = textAB;
|
||||
MutexAutoLock lock(mRDSLock);
|
||||
memset(mRadiotext, 0, sizeof(mRadiotext));
|
||||
NS_DispatchToMainThread(new NotifyRunnable(RadiotextChanged));
|
||||
}
|
||||
|
||||
if (!segmentAddr) {
|
||||
mRadiotextState = 1;
|
||||
} else {
|
||||
mRadiotextState |= 1 << segmentAddr;
|
||||
}
|
||||
uint8_t segment[2];
|
||||
segment[0] = blocks[3] >> 8;
|
||||
segment[1] = blocks[3] & 0xFF;
|
||||
|
||||
uint16_t offset = segmentAddr << 1;
|
||||
bool done = false;
|
||||
for (int i = 0; i < 2; i++) {
|
||||
if (segment[i] == '\r') {
|
||||
mTempRadiotext[offset++] = 0;
|
||||
done = true;
|
||||
} else {
|
||||
mTempRadiotext[offset++] = sRDSToUnicodeMap[segment[i]];
|
||||
}
|
||||
}
|
||||
if (offset == 32) {
|
||||
done = true;
|
||||
}
|
||||
|
||||
if (!done ||
|
||||
(mRadiotextState + 1) != (1 << ((blocks[1] & 0xF) + 1)) ||
|
||||
!memcmp(mTempRadiotext, mRadiotext, sizeof(mTempRadiotext))) {
|
||||
break;
|
||||
}
|
||||
|
||||
MutexAutoLock lock(mRDSLock);
|
||||
mRadiotextSet = true;
|
||||
memcpy(mRadiotext, mTempRadiotext, sizeof(mTempRadiotext));
|
||||
NS_DispatchToMainThread(new NotifyRunnable(RadiotextChanged));
|
||||
break;
|
||||
}
|
||||
case 31: // 15b Fast Tuning and Switching
|
||||
{
|
||||
uint16_t secondPty = (blocks[3] >> 5) & 0x1F;
|
||||
if (pty == mPTY || pty != secondPty) {
|
||||
break;
|
||||
}
|
||||
mPTY = pty;
|
||||
NS_DispatchToMainThread(new NotifyRunnable(PTYChanged));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Only notify users of raw RDS groups that they're interested in.
|
||||
// We always receive DOM_PARSED_RDS_GROUPS when RDS is enabled.
|
||||
if (!(mRDSGroupMask & (1 << grouptype))) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint64_t newgroup = blocks[0];
|
||||
newgroup <<= 16;
|
||||
newgroup |= blocks[1];
|
||||
newgroup <<= 16;
|
||||
newgroup |= blocks[2];
|
||||
newgroup <<= 16;
|
||||
newgroup |= blocks[3];
|
||||
|
||||
MutexAutoLock lock(mRDSLock);
|
||||
mRDSGroup = newgroup;
|
||||
mRDSGroupSet = true;
|
||||
NS_DispatchToMainThread(new NotifyRunnable(NewRDSGroup));
|
||||
}
|
||||
|
||||
void
|
||||
FMRadioService::UpdatePowerState()
|
||||
{
|
||||
@ -802,6 +1210,13 @@ FMRadioService::UpdateFrequency()
|
||||
if (mPendingFrequencyInKHz != frequency) {
|
||||
mPendingFrequencyInKHz = frequency;
|
||||
NotifyFMRadioEvent(FrequencyChanged);
|
||||
mPISet = false;
|
||||
mPTYSet = false;
|
||||
memset(mPSName, 0, sizeof(mPSName));
|
||||
memset(mRadiotext, 0, sizeof(mRadiotext));
|
||||
mRDSGroupSet = false;
|
||||
mPSNameSet = false;
|
||||
mRadiotextSet = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -7,9 +7,11 @@
|
||||
#ifndef mozilla_dom_fmradioservice_h__
|
||||
#define mozilla_dom_fmradioservice_h__
|
||||
|
||||
#include "mozilla/dom/Nullable.h"
|
||||
#include "mozilla/dom/PFMRadioRequest.h"
|
||||
#include "FMRadioCommon.h"
|
||||
#include "mozilla/Hal.h"
|
||||
#include "mozilla/Mutex.h"
|
||||
#include "mozilla/StaticPtr.h"
|
||||
#include "mozilla/Services.h"
|
||||
#include "nsThreadUtils.h"
|
||||
@ -95,10 +97,16 @@ protected:
|
||||
|
||||
public:
|
||||
virtual bool IsEnabled() const = 0;
|
||||
virtual bool IsRDSEnabled() const = 0;
|
||||
virtual double GetFrequency() const = 0;
|
||||
virtual double GetFrequencyUpperBound() const = 0;
|
||||
virtual double GetFrequencyLowerBound() const = 0;
|
||||
virtual double GetChannelWidth() const = 0;
|
||||
virtual Nullable<unsigned short> GetPi() const = 0;
|
||||
virtual Nullable<uint8_t> GetPty() const = 0;
|
||||
virtual bool GetPs(nsString& aPsname) = 0;
|
||||
virtual bool GetRt(nsString& aRadiotext) = 0;
|
||||
virtual bool GetRdsgroup(uint64_t& aRDSGroup) = 0;
|
||||
|
||||
virtual void Enable(double aFrequency, FMRadioReplyRunnable* aReplyRunnable) = 0;
|
||||
virtual void Disable(FMRadioReplyRunnable* aReplyRunnable) = 0;
|
||||
@ -106,6 +114,9 @@ public:
|
||||
virtual void Seek(mozilla::hal::FMRadioSeekDirection aDirection,
|
||||
FMRadioReplyRunnable* aReplyRunnable) = 0;
|
||||
virtual void CancelSeek(FMRadioReplyRunnable* aReplyRunnable) = 0;
|
||||
virtual void SetRDSGroupMask(uint32_t aRDSGroupMask) = 0;
|
||||
virtual void EnableRDS(FMRadioReplyRunnable* aReplyRunnable) = 0;
|
||||
virtual void DisableRDS(FMRadioReplyRunnable* aReplyRunnable) = 0;
|
||||
|
||||
/**
|
||||
* Register handler to receive the FM Radio events, including:
|
||||
@ -138,11 +149,13 @@ enum FMRadioState
|
||||
|
||||
class FMRadioService MOZ_FINAL : public IFMRadioService
|
||||
, public hal::FMRadioObserver
|
||||
, public hal::FMRadioRDSObserver
|
||||
, public nsIObserver
|
||||
{
|
||||
friend class ReadAirplaneModeSettingTask;
|
||||
friend class EnableRunnable;
|
||||
friend class DisableRunnable;
|
||||
friend class NotifyRunnable;
|
||||
|
||||
public:
|
||||
static FMRadioService* Singleton();
|
||||
@ -151,10 +164,16 @@ public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
virtual bool IsEnabled() const MOZ_OVERRIDE;
|
||||
virtual bool IsRDSEnabled() const MOZ_OVERRIDE;
|
||||
virtual double GetFrequency() const MOZ_OVERRIDE;
|
||||
virtual double GetFrequencyUpperBound() const MOZ_OVERRIDE;
|
||||
virtual double GetFrequencyLowerBound() const MOZ_OVERRIDE;
|
||||
virtual double GetChannelWidth() const MOZ_OVERRIDE;
|
||||
virtual Nullable<unsigned short> GetPi() const MOZ_OVERRIDE;
|
||||
virtual Nullable<uint8_t> GetPty() const MOZ_OVERRIDE;
|
||||
virtual bool GetPs(nsString& aPsname) MOZ_OVERRIDE;
|
||||
virtual bool GetRt(nsString& aRadiotext) MOZ_OVERRIDE;
|
||||
virtual bool GetRdsgroup(uint64_t& aRDSGroup) MOZ_OVERRIDE;
|
||||
|
||||
virtual void Enable(double aFrequency,
|
||||
FMRadioReplyRunnable* aReplyRunnable) MOZ_OVERRIDE;
|
||||
@ -164,6 +183,9 @@ public:
|
||||
virtual void Seek(mozilla::hal::FMRadioSeekDirection aDirection,
|
||||
FMRadioReplyRunnable* aReplyRunnable) MOZ_OVERRIDE;
|
||||
virtual void CancelSeek(FMRadioReplyRunnable* aReplyRunnable) MOZ_OVERRIDE;
|
||||
virtual void SetRDSGroupMask(uint32_t aRDSGroupMask) MOZ_OVERRIDE;
|
||||
virtual void EnableRDS(FMRadioReplyRunnable* aReplyRunnable) MOZ_OVERRIDE;
|
||||
virtual void DisableRDS(FMRadioReplyRunnable* aReplyRunnable) MOZ_OVERRIDE;
|
||||
|
||||
virtual void AddObserver(FMRadioEventObserver* aObserver) MOZ_OVERRIDE;
|
||||
virtual void RemoveObserver(FMRadioEventObserver* aObserver) MOZ_OVERRIDE;
|
||||
@ -172,6 +194,8 @@ public:
|
||||
|
||||
/* FMRadioObserver */
|
||||
void Notify(const hal::FMRadioOperationInformation& aInfo) MOZ_OVERRIDE;
|
||||
/* FMRadioRDSObserver */
|
||||
void Notify(const hal::FMRadioRDSGroup& aRDSGroup) MOZ_OVERRIDE;
|
||||
|
||||
NS_DECL_NSIOBSERVER
|
||||
|
||||
@ -197,6 +221,7 @@ private:
|
||||
|
||||
bool mHasReadAirplaneModeSetting;
|
||||
bool mAirplaneModeEnabled;
|
||||
bool mRDSEnabled;
|
||||
|
||||
uint32_t mUpperBoundInKHz;
|
||||
uint32_t mLowerBoundInKHz;
|
||||
@ -209,6 +234,30 @@ private:
|
||||
FMRadioEventObserverList mObserverList;
|
||||
|
||||
static StaticRefPtr<FMRadioService> sFMRadioService;
|
||||
|
||||
uint32_t mRDSGroupMask;
|
||||
|
||||
uint16_t mLastPI;
|
||||
uint16_t mLastPTY;
|
||||
Atomic<uint32_t> mPI;
|
||||
Atomic<uint32_t> mPTY;
|
||||
Atomic<bool> mPISet;
|
||||
Atomic<bool> mPTYSet;
|
||||
|
||||
/* Protects mPSName, mRadiotext, and mRDSGroup */
|
||||
Mutex mRDSLock;
|
||||
char16_t mPSName[9];
|
||||
char16_t mRadiotext[65];
|
||||
uint64_t mRDSGroup;
|
||||
|
||||
uint8_t mPSNameState;
|
||||
uint16_t mRadiotextState;
|
||||
uint16_t mTempPSName[8];
|
||||
uint16_t mTempRadiotext[64];
|
||||
bool mRadiotextAB;
|
||||
bool mRDSGroupSet;
|
||||
bool mPSNameSet;
|
||||
bool mRadiotextSet;
|
||||
};
|
||||
|
||||
END_FMRADIO_NAMESPACE
|
||||
|
@ -16,7 +16,13 @@ StaticAutoPtr<FMRadioChild> FMRadioChild::sFMRadioChild;
|
||||
|
||||
FMRadioChild::FMRadioChild()
|
||||
: mEnabled(false)
|
||||
, mRDSEnabled(false)
|
||||
, mRDSGroupSet(false)
|
||||
, mPSNameSet(false)
|
||||
, mRadiotextSet(false)
|
||||
, mFrequency(0)
|
||||
, mRDSGroup(0)
|
||||
, mRDSGroupMask(0)
|
||||
, mObserverList(FMRadioEventObserverList())
|
||||
{
|
||||
MOZ_COUNT_CTOR(FMRadioChild);
|
||||
@ -44,6 +50,12 @@ FMRadioChild::IsEnabled() const
|
||||
return mEnabled;
|
||||
}
|
||||
|
||||
bool
|
||||
FMRadioChild::IsRDSEnabled() const
|
||||
{
|
||||
return mRDSEnabled;
|
||||
}
|
||||
|
||||
double
|
||||
FMRadioChild::GetFrequency() const
|
||||
{
|
||||
@ -69,6 +81,43 @@ FMRadioChild::GetChannelWidth() const
|
||||
return mChannelWidth;
|
||||
}
|
||||
|
||||
Nullable<unsigned short>
|
||||
FMRadioChild::GetPi() const
|
||||
{
|
||||
return mPI;
|
||||
}
|
||||
|
||||
Nullable<uint8_t>
|
||||
FMRadioChild::GetPty() const
|
||||
{
|
||||
return mPTY;
|
||||
}
|
||||
|
||||
bool
|
||||
FMRadioChild::GetPs(nsString& aPSName)
|
||||
{
|
||||
if (mPSNameSet) {
|
||||
aPSName = mPSName;
|
||||
}
|
||||
return mPSNameSet;
|
||||
}
|
||||
|
||||
bool
|
||||
FMRadioChild::GetRt(nsString& aRadiotext)
|
||||
{
|
||||
if (mRadiotextSet) {
|
||||
aRadiotext = mRadiotext;
|
||||
}
|
||||
return mRadiotextSet;
|
||||
}
|
||||
|
||||
bool
|
||||
FMRadioChild::GetRdsgroup(uint64_t& aRDSGroup)
|
||||
{
|
||||
aRDSGroup = mRDSGroup;
|
||||
return mRDSGroupSet;
|
||||
}
|
||||
|
||||
void
|
||||
FMRadioChild::Enable(double aFrequency, FMRadioReplyRunnable* aReplyRunnable)
|
||||
{
|
||||
@ -101,6 +150,25 @@ FMRadioChild::CancelSeek(FMRadioReplyRunnable* aReplyRunnable)
|
||||
SendRequest(aReplyRunnable, CancelSeekRequestArgs());
|
||||
}
|
||||
|
||||
void
|
||||
FMRadioChild::SetRDSGroupMask(uint32_t aRDSGroupMask)
|
||||
{
|
||||
mRDSGroupMask = aRDSGroupMask;
|
||||
SendSetRDSGroupMask(aRDSGroupMask);
|
||||
}
|
||||
|
||||
void
|
||||
FMRadioChild::EnableRDS(FMRadioReplyRunnable* aReplyRunnable)
|
||||
{
|
||||
SendRequest(aReplyRunnable, EnableRDSArgs());
|
||||
}
|
||||
|
||||
void
|
||||
FMRadioChild::DisableRDS(FMRadioReplyRunnable* aReplyRunnable)
|
||||
{
|
||||
SendRequest(aReplyRunnable, DisableRDSArgs());
|
||||
}
|
||||
|
||||
inline void
|
||||
FMRadioChild::NotifyFMRadioEvent(FMRadioEventType aType)
|
||||
{
|
||||
@ -132,6 +200,26 @@ FMRadioChild::RecvNotifyFrequencyChanged(const double& aFrequency)
|
||||
{
|
||||
mFrequency = aFrequency;
|
||||
NotifyFMRadioEvent(FrequencyChanged);
|
||||
|
||||
if (!mPI.IsNull()) {
|
||||
mPI.SetNull();
|
||||
NotifyFMRadioEvent(PIChanged);
|
||||
}
|
||||
if (!mPTY.IsNull()) {
|
||||
mPTY.SetNull();
|
||||
NotifyFMRadioEvent(PTYChanged);
|
||||
}
|
||||
if (mPSNameSet) {
|
||||
mPSNameSet = false;
|
||||
mPSName.Truncate();
|
||||
NotifyFMRadioEvent(PSChanged);
|
||||
}
|
||||
if (mRadiotextSet) {
|
||||
mRadiotextSet = false;
|
||||
mRadiotext.Truncate();
|
||||
NotifyFMRadioEvent(RadiotextChanged);
|
||||
}
|
||||
mRDSGroupSet = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -141,10 +229,85 @@ FMRadioChild::RecvNotifyEnabledChanged(const bool& aEnabled,
|
||||
{
|
||||
mEnabled = aEnabled;
|
||||
mFrequency = aFrequency;
|
||||
if (!mEnabled) {
|
||||
mPI.SetNull();
|
||||
mPTY.SetNull();
|
||||
mPSName.Truncate();
|
||||
mRadiotext.Truncate();
|
||||
mRDSGroupSet = false;
|
||||
mPSNameSet = false;
|
||||
mRadiotextSet = false;
|
||||
}
|
||||
NotifyFMRadioEvent(EnabledChanged);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
FMRadioChild::RecvNotifyRDSEnabledChanged(const bool& aEnabled)
|
||||
{
|
||||
mRDSEnabled = aEnabled;
|
||||
NotifyFMRadioEvent(RDSEnabledChanged);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
FMRadioChild::RecvNotifyPIChanged(const bool& aValid,
|
||||
const uint16_t& aCode)
|
||||
{
|
||||
if (aValid) {
|
||||
mPI.SetValue(aCode);
|
||||
} else {
|
||||
mPI.SetNull();
|
||||
}
|
||||
NotifyFMRadioEvent(PIChanged);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
FMRadioChild::RecvNotifyPTYChanged(const bool& aValid,
|
||||
const uint8_t& aPTY)
|
||||
{
|
||||
if (aValid) {
|
||||
mPTY.SetValue(aPTY);
|
||||
} else {
|
||||
mPTY.SetNull();
|
||||
}
|
||||
NotifyFMRadioEvent(PTYChanged);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
FMRadioChild::RecvNotifyPSChanged(const nsString& aPSName)
|
||||
{
|
||||
mPSNameSet = true;
|
||||
mPSName = aPSName;
|
||||
NotifyFMRadioEvent(PSChanged);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
FMRadioChild::RecvNotifyRadiotextChanged(const nsString& aRadiotext)
|
||||
{
|
||||
mRadiotextSet = true;
|
||||
mRadiotext = aRadiotext;
|
||||
NotifyFMRadioEvent(RadiotextChanged);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
FMRadioChild::RecvNotifyNewRDSGroup(const uint64_t& aGroup)
|
||||
{
|
||||
uint16_t grouptype = (aGroup >> 43) & 0x1F;
|
||||
if (!(mRDSGroupMask & (1 << grouptype))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
mRDSGroupSet = true;
|
||||
mRDSGroup = aGroup;
|
||||
NotifyFMRadioEvent(NewRDSGroup);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
FMRadioChild::Recv__delete__()
|
||||
{
|
||||
|
@ -34,10 +34,16 @@ public:
|
||||
|
||||
/* IFMRadioService */
|
||||
virtual bool IsEnabled() const MOZ_OVERRIDE;
|
||||
virtual bool IsRDSEnabled() const MOZ_OVERRIDE;
|
||||
virtual double GetFrequency() const MOZ_OVERRIDE;
|
||||
virtual double GetFrequencyUpperBound() const MOZ_OVERRIDE;
|
||||
virtual double GetFrequencyLowerBound() const MOZ_OVERRIDE;
|
||||
virtual double GetChannelWidth() const MOZ_OVERRIDE;
|
||||
virtual Nullable<unsigned short> GetPi() const MOZ_OVERRIDE;
|
||||
virtual Nullable<uint8_t> GetPty() const MOZ_OVERRIDE;
|
||||
virtual bool GetPs(nsString& aPSName) MOZ_OVERRIDE;
|
||||
virtual bool GetRt(nsString& aRadiotext) MOZ_OVERRIDE;
|
||||
virtual bool GetRdsgroup(uint64_t& aRDSGroup) MOZ_OVERRIDE;
|
||||
|
||||
virtual void Enable(double aFrequency,
|
||||
FMRadioReplyRunnable* aReplyRunnable) MOZ_OVERRIDE;
|
||||
@ -47,6 +53,9 @@ public:
|
||||
virtual void Seek(mozilla::hal::FMRadioSeekDirection aDirection,
|
||||
FMRadioReplyRunnable* aReplyRunnable) MOZ_OVERRIDE;
|
||||
virtual void CancelSeek(FMRadioReplyRunnable* aReplyRunnable) MOZ_OVERRIDE;
|
||||
virtual void SetRDSGroupMask(uint32_t aRDSGroupMask) MOZ_OVERRIDE;
|
||||
virtual void EnableRDS(FMRadioReplyRunnable* aReplyRunnable) MOZ_OVERRIDE;
|
||||
virtual void DisableRDS(FMRadioReplyRunnable* aReplyRunnable) MOZ_OVERRIDE;
|
||||
|
||||
virtual void AddObserver(FMRadioEventObserver* aObserver) MOZ_OVERRIDE;
|
||||
virtual void RemoveObserver(FMRadioEventObserver* aObserver) MOZ_OVERRIDE;
|
||||
@ -64,6 +73,26 @@ public:
|
||||
RecvNotifyEnabledChanged(const bool& aEnabled,
|
||||
const double& aFrequency) MOZ_OVERRIDE;
|
||||
|
||||
virtual bool
|
||||
RecvNotifyRDSEnabledChanged(const bool& aEnabled) MOZ_OVERRIDE;
|
||||
|
||||
virtual bool
|
||||
RecvNotifyPIChanged(const bool& aValid,
|
||||
const uint16_t& aCode) MOZ_OVERRIDE;
|
||||
|
||||
virtual bool
|
||||
RecvNotifyPTYChanged(const bool& aValid,
|
||||
const uint8_t& aPTY) MOZ_OVERRIDE;
|
||||
|
||||
virtual bool
|
||||
RecvNotifyPSChanged(const nsString& aPSName) MOZ_OVERRIDE;
|
||||
|
||||
virtual bool
|
||||
RecvNotifyRadiotextChanged(const nsString& aRadiotext) MOZ_OVERRIDE;
|
||||
|
||||
virtual bool
|
||||
RecvNotifyNewRDSGroup(const uint64_t& aGroup) MOZ_OVERRIDE;
|
||||
|
||||
virtual PFMRadioRequestChild*
|
||||
AllocPFMRadioRequestChild(const FMRadioRequestArgs& aArgs) MOZ_OVERRIDE;
|
||||
|
||||
@ -78,10 +107,20 @@ private:
|
||||
inline void NotifyFMRadioEvent(FMRadioEventType aType);
|
||||
|
||||
bool mEnabled;
|
||||
bool mRDSEnabled;
|
||||
bool mRDSGroupSet;
|
||||
bool mPSNameSet;
|
||||
bool mRadiotextSet;
|
||||
double mFrequency;
|
||||
double mUpperBound;
|
||||
double mLowerBound;
|
||||
double mChannelWidth;
|
||||
Nullable<unsigned short> mPI;
|
||||
Nullable<uint8_t> mPTY;
|
||||
nsAutoString mPSName;
|
||||
nsAutoString mRadiotext;
|
||||
uint64_t mRDSGroup;
|
||||
uint32_t mRDSGroupMask;
|
||||
|
||||
FMRadioEventObserverList mObserverList;
|
||||
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include "FMRadioParent.h"
|
||||
#include "mozilla/unused.h"
|
||||
#include "mozilla/dom/ContentParent.h"
|
||||
#include "mozilla/DebugOnly.h"
|
||||
#include "FMRadioRequestParent.h"
|
||||
#include "FMRadioService.h"
|
||||
|
||||
@ -69,6 +70,12 @@ FMRadioParent::AllocPFMRadioRequestParent(const FMRadioRequestArgs& aArgs)
|
||||
case FMRadioRequestArgs::TCancelSeekRequestArgs:
|
||||
IFMRadioService::Singleton()->CancelSeek(requestParent);
|
||||
break;
|
||||
case FMRadioRequestArgs::TEnableRDSArgs:
|
||||
IFMRadioService::Singleton()->EnableRDS(requestParent);
|
||||
break;
|
||||
case FMRadioRequestArgs::TDisableRDSArgs:
|
||||
IFMRadioService::Singleton()->DisableRDS(requestParent);
|
||||
break;
|
||||
default:
|
||||
MOZ_CRASH();
|
||||
}
|
||||
@ -98,6 +105,43 @@ FMRadioParent::Notify(const FMRadioEventType& aType)
|
||||
IFMRadioService::Singleton()->IsEnabled(),
|
||||
IFMRadioService::Singleton()->GetFrequency());
|
||||
break;
|
||||
case RDSEnabledChanged:
|
||||
unused << SendNotifyRDSEnabledChanged(
|
||||
IFMRadioService::Singleton()->IsRDSEnabled());
|
||||
break;
|
||||
case PIChanged: {
|
||||
Nullable<unsigned short> pi =
|
||||
IFMRadioService::Singleton()->GetPi();
|
||||
unused << SendNotifyPIChanged(!pi.IsNull(),
|
||||
pi.IsNull() ? 0 : pi.Value());
|
||||
break;
|
||||
}
|
||||
case PTYChanged: {
|
||||
Nullable<uint8_t> pty = IFMRadioService::Singleton()->GetPty();
|
||||
unused << SendNotifyPTYChanged(!pty.IsNull(),
|
||||
pty.IsNull() ? 0 : pty.Value());
|
||||
break;
|
||||
}
|
||||
case PSChanged: {
|
||||
nsAutoString psname;
|
||||
IFMRadioService::Singleton()->GetPs(psname);
|
||||
unused << SendNotifyPSChanged(psname);
|
||||
break;
|
||||
}
|
||||
case RadiotextChanged: {
|
||||
nsAutoString radiotext;
|
||||
IFMRadioService::Singleton()->GetRt(radiotext);
|
||||
unused << SendNotifyRadiotextChanged(radiotext);
|
||||
break;
|
||||
}
|
||||
case NewRDSGroup: {
|
||||
uint64_t group;
|
||||
DebugOnly<bool> rdsgroupset =
|
||||
IFMRadioService::Singleton()->GetRdsgroup(group);
|
||||
MOZ_ASSERT(rdsgroupset);
|
||||
unused << SendNotifyNewRDSGroup(group);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
NS_RUNTIMEABORT("not reached");
|
||||
break;
|
||||
@ -111,5 +155,12 @@ FMRadioParent::RecvEnableAudio(const bool& aAudioEnabled)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
FMRadioParent::RecvSetRDSGroupMask(const uint32_t& aRDSGroupMask)
|
||||
{
|
||||
IFMRadioService::Singleton()->SetRDSGroupMask(aRDSGroupMask);
|
||||
return true;
|
||||
}
|
||||
|
||||
END_FMRADIO_NAMESPACE
|
||||
|
||||
|
@ -39,6 +39,9 @@ public:
|
||||
|
||||
virtual bool
|
||||
RecvEnableAudio(const bool& aAudioEnabled) MOZ_OVERRIDE;
|
||||
|
||||
virtual bool
|
||||
RecvSetRDSGroupMask(const uint32_t& aRDSGroupMask) MOZ_OVERRIDE;
|
||||
};
|
||||
|
||||
END_FMRADIO_NAMESPACE
|
||||
|
@ -34,6 +34,14 @@ struct CancelSeekRequestArgs
|
||||
{
|
||||
};
|
||||
|
||||
struct EnableRDSArgs
|
||||
{
|
||||
};
|
||||
|
||||
struct DisableRDSArgs
|
||||
{
|
||||
};
|
||||
|
||||
union FMRadioRequestArgs
|
||||
{
|
||||
EnableRequestArgs;
|
||||
@ -41,6 +49,8 @@ union FMRadioRequestArgs
|
||||
SetFrequencyRequestArgs;
|
||||
SeekRequestArgs;
|
||||
CancelSeekRequestArgs;
|
||||
EnableRDSArgs;
|
||||
DisableRDSArgs;
|
||||
};
|
||||
|
||||
struct StatusInfo
|
||||
@ -66,6 +76,30 @@ child:
|
||||
* Sent when the power state of FM radio HW is changed.
|
||||
*/
|
||||
NotifyEnabledChanged(bool enabled, double frequency);
|
||||
/**
|
||||
* Sent when RDS is enabled or disabled.
|
||||
*/
|
||||
NotifyRDSEnabledChanged(bool enabled);
|
||||
/**
|
||||
* Sent when we have a new PI code.
|
||||
*/
|
||||
NotifyPIChanged(bool valid, uint16_t code);
|
||||
/**
|
||||
* Sent when we have a new PTY
|
||||
*/
|
||||
NotifyPTYChanged(bool valid, uint8_t pty);
|
||||
/**
|
||||
* Sent when we have a new PS name.
|
||||
*/
|
||||
NotifyPSChanged(nsString psname);
|
||||
/**
|
||||
* Sent when we have new radiotext.
|
||||
*/
|
||||
NotifyRadiotextChanged(nsString radiotext);
|
||||
/**
|
||||
* Sent when a full RDS group is received.
|
||||
*/
|
||||
NotifyNewRDSGroup(uint64_t data);
|
||||
|
||||
__delete__();
|
||||
|
||||
@ -91,6 +125,11 @@ parent:
|
||||
* Enable/Disable audio
|
||||
*/
|
||||
EnableAudio(bool audioEnabled);
|
||||
|
||||
/**
|
||||
* Set RDS group mask
|
||||
*/
|
||||
SetRDSGroupMask(uint32_t groupMask);
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
@ -6,6 +6,9 @@ interface FMRadio : EventTarget {
|
||||
/* Indicates if the FM radio is enabled. */
|
||||
readonly attribute boolean enabled;
|
||||
|
||||
/* Indicates if RDS reception is enabled */
|
||||
readonly attribute boolean rdsEnabled;
|
||||
|
||||
/* Indicates if the antenna is plugged and available. */
|
||||
readonly attribute boolean antennaAvailable;
|
||||
|
||||
@ -31,12 +34,58 @@ interface FMRadio : EventTarget {
|
||||
*/
|
||||
readonly attribute double channelWidth;
|
||||
|
||||
/**
|
||||
* This is a mask consisting of bits corresponding to
|
||||
* (1 << groupcode) that can be specified to receive
|
||||
* raw RDS groups of specific group types. Note that
|
||||
* groupcode corresponds to the upper 5 bits in block B.
|
||||
*/
|
||||
attribute unsigned long rdsGroupMask;
|
||||
|
||||
/**
|
||||
* The Program Identification (PI) code.
|
||||
* Available if RDS is enabled on both the station and on this device.
|
||||
* The value is null otherwise.
|
||||
*/
|
||||
readonly attribute unsigned short? pi;
|
||||
|
||||
/**
|
||||
* The Program Type (PTY) code.
|
||||
* Available if RDS is enabled on both the station and on this device.
|
||||
* The value is null otherwise.
|
||||
*/
|
||||
readonly attribute octet? pty;
|
||||
|
||||
/**
|
||||
* The Program Service (PS) name.
|
||||
* Available if RDS is enabled on the station and on this device
|
||||
*/
|
||||
readonly attribute DOMString? ps;
|
||||
|
||||
/**
|
||||
* The radiotext, as provided by group 2A/2B.
|
||||
* Available if RDS is enabled on the station and on this device
|
||||
*/
|
||||
readonly attribute DOMString? rt;
|
||||
|
||||
/**
|
||||
* The last RDS group received.
|
||||
* Available if RDS is enabled on the station and on this device
|
||||
*/
|
||||
readonly attribute Uint16Array? rdsgroup;
|
||||
|
||||
/* Fired when the FM radio is enabled. */
|
||||
attribute EventHandler onenabled;
|
||||
|
||||
/* Fired when the FM radio is disabled. */
|
||||
attribute EventHandler ondisabled;
|
||||
|
||||
/* Fired when the RDS is enabled. */
|
||||
attribute EventHandler onrdsenabled;
|
||||
|
||||
/* Fired when the RDS is disabled. */
|
||||
attribute EventHandler onrdsdisabled;
|
||||
|
||||
/**
|
||||
* Fired when the antenna becomes available or unavailable, i.e., fired when
|
||||
* the antennaAvailable attribute changes.
|
||||
@ -46,6 +95,21 @@ interface FMRadio : EventTarget {
|
||||
/* Fired when the FM radio's frequency is changed. */
|
||||
attribute EventHandler onfrequencychange;
|
||||
|
||||
/* Fired when the PI code changes */
|
||||
attribute EventHandler onpichange;
|
||||
|
||||
/* Fired when the PTY changes */
|
||||
attribute EventHandler onptychange;
|
||||
|
||||
/* Fired when the PS name changes */
|
||||
attribute EventHandler onpschange;
|
||||
|
||||
/* Fired when the radiotext changes */
|
||||
attribute EventHandler onrtchange;
|
||||
|
||||
/* Fired when we get a new RDS group */
|
||||
attribute EventHandler onnewrdsgroup;
|
||||
|
||||
/**
|
||||
* Power the FM radio off. The disabled event will be fired if this request
|
||||
* completes successfully.
|
||||
@ -94,5 +158,19 @@ interface FMRadio : EventTarget {
|
||||
* error will be fired.
|
||||
*/
|
||||
DOMRequest cancelSeek();
|
||||
|
||||
/**
|
||||
* Enable RDS reception.
|
||||
*
|
||||
* If the radio is off, RDS will be enabled when the radio is turned on.
|
||||
*/
|
||||
DOMRequest enableRDS();
|
||||
|
||||
/**
|
||||
* Disable RDS reception.
|
||||
*
|
||||
* If the radio is off, RDS will not be enabled when the radio is turned on.
|
||||
*/
|
||||
DOMRequest disableRDS();
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user