michael@0: /* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */ michael@0: /* vim: set ts=2 et sw=2 tw=80: */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this file, michael@0: * You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #ifndef mozilla_dom_fmradioservice_h__ michael@0: #define mozilla_dom_fmradioservice_h__ michael@0: michael@0: #include "mozilla/dom/PFMRadioRequest.h" michael@0: #include "FMRadioCommon.h" michael@0: #include "mozilla/Hal.h" michael@0: #include "mozilla/StaticPtr.h" michael@0: #include "mozilla/Services.h" michael@0: #include "nsThreadUtils.h" michael@0: #include "nsIObserver.h" michael@0: #include "nsXULAppAPI.h" michael@0: michael@0: BEGIN_FMRADIO_NAMESPACE michael@0: michael@0: class FMRadioReplyRunnable : public nsRunnable michael@0: { michael@0: public: michael@0: FMRadioReplyRunnable() : mResponseType(SuccessResponse()) {} michael@0: virtual ~FMRadioReplyRunnable() {} michael@0: michael@0: void michael@0: SetReply(const FMRadioResponseType& aResponseType) michael@0: { michael@0: mResponseType = aResponseType; michael@0: } michael@0: michael@0: protected: michael@0: FMRadioResponseType mResponseType; michael@0: }; michael@0: michael@0: /** michael@0: * The FMRadio Service Interface for FMRadio. michael@0: * michael@0: * There are two concrete classes which implement this interface: michael@0: * - FMRadioService michael@0: * It's used in the main process, implements all the logics about FM Radio. michael@0: * michael@0: * - FMRadioChild michael@0: * It's used in subprocess. It's a kind of proxy which just sends all michael@0: * the requests to main process through IPC channel. michael@0: * michael@0: * All the requests coming from the content page will be redirected to the michael@0: * concrete class object. michael@0: * michael@0: * Consider navigator.mozFMRadio.enable(). Here is the call sequence: michael@0: * - OOP michael@0: * Child: michael@0: * (1) Call navigator.mozFMRadio.enable(). michael@0: * (2) Return a DOMRequest object, and call FMRadioChild.Enable() with a michael@0: * FMRadioReplyRunnable object. michael@0: * (3) Send IPC message to main process. michael@0: * Parent: michael@0: * (4) Call FMRadioService::Enable() with a FMRadioReplyRunnable object. michael@0: * (5) Call hal::EnableFMRadio(). michael@0: * (6) Notify FMRadioService object when FM radio HW is enabled. michael@0: * (7) Dispatch the FMRadioReplyRunnable object created in (4). michael@0: * (8) Send IPC message back to child process. michael@0: * Child: michael@0: * (9) Dispatch the FMRadioReplyRunnable object created in (2). michael@0: * (10) Fire success callback of the DOMRequest Object created in (2). michael@0: * _ _ _ _ _ _ _ _ _ _ _ _ _ _ michael@0: * | OOP | michael@0: * | | michael@0: * Page FMRadio | FMRadioChild IPC | FMRadioService Hal michael@0: * | (1) | | | | | | | michael@0: * |----->| (2) | | | | | | michael@0: * | |--------|--------->| (3) | | | | michael@0: * | | | |-----------> | | (4) | | michael@0: * | | | | |--|---------->| (5) | michael@0: * | | | | | | |--------->| michael@0: * | | | | | | | (6) | michael@0: * | | | | | | (7) |<---------| michael@0: * | | | | (8) |<-|-----------| | michael@0: * | | (9) | |<----------- | | | | michael@0: * | (10) |<-------|----------| | | | | michael@0: * |<-----| | | | | | | michael@0: * | | michael@0: * |_ _ _ _ _ _ _ _ _ _ _ _ _ _| michael@0: * - non-OOP michael@0: * In non-OOP model, we don't need to send messages between processes, so michael@0: * the call sequences are much more simpler, it almost just follows the michael@0: * sequences presented in OOP model: (1) (2) (5) (6) (9) and (10). michael@0: * michael@0: */ michael@0: class IFMRadioService michael@0: { michael@0: protected: michael@0: virtual ~IFMRadioService() { } michael@0: michael@0: public: michael@0: virtual bool IsEnabled() const = 0; michael@0: virtual double GetFrequency() const = 0; michael@0: virtual double GetFrequencyUpperBound() const = 0; michael@0: virtual double GetFrequencyLowerBound() const = 0; michael@0: virtual double GetChannelWidth() const = 0; michael@0: michael@0: virtual void Enable(double aFrequency, FMRadioReplyRunnable* aReplyRunnable) = 0; michael@0: virtual void Disable(FMRadioReplyRunnable* aReplyRunnable) = 0; michael@0: virtual void SetFrequency(double aFrequency, FMRadioReplyRunnable* aReplyRunnable) = 0; michael@0: virtual void Seek(mozilla::hal::FMRadioSeekDirection aDirection, michael@0: FMRadioReplyRunnable* aReplyRunnable) = 0; michael@0: virtual void CancelSeek(FMRadioReplyRunnable* aReplyRunnable) = 0; michael@0: michael@0: /** michael@0: * Register handler to receive the FM Radio events, including: michael@0: * - StateChangedEvent michael@0: * - FrequencyChangedEvent michael@0: * michael@0: * Called by FMRadio and FMRadioParent. michael@0: */ michael@0: virtual void AddObserver(FMRadioEventObserver* aObserver) = 0; michael@0: virtual void RemoveObserver(FMRadioEventObserver* aObserver) = 0; michael@0: michael@0: // Enable/Disable FMRadio michael@0: virtual void EnableAudio(bool aAudioEnabled) = 0; michael@0: michael@0: /** michael@0: * Static method to return the singleton instance. If it's in the child michael@0: * process, we will get an object of FMRadioChild. michael@0: */ michael@0: static IFMRadioService* Singleton(); michael@0: }; michael@0: michael@0: enum FMRadioState michael@0: { michael@0: Disabled, michael@0: Disabling, michael@0: Enabling, michael@0: Enabled, michael@0: Seeking michael@0: }; michael@0: michael@0: class FMRadioService MOZ_FINAL : public IFMRadioService michael@0: , public hal::FMRadioObserver michael@0: , public nsIObserver michael@0: { michael@0: friend class ReadAirplaneModeSettingTask; michael@0: friend class SetFrequencyRunnable; michael@0: michael@0: public: michael@0: static FMRadioService* Singleton(); michael@0: virtual ~FMRadioService(); michael@0: michael@0: NS_DECL_ISUPPORTS michael@0: michael@0: virtual bool IsEnabled() const MOZ_OVERRIDE; michael@0: virtual double GetFrequency() const MOZ_OVERRIDE; michael@0: virtual double GetFrequencyUpperBound() const MOZ_OVERRIDE; michael@0: virtual double GetFrequencyLowerBound() const MOZ_OVERRIDE; michael@0: virtual double GetChannelWidth() const MOZ_OVERRIDE; michael@0: michael@0: virtual void Enable(double aFrequency, michael@0: FMRadioReplyRunnable* aReplyRunnable) MOZ_OVERRIDE; michael@0: virtual void Disable(FMRadioReplyRunnable* aReplyRunnable) MOZ_OVERRIDE; michael@0: virtual void SetFrequency(double aFrequency, michael@0: FMRadioReplyRunnable* aReplyRunnable) MOZ_OVERRIDE; michael@0: virtual void Seek(mozilla::hal::FMRadioSeekDirection aDirection, michael@0: FMRadioReplyRunnable* aReplyRunnable) MOZ_OVERRIDE; michael@0: virtual void CancelSeek(FMRadioReplyRunnable* aReplyRunnable) MOZ_OVERRIDE; michael@0: michael@0: virtual void AddObserver(FMRadioEventObserver* aObserver) MOZ_OVERRIDE; michael@0: virtual void RemoveObserver(FMRadioEventObserver* aObserver) MOZ_OVERRIDE; michael@0: michael@0: virtual void EnableAudio(bool aAudioEnabled) MOZ_OVERRIDE; michael@0: michael@0: /* FMRadioObserver */ michael@0: void Notify(const hal::FMRadioOperationInformation& aInfo) MOZ_OVERRIDE; michael@0: michael@0: NS_DECL_NSIOBSERVER michael@0: michael@0: protected: michael@0: FMRadioService(); michael@0: michael@0: private: michael@0: int32_t RoundFrequency(double aFrequencyInMHz); michael@0: michael@0: void NotifyFMRadioEvent(FMRadioEventType aType); michael@0: void DoDisable(); michael@0: void TransitionState(const FMRadioResponseType& aResponse, FMRadioState aState); michael@0: void SetState(FMRadioState aState); michael@0: void UpdatePowerState(); michael@0: void UpdateFrequency(); michael@0: michael@0: private: michael@0: bool mEnabled; michael@0: michael@0: int32_t mPendingFrequencyInKHz; michael@0: michael@0: FMRadioState mState; michael@0: michael@0: bool mHasReadAirplaneModeSetting; michael@0: bool mAirplaneModeEnabled; michael@0: michael@0: double mUpperBoundInKHz; michael@0: double mLowerBoundInKHz; michael@0: double mChannelWidthInKHz; michael@0: michael@0: nsRefPtr mPendingRequest; michael@0: michael@0: FMRadioEventObserverList mObserverList; michael@0: michael@0: static StaticRefPtr sFMRadioService; michael@0: }; michael@0: michael@0: END_FMRADIO_NAMESPACE michael@0: michael@0: #endif // mozilla_dom_fmradioservice_h__ michael@0: