--- a/dom/tv/TVChannel.cpp
+++ b/dom/tv/TVChannel.cpp
@@ -12,18 +12,17 @@
#include "mozilla/dom/TVUtils.h"
#include "nsITVService.h"
#include "nsServiceManagerUtils.h"
#include "TVChannel.h"
namespace mozilla {
namespace dom {
-NS_IMPL_CYCLE_COLLECTION_INHERITED(TVChannel, DOMEventTargetHelper,
- mTVService, mSource)
+NS_IMPL_CYCLE_COLLECTION_INHERITED(TVChannel, DOMEventTargetHelper, mSource)
NS_IMPL_ADDREF_INHERITED(TVChannel, DOMEventTargetHelper)
NS_IMPL_RELEASE_INHERITED(TVChannel, DOMEventTargetHelper)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(TVChannel)
NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
TVChannel::TVChannel(nsPIDOMWindowInner* aWindow,
@@ -62,19 +61,16 @@ TVChannel::Init(nsITVChannelData* aData)
aData->GetNetworkId(mNetworkId);
aData->GetTransportStreamId(mTransportStreamId);
aData->GetServiceId(mServiceId);
aData->GetName(mName);
aData->GetNumber(mNumber);
aData->GetIsEmergency(&mIsEmergency);
aData->GetIsFree(&mIsFree);
- mTVService = TVServiceFactory::AutoCreateTVService();
- NS_ENSURE_TRUE(mTVService, false);
-
return true;
}
/* virtual */ JSObject*
TVChannel::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
{
return TVChannelBinding::Wrap(aCx, this, aGivenProto);
}
@@ -91,35 +87,36 @@ TVChannel::GetPrograms(const TVGetProgra
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(GetOwner());
MOZ_ASSERT(global);
RefPtr<Promise> promise = Promise::Create(global, aRv);
if (NS_WARN_IF(aRv.Failed())) {
return nullptr;
}
+ nsCOMPtr<nsITVService> service = do_GetService(TV_SERVICE_CONTRACTID);
+ if (NS_WARN_IF(!service)) {
+ promise->MaybeReject(NS_ERROR_DOM_ABORT_ERR);
+ }
+
RefPtr<TVTuner> tuner = mSource->Tuner();
nsString tunerId;
tuner->GetId(tunerId);
uint64_t startTime = aOptions.mStartTime.WasPassed() ?
aOptions.mStartTime.Value() :
PR_Now();
uint64_t endTime = aOptions.mDuration.WasPassed() ?
(startTime + aOptions.mDuration.Value()) :
std::numeric_limits<uint64_t>::max();
nsCOMPtr<nsITVServiceCallback> callback =
new TVServiceProgramGetterCallback(this, promise, false);
nsresult rv =
- mTVService->GetPrograms(tunerId,
- ToTVSourceTypeStr(mSource->Type()),
- mNumber,
- startTime,
- endTime,
- callback);
+ service->GetPrograms(tunerId, ToTVSourceTypeStr(mSource->Type()), mNumber,
+ startTime, endTime, callback);
if (NS_WARN_IF(NS_FAILED(rv))) {
promise->MaybeReject(NS_ERROR_DOM_ABORT_ERR);
}
return promise.forget();
}
void
@@ -183,30 +180,31 @@ TVChannel::GetCurrentProgram(ErrorResult
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(GetOwner());
MOZ_ASSERT(global);
RefPtr<Promise> promise = Promise::Create(global, aRv);
if (aRv.Failed()) {
return nullptr;
}
+ nsCOMPtr<nsITVService> service = do_GetService(TV_SERVICE_CONTRACTID);
+ if (NS_WARN_IF(!service)) {
+ promise->MaybeReject(NS_ERROR_DOM_ABORT_ERR);
+ }
+
RefPtr<TVTuner> tuner = mSource->Tuner();
nsString tunerId;
tuner->GetId(tunerId);
// Get only one program from now on.
nsCOMPtr<nsITVServiceCallback> callback =
new TVServiceProgramGetterCallback(this, promise, true);
- nsresult rv =
- mTVService->GetPrograms(tunerId,
- ToTVSourceTypeStr(mSource->Type()),
- mNumber,
- PR_Now(),
- std::numeric_limits<uint64_t>::max(),
- callback);
+ nsresult rv = service->GetPrograms(
+ tunerId, ToTVSourceTypeStr(mSource->Type()), mNumber, PR_Now(),
+ std::numeric_limits<uint64_t>::max(), callback);
if (NS_WARN_IF(NS_FAILED(rv))) {
promise->MaybeReject(NS_ERROR_DOM_ABORT_ERR);
}
return promise.forget();
}
} // namespace dom
--- a/dom/tv/TVChannel.h
+++ b/dom/tv/TVChannel.h
@@ -7,17 +7,16 @@
#ifndef mozilla_dom_TVChannel_h
#define mozilla_dom_TVChannel_h
#include "mozilla/DOMEventTargetHelper.h"
// Include TVChannelBinding.h since enum TVChannelType can't be forward declared.
#include "mozilla/dom/TVChannelBinding.h"
class nsITVChannelData;
-class nsITVService;
namespace mozilla {
namespace dom {
class Promise;
class TVSource;
class TVChannel final : public DOMEventTargetHelper
@@ -65,17 +64,16 @@ public:
private:
TVChannel(nsPIDOMWindowInner* aWindow,
TVSource* aSource);
~TVChannel();
bool Init(nsITVChannelData* aData);
- nsCOMPtr<nsITVService> mTVService;
RefPtr<TVSource> mSource;
nsString mNetworkId;
nsString mTransportStreamId;
nsString mServiceId;
TVChannelType mType;
nsString mNumber;
nsString mName;
bool mIsEmergency;
--- a/dom/tv/TVListeners.cpp
+++ b/dom/tv/TVListeners.cpp
@@ -7,96 +7,131 @@
#include "mozilla/dom/TVSource.h"
#include "mozilla/dom/TVTuner.h"
#include "mozilla/dom/TVUtils.h"
#include "TVListeners.h"
namespace mozilla {
namespace dom {
-NS_IMPL_CYCLE_COLLECTION(TVSourceListener, mSources)
+NS_IMPL_CYCLE_COLLECTION_CLASS(TVSourceListener)
+
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(TVSourceListener)
+ NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSource)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(TVSourceListener)
+ tmp->Shutdown();
+ NS_IMPL_CYCLE_COLLECTION_UNLINK(mSource)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTING_ADDREF(TVSourceListener)
NS_IMPL_CYCLE_COLLECTING_RELEASE(TVSourceListener)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(TVSourceListener)
NS_INTERFACE_MAP_ENTRY(nsITVSourceListener)
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_END
-void
-TVSourceListener::RegisterSource(TVSource* aSource)
+/* static */ already_AddRefed<TVSourceListener>
+TVSourceListener::Create(TVSource* aSource)
+{
+ RefPtr<TVSourceListener> listener = new TVSourceListener(aSource);
+ return (listener->Init()) ? listener.forget() : nullptr;
+}
+
+TVSourceListener::TVSourceListener(TVSource* aSource) : mSource(aSource)
+{
+ MOZ_ASSERT(mSource);
+}
+
+TVSourceListener::~TVSourceListener()
{
- mSources.AppendElement(aSource);
+ Shutdown();
+}
+
+bool
+TVSourceListener::Init()
+{
+ RefPtr<TVTuner> tuner = mSource->Tuner();
+ tuner->GetId(mTunerId);
+
+ nsCOMPtr<nsITVService> service = do_GetService(TV_SERVICE_CONTRACTID);
+ if (NS_WARN_IF(!service)) {
+ return false;
+ }
+
+ nsresult rv = service->RegisterSourceListener(
+ mTunerId, ToTVSourceTypeStr(mSource->Type()), this);
+ return NS_WARN_IF(NS_FAILED(rv)) ? false : true;
}
void
-TVSourceListener::UnregisterSource(TVSource* aSource)
+TVSourceListener::Shutdown()
{
- for (uint32_t i = 0; i < mSources.Length(); i++) {
- if (mSources[i] == aSource) {
- mSources.RemoveElementsAt(i, 1);
- }
+ nsCOMPtr<nsITVService> service = do_GetService(TV_SERVICE_CONTRACTID);
+ if (NS_WARN_IF(!service)) {
+ return;
}
+
+ nsresult rv = service->UnregisterSourceListener(
+ mTunerId, ToTVSourceTypeStr(mSource->Type()), this);
+ NS_WARN_IF(NS_FAILED(rv));
}
/* virtual */ NS_IMETHODIMP
TVSourceListener::NotifyChannelScanned(const nsAString& aTunerId,
const nsAString& aSourceType,
nsITVChannelData* aChannelData)
{
- RefPtr<TVSource> source = GetSource(aTunerId, aSourceType);
- source->NotifyChannelScanned(aChannelData);
- return NS_OK;
+ if (NS_WARN_IF(!IsMatched(aTunerId, aSourceType))) {
+ return NS_ERROR_INVALID_ARG;
+ }
+
+ return mSource->NotifyChannelScanned(aChannelData);
}
/* virtual */ NS_IMETHODIMP
TVSourceListener::NotifyChannelScanComplete(const nsAString& aTunerId,
const nsAString& aSourceType)
{
- RefPtr<TVSource> source = GetSource(aTunerId, aSourceType);
- source->NotifyChannelScanComplete();
- return NS_OK;
+ if (NS_WARN_IF(!IsMatched(aTunerId, aSourceType))) {
+ return NS_ERROR_INVALID_ARG;
+ }
+
+ return mSource->NotifyChannelScanComplete();
}
/* virtual */ NS_IMETHODIMP
TVSourceListener::NotifyChannelScanStopped(const nsAString& aTunerId,
const nsAString& aSourceType)
{
- RefPtr<TVSource> source = GetSource(aTunerId, aSourceType);
- source->NotifyChannelScanStopped();
- return NS_OK;
+ if (NS_WARN_IF(!IsMatched(aTunerId, aSourceType))) {
+ return NS_ERROR_INVALID_ARG;
+ }
+
+ return mSource->NotifyChannelScanStopped();
}
/* virtual */ NS_IMETHODIMP
TVSourceListener::NotifyEITBroadcasted(const nsAString& aTunerId,
const nsAString& aSourceType,
nsITVChannelData* aChannelData,
nsITVProgramData** aProgramDataList,
const uint32_t aCount)
{
- RefPtr<TVSource> source = GetSource(aTunerId, aSourceType);
- source->NotifyEITBroadcasted(aChannelData, aProgramDataList, aCount);
- return NS_OK;
+ if (NS_WARN_IF(!IsMatched(aTunerId, aSourceType))) {
+ return NS_ERROR_INVALID_ARG;
+ }
+
+ return mSource->NotifyEITBroadcasted(aChannelData, aProgramDataList, aCount);
}
-already_AddRefed<TVSource>
-TVSourceListener::GetSource(const nsAString& aTunerId,
+bool
+TVSourceListener::IsMatched(const nsAString& aTunerId,
const nsAString& aSourceType)
{
- for (uint32_t i = 0; i < mSources.Length(); i++) {
- nsString tunerId;
- RefPtr<TVTuner> tuner = mSources[i]->Tuner();
- tuner->GetId(tunerId);
-
- nsString sourceType = ToTVSourceTypeStr(mSources[i]->Type());
-
- if (aTunerId.Equals(tunerId) && aSourceType.Equals(sourceType)) {
- RefPtr<TVSource> source = mSources[i];
- return source.forget();
- }
- }
-
- return nullptr;
+ return aTunerId.Equals(mTunerId) &&
+ ToTVSourceType(aSourceType) == mSource->Type();
}
} // namespace dom
} // namespace mozilla
--- a/dom/tv/TVListeners.h
+++ b/dom/tv/TVListeners.h
@@ -2,40 +2,54 @@
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_TVListeners_h
#define mozilla_dom_TVListeners_h
-#include "mozilla/dom/TVSource.h"
#include "nsCycleCollectionParticipant.h"
#include "nsITVService.h"
-#include "nsTArray.h"
namespace mozilla {
namespace dom {
+class TVSource;
+
+/*
+ * Instead of making |TVSource| class implement |TVSource| (WebIDL) and
+ * |nsITVSourceListener| (XPCOM) at the same time, having an individual class
+ * for |nsITVSourceListener| (XPCOM) interface would help the JS context
+ * recognize |nsITVSourceListener| instances (when it comes to use them in
+ * |TVSimulatorService.js|.)
+ */
class TVSourceListener final : public nsITVSourceListener
{
public:
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_CLASS(TVSourceListener)
NS_DECL_NSITVSOURCELISTENER
- void RegisterSource(TVSource* aSource);
-
- void UnregisterSource(TVSource* aSource);
+ static already_AddRefed<TVSourceListener> Create(TVSource* aSource);
private:
- ~TVSourceListener() {}
+ explicit TVSourceListener(TVSource* aSource);
+
+ ~TVSourceListener();
+
+ bool Init();
+
+ void Shutdown();
- already_AddRefed<TVSource> GetSource(const nsAString& aTunerId,
- const nsAString& aSourceType);
+ bool IsMatched(const nsAString& aTunerId, const nsAString& aSourceType);
+
+ RefPtr<TVSource> mSource;
- nsTArray<RefPtr<TVSource>> mSources;
+ // Store the tuner ID for |UnregisterSourceListener| call in |Shutdown| since
+ // |mSource->Tuner()| may not exist at that moment.
+ nsString mTunerId;
};
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_TVListeners_h
--- a/dom/tv/TVManager.cpp
+++ b/dom/tv/TVManager.cpp
@@ -11,18 +11,18 @@
#include "mozilla/dom/TVTuner.h"
#include "nsITVService.h"
#include "nsServiceManagerUtils.h"
#include "TVManager.h"
namespace mozilla {
namespace dom {
-NS_IMPL_CYCLE_COLLECTION_INHERITED(TVManager, DOMEventTargetHelper, mTVService,
- mTuners, mPendingGetTunersPromises)
+NS_IMPL_CYCLE_COLLECTION_INHERITED(TVManager, DOMEventTargetHelper, mTuners,
+ mPendingGetTunersPromises)
NS_IMPL_ADDREF_INHERITED(TVManager, DOMEventTargetHelper)
NS_IMPL_RELEASE_INHERITED(TVManager, DOMEventTargetHelper)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(TVManager)
NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
TVManager::TVManager(nsPIDOMWindowInner* aWindow)
@@ -40,21 +40,23 @@ TVManager::Create(nsPIDOMWindowInner* aW
{
RefPtr<TVManager> manager = new TVManager(aWindow);
return (manager->Init()) ? manager.forget() : nullptr;
}
bool
TVManager::Init()
{
- mTVService = TVServiceFactory::AutoCreateTVService();
- NS_ENSURE_TRUE(mTVService, false);
+ nsCOMPtr<nsITVService> service = do_GetService(TV_SERVICE_CONTRACTID);
+ if (NS_WARN_IF(!service)) {
+ return false;
+ }
nsCOMPtr<nsITVServiceCallback> callback = new TVServiceTunerGetterCallback(this);
- nsresult rv = mTVService->GetTuners(callback);
+ nsresult rv = service->GetTuners(callback);
NS_ENSURE_SUCCESS(rv, false);
return true;
}
/* virtual */ JSObject*
TVManager::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
{
--- a/dom/tv/TVManager.h
+++ b/dom/tv/TVManager.h
@@ -4,18 +4,16 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_TVManager_h
#define mozilla_dom_TVManager_h
#include "mozilla/DOMEventTargetHelper.h"
-class nsITVService;
-
namespace mozilla {
namespace dom {
class Promise;
class TVTuner;
class TVManager final : public DOMEventTargetHelper
{
@@ -41,17 +39,16 @@ public:
private:
explicit TVManager(nsPIDOMWindowInner* aWindow);
~TVManager();
bool Init();
- nsCOMPtr<nsITVService> mTVService;
nsTArray<RefPtr<TVTuner>> mTuners;
bool mIsReady;
nsTArray<RefPtr<Promise>> mPendingGetTunersPromises;
};
} // namespace dom
} // namespace mozilla
--- a/dom/tv/TVServiceCallbacks.cpp
+++ b/dom/tv/TVServiceCallbacks.cpp
@@ -42,23 +42,41 @@ TVServiceSourceSetterCallback::TVService
TVServiceSourceSetterCallback::~TVServiceSourceSetterCallback()
{
}
/* virtual */ NS_IMETHODIMP
TVServiceSourceSetterCallback::NotifySuccess(nsIArray* aDataList)
{
- // |aDataList| is expected to be null for setter callbacks.
- if (aDataList) {
+ // |aDataList| is expected to be with only one element.
+ if (!aDataList) {
mPromise->MaybeReject(NS_ERROR_DOM_ABORT_ERR);
return NS_ERROR_INVALID_ARG;
}
- nsresult rv = mTuner->SetCurrentSource(mSourceType);
+ uint32_t length;
+ nsresult rv = aDataList->GetLength(&length);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ mPromise->MaybeReject(NS_ERROR_DOM_ABORT_ERR);
+ return rv;
+ }
+ if (length != 1) {
+ mPromise->MaybeReject(NS_ERROR_DOM_ABORT_ERR);
+ return NS_ERROR_INVALID_ARG;
+ }
+
+ nsCOMPtr<nsITVGonkNativeHandleData> handleData =
+ do_QueryElementAt(aDataList, 0);
+ if (NS_WARN_IF(!handleData)) {
+ mPromise->MaybeReject(NS_ERROR_DOM_ABORT_ERR);
+ return rv;
+ }
+
+ rv = mTuner->SetCurrentSource(mSourceType, handleData);
if (NS_WARN_IF(NS_FAILED(rv))) {
mPromise->MaybeReject(rv);
return rv;
}
mPromise->MaybeResolve(JS::UndefinedHandleValue);
return NS_OK;
}
--- a/dom/tv/TVServiceFactory.cpp
+++ b/dom/tv/TVServiceFactory.cpp
@@ -1,40 +1,38 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-#include "mozilla/dom/TVListeners.h"
-#include "mozilla/Preferences.h"
+#include "TVServiceFactory.h"
+
+#ifdef MOZ_WIDGET_GONK
+#include "gonk/TVGonkService.h"
+#endif
#include "nsITVService.h"
#include "nsITVSimulatorService.h"
#include "nsServiceManagerUtils.h"
-#include "TVServiceFactory.h"
+
namespace mozilla {
namespace dom {
/* static */ already_AddRefed<nsITVService>
TVServiceFactory::AutoCreateTVService()
{
- nsresult rv = NS_OK;
- nsCOMPtr<nsITVService> service = do_CreateInstance(TV_SERVICE_CONTRACTID);
- if (!service) {
- // Fallback to the TV Simulator Service
- service = do_CreateInstance(TV_SIMULATOR_SERVICE_CONTRACTID, &rv);
+ nsCOMPtr<nsITVService> service;
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return nullptr;
- }
- }
+#ifdef MOZ_WIDGET_GONK
+ service = new TVGonkService();
+#endif
- rv = service->SetSourceListener(new TVSourceListener());
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return nullptr;
+ if (!service) {
+ // Fallback to TV simulator service, especially for TV simulator on WebIDE.
+ service = do_CreateInstance(TV_SIMULATOR_SERVICE_CONTRACTID);
}
return service.forget();
}
} // namespace dom
} // namespace mozilla
--- a/dom/tv/TVServiceFactory.h
+++ b/dom/tv/TVServiceFactory.h
@@ -4,16 +4,19 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_TVServiceFactory_h
#define mozilla_dom_TVServiceFactory_h
#include "nsCOMPtr.h"
+#define TV_SERVICE_CID \
+ { 0x60fb3c53, 0x017f, 0x4340, { 0x91, 0x1b, 0xd5, 0x5c, 0x31, 0x28, 0x88, 0xb6 } }
+
class nsITVService;
namespace mozilla {
namespace dom {
class TVServiceFactory
{
public:
--- a/dom/tv/TVServiceRunnables.h
+++ b/dom/tv/TVServiceRunnables.h
@@ -27,17 +27,19 @@ class TVServiceNotifyRunnable final : pu
{
public:
TVServiceNotifyRunnable(nsITVServiceCallback* aCallback,
nsIArray* aDataList,
uint16_t aErrorCode = nsITVServiceCallback::TV_ERROR_OK)
: mCallback(aCallback)
, mDataList(aDataList)
, mErrorCode(aErrorCode)
- {}
+ {
+ MOZ_ASSERT(mCallback);
+ }
NS_IMETHOD Run()
{
if (mErrorCode == nsITVServiceCallback::TV_ERROR_OK) {
return mCallback->NotifySuccess(mDataList);
} else {
return mCallback->NotifyError(mErrorCode);
}
--- a/dom/tv/TVSimulatorService.js
+++ b/dom/tv/TVSimulatorService.js
@@ -9,35 +9,45 @@ function debug(aMsg) {
const Cc = Components.classes;
const Cu = Components.utils;
const Ci = Components.interfaces;
const Cr = Components.returnCode;
Cu.importGlobalProperties(["File"]);
Cu.import("resource://gre/modules/Services.jsm");
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
const TV_SIMULATOR_DUMMY_DIRECTORY = "dummy";
const TV_SIMULATOR_DUMMY_FILE = "settings.json";
// See http://seanyhlin.github.io/TV-Manager-API/#idl-def-TVSourceType
const TV_SOURCE_TYPES = ["dvb-t","dvb-t2","dvb-c","dvb-c2","dvb-s",
"dvb-s2","dvb-h","dvb-sh","atsc","atsc-m/h",
"isdb-t","isdb-tb","isdb-s","isdb-c","1seg",
"dtmb","cmmb","t-dmb","s-dmb"];
function containInvalidSourceType(aElement, aIndex, aArray) {
return !TV_SOURCE_TYPES.includes(aElement);
}
// See http://seanyhlin.github.io/TV-Manager-API/#idl-def-TVChannelType
const TV_CHANNEL_TYPES = ["tv","radio","data"];
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-
function TVSimulatorService() {
+ // This is used for saving the registered source listeners. The object literal
+ // is defined as below:
+ // {
+ // "tunerId1": {
+ // "sourceType1": [ /* source listeners */ ],
+ // "sourceType2": [ /* source listeners */ ],
+ // ...
+ // },
+ // ...
+ // }
+ this._sourceListeners = {};
this._internalTuners = null;
this._scanCompleteTimer = null;
this._scanningWrapTunerData = null;
this._init();
}
TVSimulatorService.prototype = {
classID: Components.ID("{94b065ad-d45a-436a-b394-6dabc3cf110f}"),
@@ -192,239 +202,274 @@ TVSimulatorService.prototype = {
}));
this._internalTuners.set(
this._getTunerMapKey(tuner.id, sourceData.type),
wrapTunerData);
}
}
},
- getTuners: function TVSimGetTuners(aCallback) {
+ registerSourceListener: function(aTunerId, aSourceType, aListener) {
+ let tunerSourceListeners = this._sourceListeners[aTunerId];
+ if (!tunerSourceListeners) {
+ tunerSourceListeners = this._sourceListeners[aTunerId] = {};
+ }
+
+ let listeners = tunerSourceListeners[aSourceType];
+ if (!listeners) {
+ listeners = tunerSourceListeners[aSourceType] = [];
+ }
+
+ if (listeners.indexOf(aListener) < 0) {
+ listeners.push(aListener);
+ }
+ },
+
+ unregisterSourceListener: function(aTunerId, aSourceType, aListener) {
+ let tunerSourceListeners = this._sourceListeners[aTunerId];
+ if (!tunerSourceListeners) {
+ return;
+ }
+
+ let listeners = tunerSourceListeners[aSourceType];
+ if (!listeners) {
+ return;
+ }
+
+ let index = listeners.indexOf(aListener);
+ if (index < 0) {
+ return;
+ }
+
+ listeners.splice(index, 1);
+ },
+
+ _getSourceListeners: function(aTunerId, aSourceType) {
+ let tunerSourceListeners = this._sourceListeners[aTunerId];
+ if (!tunerSourceListeners) {
+ return [];
+ }
+
+ let listeners = tunerSourceListeners[aSourceType];
+ if (!listeners) {
+ return [];
+ }
+
+ return listeners;
+ },
+
+ getTuners: function(aCallback) {
if (!aCallback) {
debug("aCallback is null\n");
- return Cr.NS_ERROR_INVALID_ARG;
+ throw Cr.NS_ERROR_INVALID_ARG;
}
let tuners = Cc["@mozilla.org/array;1"]
.createInstance(Ci.nsIMutableArray);
for (let [k,wrapTunerData] of this._internalTuners) {
tuners.appendElement(wrapTunerData.tuner, false);
}
- return aCallback.notifySuccess(tuners);
+ aCallback.notifySuccess(tuners);
},
- setSource: function TVSimSetSource(aTunerId, aSourceType, aCallback) {
+ setSource: function(aTunerId, aSourceType, aCallback) {
if (!aCallback) {
debug("aCallback is null\n");
- return NS_ERROR_INVALID_ARG;
+ throw NS_ERROR_INVALID_ARG;
}
let wrapTunerData = this._getWrapTunerData(aTunerId, aSourceType);
if (!wrapTunerData) {
- return aCallback.notifyError(Ci.nsITVServiceCallback.TV_ERROR_FAILURE);
+ aCallback.notifyError(Ci.nsITVServiceCallback.TV_ERROR_FAILURE);
+ return;
}
- return aCallback.notifySuccess(null);
+
+ let streamHandle = Cc["@mozilla.org/tv/tvgonknativehandledata;1"]
+ .createInstance(Ci.nsITVGonkNativeHandleData);
+ let streamHandles = Cc["@mozilla.org/array;1"]
+ .createInstance(Ci.nsIMutableArray);
+ streamHandles.appendElement(streamHandle, false);
+
+ aCallback.notifySuccess(streamHandles);
},
- startScanningChannels: function TVSimStartScanningChannels(aTunerId, aSourceType, aCallback) {
+ startScanningChannels: function(aTunerId, aSourceType, aCallback) {
if (!aCallback) {
debug("aCallback is null\n");
- return Cr.NS_ERROR_INVALID_ARG;
+ throw Cr.NS_ERROR_INVALID_ARG;
+ }
+
+ if (this._scanningWrapTunerData) {
+ aCallback.notifyError(Cr.NS_ERROR_DOM_INVALID_STATE_ERR);
+ return;
}
let wrapTunerData = this._getWrapTunerData(aTunerId, aSourceType);
if (!wrapTunerData || !wrapTunerData.channels) {
- return aCallback.notifyError(Ci.nsITVServiceCallback.TV_ERROR_FAILURE);
- }
-
- if (this._scanningWrapTunerData) {
- return aCallback.notifyError(Cr.NS_ERROR_DOM_INVALID_STATE_ERR);
+ aCallback.notifyError(Ci.nsITVServiceCallback.TV_ERROR_FAILURE);
+ return;
}
this._scanningWrapTunerData = wrapTunerData;
aCallback.notifySuccess(null);
for (let [key, wrapChannelData] of wrapTunerData.channels) {
- this._sourceListener.notifyChannelScanned(
- wrapTunerData.tuner.id,
- wrapTunerData.sourceType,
- wrapChannelData.channel);
+ for (let listener of this._getSourceListeners(aTunerId, aSourceType)) {
+ listener.notifyChannelScanned(aTunerId, aSourceType, wrapChannelData.channel);
+ }
}
this._scanCompleteTimer = Cc["@mozilla.org/timer;1"]
.createInstance(Ci.nsITimer);
- let rv = this._scanCompleteTimer.initWithCallback(this, 10,
- Ci.nsITimer.TYPE_ONE_SHOT);
- return Cr.NS_OK;
+ this._scanCompleteTimer.initWithCallback(this, 10,
+ Ci.nsITimer.TYPE_ONE_SHOT);
},
- notify: function TVSimTimerCallback(aTimer) {
+ notify: function(aTimer) {
if (!this._scanningWrapTunerData) {
return;
}
this._scanCompleteTimer = null;
- let notifyResult = this._sourceListener.notifyChannelScanComplete(
- this._scanningWrapTunerData.tuner.id,
- this._scanningWrapTunerData.sourceType);
+
+ let tunerId = this._scanningWrapTunerData.tuner.id;
+ let sourceType = this._scanningWrapTunerData.sourceType;
+ let notifyResult = Cr.NS_OK;
+ for (let listener of this._getSourceListeners(tunerId, sourceType)) {
+ notifyResult = listener.notifyChannelScanComplete(tunerId, sourceType);
+ }
this._scanningWrapTunerData = null;
return notifyResult;
},
- stopScanningChannels: function TVSimStopScanningChannels(aTunerId, aSourceType, aCallback) {
+ stopScanningChannels: function(aTunerId, aSourceType, aCallback) {
if (!aCallback) {
debug("aCallback is null\n");
- return Cr.NS_ERROR_INVALID_ARG;
+ throw Cr.NS_ERROR_INVALID_ARG;
}
- if (!this._scanningWrapTunerData) {
- return aCallback.notifyError(Cr.NS_ERROR_DOM_INVALID_STATE_ERR);
+ if (!this._scanningWrapTunerData ||
+ aTunerId != this._scanningWrapTunerData.tuner.id ||
+ aSourceType != this._scanningWrapTunerData.sourceType) {
+ aCallback.notifyError(Cr.NS_ERROR_DOM_INVALID_STATE_ERR);
+ return;
}
- let wrapTunerData = this._getWrapTunerData(aTunerId, aSourceType);
- if (!wrapTunerData) {
- return aCallback.notifyError(Ci.nsITVServiceCallback.TV_ERROR_FAILURE);
- }
+ this._scanningWrapTunerData = null;
if (this._scanCompleteTimer) {
this._scanCompleteTimer.cancel();
this._scanCompleteTimer = null;
}
- if (wrapTunerData.tuner.id === this._scanningWrapTunerData.tuner.id &&
- wrapTunerData.sourceType === this._scanningWrapTunerData.sourceType) {
- this._scanningWrapTunerData = null;
- this._sourceListener.notifyChannelScanStopped(
- wrapTunerData.tuner.id,
- wrapTunerData.sourceType);
+ for (let listener of this._getSourceListeners(aTunerId, aSourceType)) {
+ listener.notifyChannelScanStopped(aTunerId, aSourceType);
}
- return aCallback.notifySuccess(null);
+ aCallback.notifySuccess(null);
},
- clearScannedChannelsCache: function TVSimClearScannedChannelsCache(aTunerId, aSourceType, aCallback) {
- // Doesn't support for this method.
- return Cr.NS_OK;
+ clearScannedChannelsCache: function(aTunerId, aSourceType, aCallback) {
+ // Simulator service doesn't support channel cache, so there's nothing to do here.
},
- setChannel: function TVSimSetChannel(aTunerId, aSourceType, aChannelNumber, aCallback) {
+ setChannel: function(aTunerId, aSourceType, aChannelNumber, aCallback) {
if (!aCallback) {
debug("aCallback is null\n");
- return Cr.NS_ERROR_INVALID_ARG;
+ throw Cr.NS_ERROR_INVALID_ARG;
}
let channel = Cc["@mozilla.org/array;1"]
.createInstance(Ci.nsIMutableArray);
let wrapTunerData = this._getWrapTunerData(aTunerId, aSourceType);
if (!wrapTunerData || !wrapTunerData.channels) {
- return aCallback.notifyError(Ci.nsITVServiceCallback.TV_ERROR_FAILURE);
+ aCallback.notifyError(Ci.nsITVServiceCallback.TV_ERROR_FAILURE);
+ return;
}
let wrapChannelData = wrapTunerData.channels.get(aChannelNumber);
if (!wrapChannelData) {
- return aCallback.notifyError(Ci.nsITVServiceCallback.TV_ERROR_FAILURE);
+ aCallback.notifyError(Ci.nsITVServiceCallback.TV_ERROR_FAILURE);
+ return;
}
channel.appendElement(wrapChannelData.channel, false);
- return aCallback.notifySuccess(channel);
-
+ aCallback.notifySuccess(channel);
},
- getChannels: function TVSimGetChannels(aTunerId, aSourceType, aCallback) {
+ getChannels: function(aTunerId, aSourceType, aCallback) {
if (!aCallback) {
debug("aCallback is null\n");
- return Cr.NS_ERROR_INVALID_ARG;
+ throw Cr.NS_ERROR_INVALID_ARG;
}
let channelArray = Cc["@mozilla.org/array;1"]
.createInstance(Ci.nsIMutableArray);
let wrapTunerData = this._getWrapTunerData(aTunerId, aSourceType);
if (!wrapTunerData || !wrapTunerData.channels) {
- return aCallback.notifyError(Ci.nsITVServiceCallback.TV_ERROR_FAILURE);
+ aCallback.notifyError(Ci.nsITVServiceCallback.TV_ERROR_FAILURE);
+ return;
}
for (let [key, wrapChannelData] of wrapTunerData.channels) {
channelArray.appendElement(wrapChannelData.channel, false);
}
- return aCallback.notifySuccess(channelArray);
+ aCallback.notifySuccess(channelArray);
},
- getPrograms: function TVSimGetPrograms(aTunerId, aSourceType, aChannelNumber, aStartTime, aEndTime, aCallback) {
+ getPrograms: function(aTunerId, aSourceType, aChannelNumber, aStartTime, aEndTime, aCallback) {
if (!aCallback) {
debug("aCallback is null\n");
- return Cr.NS_ERROR_INVALID_ARG;
+ throw Cr.NS_ERROR_INVALID_ARG;
}
let programArray = Cc["@mozilla.org/array;1"]
.createInstance(Ci.nsIMutableArray);
let wrapTunerData = this._getWrapTunerData(aTunerId, aSourceType);
if (!wrapTunerData || !wrapTunerData.channels) {
- return aCallback.notifyError(Ci.nsITVServiceCallback.TV_ERROR_FAILURE);
+ aCallback.notifyError(Ci.nsITVServiceCallback.TV_ERROR_FAILURE);
+ return;
}
let wrapChannelData = wrapTunerData.channels.get(aChannelNumber);
if (!wrapChannelData || !wrapChannelData.programs) {
- return Cr.NS_ERROR_INVALID_ARG;
+ throw Cr.NS_ERROR_INVALID_ARG;
}
for (let program of wrapChannelData.programs) {
programArray.appendElement(program, false);
}
- return aCallback.notifySuccess(programArray);
-
+ aCallback.notifySuccess(programArray);
},
- getOverlayId: function TVSimGetOverlayId(aTunerId, aCallback) {
- if (!aCallback) {
- debug("aCallback is null\n");
- return Cr.NS_ERROR_INVALID_ARG;
- }
-
- // TVSimulatorService does not use this parameter.
- overlayIds = Cc["@mozilla.org/array;1"]
- .createInstance(Ci.nsIMutableArray);
- return aCallback.notifySuccess(overlayIds);
- },
-
- set sourceListener(aListener) {
- this._sourceListener = aListener;
- },
-
- get sourceListener() {
- return this._sourceListener;
- },
-
- getSimulatorVideoBlobURL: function TVSimGetSimulatorVideoBlob(aTunerId,
- aSourceType,
- aChannelNumber,
- aWin) {
+ getSimulatorVideoBlobURL: function(aTunerId, aSourceType, aChannelNumber, aWin) {
let wrapTunerData = this._getWrapTunerData(aTunerId, aSourceType);
if (!wrapTunerData || !wrapTunerData.channels) {
return "";
}
let wrapChannelData = wrapTunerData.channels.get(aChannelNumber);
if (!wrapChannelData || !wrapChannelData.videoFilePath) {
return "";
}
let videoFile = new File(this._getFilePath(wrapChannelData.videoFilePath));
let videoBlobURL = aWin.URL.createObjectURL(videoFile);
return videoBlobURL;
},
- _getDummyData : function TVSimGetDummyData() {
+ _getDummyData : function() {
// Load the setting file from local JSON file.
// Synchrhronous File Reading.
let file = Cc["@mozilla.org/file/local;1"]
.createInstance(Ci.nsILocalFile);
let fstream = Cc["@mozilla.org/network/file-input-stream;1"]
.createInstance(Ci.nsIFileInputStream);
let cstream = Cc["@mozilla.org/intl/converter-input-stream;1"]
@@ -449,42 +494,42 @@ TVSimulatorService.prototype = {
throw e;
} finally {
cstream.close();
}
return settingsStr;
},
- _getTunerMapKey: function TVSimGetTunerMapKey(aTunerId, aSourceType) {
+ _getTunerMapKey: function(aTunerId, aSourceType) {
return JSON.stringify({'tunerId': aTunerId, 'sourceType': aSourceType});
},
- _getWrapTunerData: function TVSimGetWrapTunerData(aTunerId, aSourceType) {
+ _getWrapTunerData: function(aTunerId, aSourceType) {
if (!this._internalTuners || this._internalTuners.size <= 0) {
return null;
}
return this._internalTuners.get(this._getTunerMapKey(aTunerId, aSourceType));
},
- _getFilePath: function TVSimGetFilePathFromDummyDirectory(fileName) {
+ _getFilePath: function(fileName) {
let dsFile = Cc["@mozilla.org/file/directory_service;1"]
.getService(Ci.nsIProperties)
.get("ProfD", Ci.nsIFile);
dsFile.append(TV_SIMULATOR_DUMMY_DIRECTORY);
dsFile.append(fileName);
return dsFile.path;
},
- _validateSettings: function TVSimValidateSettings(aSettingsObject) {
+ _validateSettings: function(aSettingsObject) {
return this._validateTuners(aSettingsObject.tuners);
},
- _validateTuners: function TVSimValidateTuners(aTunersObject) {
+ _validateTuners: function(aTunersObject) {
let tunerIds = new Array();
for (let tuner of aTunersObject) {
if (!tuner.id ||
!tuner.supportedType ||
!tuner.supportedType.length ||
tuner.supportedType.some(containInvalidSourceType) ||
tunerIds.includes(tuner.id)) {
debug("invalid tuner data.");
@@ -494,32 +539,32 @@ TVSimulatorService.prototype = {
if (!this._validateSources(tuner.sources)) {
return false;
}
}
return true;
},
- _validateSources: function TVSimValidateSources(aSourcesObject) {
+ _validateSources: function(aSourcesObject) {
for (let source of aSourcesObject) {
if (!source.type ||
!TV_SOURCE_TYPES.includes(source.type)) {
debug("invalid source data.");
return false;
}
if (!this._validateChannels(source.channels)) {
return false;
}
}
return true;
},
- _validateChannels: function TVSimValidateChannels(aChannelsObject) {
+ _validateChannels: function(aChannelsObject) {
let channelNumbers = new Array();
for (let channel of aChannelsObject) {
if (!channel.networkId ||
!channel.transportStreamId ||
!channel.serviceId ||
!channel.type ||
!TV_CHANNEL_TYPES.includes(channel.type) ||
!channel.number ||
@@ -532,17 +577,17 @@ TVSimulatorService.prototype = {
if (!this._validatePrograms(channel.programs)) {
return false;
}
}
return true;
},
- _validatePrograms: function TVSimValidatePrograms(aProgramsObject) {
+ _validatePrograms: function(aProgramsObject) {
let eventIds = new Array();
for (let program of aProgramsObject) {
if (!program.eventId ||
eventIds.includes(program.eventId) ||
!program.title ||
!program.startTime ||
!program.duration) {
debug("invalid program data.");
--- a/dom/tv/TVSource.cpp
+++ b/dom/tv/TVSource.cpp
@@ -16,32 +16,18 @@
#include "mozilla/dom/TVUtils.h"
#include "nsITVService.h"
#include "nsServiceManagerUtils.h"
#include "TVSource.h"
namespace mozilla {
namespace dom {
-NS_IMPL_CYCLE_COLLECTION_CLASS(TVSource)
-
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(TVSource,
- DOMEventTargetHelper)
- NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTVService)
- NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTuner)
- NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCurrentChannel)
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
-
-NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(TVSource,
- DOMEventTargetHelper)
- tmp->Shutdown();
- NS_IMPL_CYCLE_COLLECTION_UNLINK(mTVService)
- NS_IMPL_CYCLE_COLLECTION_UNLINK(mTuner)
- NS_IMPL_CYCLE_COLLECTION_UNLINK(mCurrentChannel)
-NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+NS_IMPL_CYCLE_COLLECTION_INHERITED(TVSource, DOMEventTargetHelper, mTuner,
+ mCurrentChannel, mSourceListener)
NS_IMPL_ADDREF_INHERITED(TVSource, DOMEventTargetHelper)
NS_IMPL_RELEASE_INHERITED(TVSource, DOMEventTargetHelper)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(TVSource)
NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
TVSource::TVSource(nsPIDOMWindowInner* aWindow,
@@ -52,57 +38,38 @@ TVSource::TVSource(nsPIDOMWindowInner* a
, mType(aType)
, mIsScanning(false)
{
MOZ_ASSERT(mTuner);
}
TVSource::~TVSource()
{
- Shutdown();
}
/* static */ already_AddRefed<TVSource>
TVSource::Create(nsPIDOMWindowInner* aWindow,
TVSourceType aType,
TVTuner* aTuner)
{
RefPtr<TVSource> source = new TVSource(aWindow, aType, aTuner);
return (source->Init()) ? source.forget() : nullptr;
}
bool
TVSource::Init()
{
- mTVService = TVServiceFactory::AutoCreateTVService();
- NS_ENSURE_TRUE(mTVService, false);
-
- nsCOMPtr<nsITVSourceListener> sourceListener;
- mTVService->GetSourceListener(getter_AddRefs(sourceListener));
- NS_ENSURE_TRUE(sourceListener, false);
- (static_cast<TVSourceListener*>(sourceListener.get()))->RegisterSource(this);
+ mSourceListener = TVSourceListener::Create(this);
+ if (NS_WARN_IF(!mSourceListener)) {
+ return false;
+ }
return true;
}
-void
-TVSource::Shutdown()
-{
- if (!mTVService) {
- return;
- }
-
- nsCOMPtr<nsITVSourceListener> sourceListener;
- mTVService->GetSourceListener(getter_AddRefs(sourceListener));
- if (!sourceListener) {
- return;
- }
- (static_cast<TVSourceListener*>(sourceListener.get()))->UnregisterSource(this);
-}
-
/* virtual */ JSObject*
TVSource::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
{
return TVSourceBinding::Wrap(aCx, this, aGivenProto);
}
nsresult
TVSource::SetCurrentChannel(nsITVChannelData* aChannelData)
@@ -175,23 +142,29 @@ TVSource::GetChannels(ErrorResult& aRv)
}
// The operation is prohibited when the source is scanning channels.
if (mIsScanning) {
promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR);
return promise.forget();
}
+ nsCOMPtr<nsITVService> service = do_GetService(TV_SERVICE_CONTRACTID);
+ if (NS_WARN_IF(!service)) {
+ promise->MaybeReject(NS_ERROR_DOM_ABORT_ERR);
+ return promise.forget();
+ }
+
nsString tunerId;
mTuner->GetId(tunerId);
nsCOMPtr<nsITVServiceCallback> callback =
new TVServiceChannelGetterCallback(this, promise);
nsresult rv =
- mTVService->GetChannels(tunerId, ToTVSourceTypeStr(mType), callback);
+ service->GetChannels(tunerId, ToTVSourceTypeStr(mType), callback);
if (NS_WARN_IF(NS_FAILED(rv))) {
promise->MaybeReject(NS_ERROR_DOM_ABORT_ERR);
}
return promise.forget();
}
already_AddRefed<Promise>
@@ -207,23 +180,29 @@ TVSource::SetCurrentChannel(const nsAStr
}
// The operation is prohibited when the source is scanning channels.
if (mIsScanning) {
promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR);
return promise.forget();
}
+ nsCOMPtr<nsITVService> service = do_GetService(TV_SERVICE_CONTRACTID);
+ if (NS_WARN_IF(!service)) {
+ promise->MaybeReject(NS_ERROR_DOM_ABORT_ERR);
+ return promise.forget();
+ }
+
nsString tunerId;
mTuner->GetId(tunerId);
nsCOMPtr<nsITVServiceCallback> callback =
new TVServiceChannelSetterCallback(this, promise, aChannelNumber);
- nsresult rv =
- mTVService->SetChannel(tunerId, ToTVSourceTypeStr(mType), aChannelNumber, callback);
+ nsresult rv = service->SetChannel(tunerId, ToTVSourceTypeStr(mType),
+ aChannelNumber, callback);
if (NS_WARN_IF(NS_FAILED(rv))) {
promise->MaybeReject(NS_ERROR_DOM_ABORT_ERR);
}
return promise.forget();
}
already_AddRefed<Promise>
@@ -233,42 +212,48 @@ TVSource::StartScanning(const TVStartSca
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(GetOwner());
MOZ_ASSERT(global);
RefPtr<Promise> promise = Promise::Create(global, aRv);
if (NS_WARN_IF(aRv.Failed())) {
return nullptr;
}
- nsString tunerId;
- mTuner->GetId(tunerId);
+ nsCOMPtr<nsITVService> service = do_GetService(TV_SERVICE_CONTRACTID);
+ if (NS_WARN_IF(!service)) {
+ promise->MaybeReject(NS_ERROR_DOM_ABORT_ERR);
+ return promise.forget();
+ }
bool isRescanned = aOptions.mIsRescanned.WasPassed() &&
aOptions.mIsRescanned.Value();
if (isRescanned) {
- nsresult rv = mTVService->ClearScannedChannelsCache();
+ nsresult rv = service->ClearScannedChannelsCache();
if (NS_WARN_IF(NS_FAILED(rv))) {
promise->MaybeReject(NS_ERROR_DOM_ABORT_ERR);
return promise.forget();
}
rv = DispatchScanningStateChangedEvent(TVScanningState::Cleared, nullptr);
if (NS_WARN_IF(NS_FAILED(rv))) {
promise->MaybeReject(NS_ERROR_DOM_ABORT_ERR);
return promise.forget();
}
}
+ nsString tunerId;
+ mTuner->GetId(tunerId);
+
// |SetIsScanning(bool)| should be called once |notifySuccess()| of this
// callback is invoked.
nsCOMPtr<nsITVServiceCallback> callback =
new TVServiceChannelScanCallback(this, promise, true);
nsresult rv =
- mTVService->StartScanningChannels(tunerId, ToTVSourceTypeStr(mType), callback);
+ service->StartScanningChannels(tunerId, ToTVSourceTypeStr(mType), callback);
if (NS_WARN_IF(NS_FAILED(rv))) {
promise->MaybeReject(NS_ERROR_DOM_ABORT_ERR);
}
return promise.forget();
}
already_AddRefed<Promise>
@@ -277,25 +262,31 @@ TVSource::StopScanning(ErrorResult& aRv)
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(GetOwner());
MOZ_ASSERT(global);
RefPtr<Promise> promise = Promise::Create(global, aRv);
if (NS_WARN_IF(aRv.Failed())) {
return nullptr;
}
+ nsCOMPtr<nsITVService> service = do_GetService(TV_SERVICE_CONTRACTID);
+ if (NS_WARN_IF(!service)) {
+ promise->MaybeReject(NS_ERROR_DOM_ABORT_ERR);
+ return promise.forget();
+ }
+
nsString tunerId;
mTuner->GetId(tunerId);
// |SetIsScanning(bool)| should be called once |notifySuccess()| of this
// callback is invoked.
nsCOMPtr<nsITVServiceCallback> callback =
new TVServiceChannelScanCallback(this, promise, false);
nsresult rv =
- mTVService->StopScanningChannels(tunerId, ToTVSourceTypeStr(mType), callback);
+ service->StopScanningChannels(tunerId, ToTVSourceTypeStr(mType), callback);
if (NS_WARN_IF(NS_FAILED(rv))) {
promise->MaybeReject(NS_ERROR_DOM_ABORT_ERR);
}
return promise.forget();
}
already_AddRefed<TVTuner>
--- a/dom/tv/TVSource.h
+++ b/dom/tv/TVSource.h
@@ -11,17 +11,17 @@
// Include TVScanningStateChangedEventBinding.h since enum TVScanningState can't
// be forward declared.
#include "mozilla/dom/TVScanningStateChangedEventBinding.h"
// Include TVSourceBinding.h since enum TVSourceType can't be forward declared.
#include "mozilla/dom/TVSourceBinding.h"
class nsITVChannelData;
class nsITVProgramData;
-class nsITVService;
+class nsITVSourceListener;
namespace mozilla {
namespace dom {
class Promise;
class TVChannel;
class TVProgram;
class TVTuner;
@@ -87,28 +87,26 @@ private:
TVSource(nsPIDOMWindowInner* aWindow,
TVSourceType aType,
TVTuner* aTuner);
~TVSource();
bool Init();
- void Shutdown();
-
nsresult DispatchCurrentChannelChangedEvent(TVChannel* aChannel);
nsresult DispatchScanningStateChangedEvent(TVScanningState aState,
TVChannel* aChannel);
nsresult DispatchEITBroadcastedEvent(const Sequence<OwningNonNull<TVProgram>>& aPrograms);
- nsCOMPtr<nsITVService> mTVService;
RefPtr<TVTuner> mTuner;
RefPtr<TVChannel> mCurrentChannel;
+ nsCOMPtr<nsITVSourceListener> mSourceListener;
TVSourceType mType;
bool mIsScanning;
};
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_TVSource_h
--- a/dom/tv/TVTuner.cpp
+++ b/dom/tv/TVTuner.cpp
@@ -1,33 +1,34 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+#include "TVTuner.h"
+
#include "DOMMediaStream.h"
+#include "mozilla/dom/HTMLVideoElement.h"
#include "mozilla/dom/Promise.h"
#include "mozilla/dom/TVCurrentSourceChangedEvent.h"
#include "mozilla/dom/TVServiceCallbacks.h"
#include "mozilla/dom/TVServiceFactory.h"
#include "mozilla/dom/TVSource.h"
#include "mozilla/dom/TVUtils.h"
#include "nsISupportsPrimitives.h"
#include "nsITVService.h"
#include "nsITVSimulatorService.h"
#include "nsServiceManagerUtils.h"
-#include "TVTuner.h"
-#include "mozilla/dom/HTMLVideoElement.h"
namespace mozilla {
namespace dom {
-NS_IMPL_CYCLE_COLLECTION_INHERITED(TVTuner, DOMEventTargetHelper,
- mTVService, mStream, mCurrentSource, mSources)
+NS_IMPL_CYCLE_COLLECTION_INHERITED(TVTuner, DOMEventTargetHelper, mStream,
+ mCurrentSource, mSources)
NS_IMPL_ADDREF_INHERITED(TVTuner, DOMEventTargetHelper)
NS_IMPL_RELEASE_INHERITED(TVTuner, DOMEventTargetHelper)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(TVTuner)
NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
TVTuner::TVTuner(nsPIDOMWindowInner* aWindow)
@@ -76,35 +77,32 @@ TVTuner::Init(nsITVTunerData* aData)
continue;
}
mSupportedSourceTypes.AppendElement(sourceType);
mSources.AppendElement(source);
}
NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(count, supportedSourceTypes);
- mTVService = TVServiceFactory::AutoCreateTVService();
- NS_ENSURE_TRUE(mTVService, false);
-
rv = aData->GetStreamType(&mStreamType);
NS_ENSURE_SUCCESS(rv, false);
return true;
}
/* virtual */ JSObject*
TVTuner::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
{
return TVTunerBinding::Wrap(aCx, this, aGivenProto);
}
nsresult
-TVTuner::SetCurrentSource(TVSourceType aSourceType)
+TVTuner::SetCurrentSource(TVSourceType aSourceType,
+ nsITVGonkNativeHandleData* aHandleData)
{
- ErrorResult error;
if (mCurrentSource) {
if (aSourceType == mCurrentSource->Type()) {
// No actual change.
return NS_OK;
}
// No need to stay tuned for non-current sources.
nsresult rv = mCurrentSource->UnsetCurrentChannel();
@@ -115,20 +113,17 @@ TVTuner::SetCurrentSource(TVSourceType a
for (uint32_t i = 0; i < mSources.Length(); i++) {
if (aSourceType == mSources[i]->Type()) {
mCurrentSource = mSources[i];
break;
}
}
- nsresult rv = InitMediaStream();
- if (NS_FAILED(rv)) {
- return rv;
- }
+ mStream = CreateHwMediaStream(aHandleData);
return DispatchCurrentSourceChangedEvent(mCurrentSource);
}
nsresult
TVTuner::DispatchTVEvent(nsIDOMEvent* aEvent)
{
return DispatchTrustedEvent(aEvent);
@@ -163,21 +158,29 @@ TVTuner::SetCurrentSource(const TVSource
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(GetOwner());
MOZ_ASSERT(global);
RefPtr<Promise> promise = Promise::Create(global, aRv);
if (NS_WARN_IF(aRv.Failed())) {
return nullptr;
}
- // |SetCurrentSource(const TVSourceType)| will be called once |notifySuccess|
- // of the callback is invoked.
+ nsCOMPtr<nsITVService> service = do_GetService(TV_SERVICE_CONTRACTID);
+ if (NS_WARN_IF(!service)) {
+ promise->MaybeReject(NS_ERROR_DOM_ABORT_ERR);
+ }
+
+ // For TV simulator, |SetCurrentSource(TVSourceType)| will be called once
+ // |notifySuccess| of the callback is invoked. On the other hand, for gonk TV,
+ // |SetCurrentSource(TVSourceType, const GonkNativeHandle&)| will be called
+ // once |notifyStreamHandle| of the callback is invoked.
nsCOMPtr<nsITVServiceCallback> callback =
new TVServiceSourceSetterCallback(this, promise, aSourceType);
- nsresult rv = mTVService->SetSource(mId, ToTVSourceTypeStr(aSourceType), callback);
+ nsresult rv =
+ service->SetSource(mId, ToTVSourceTypeStr(aSourceType), callback);
if (NS_WARN_IF(NS_FAILED(rv))) {
promise->MaybeReject(NS_ERROR_DOM_ABORT_ERR);
}
return promise.forget();
}
void
@@ -198,32 +201,53 @@ TVTuner::GetStream() const
{
RefPtr<DOMMediaStream> stream = mStream;
return stream.forget();
}
nsresult
TVTuner::ReloadMediaStream()
{
- return InitMediaStream();
+ // Only TV simulator needs to reload the media stream (during channel changes).
+ if (NS_WARN_IF(nsITVTunerData::TV_STREAM_TYPE_SIMULATOR != mStreamType)) {
+ return NS_ERROR_FAILURE;
+ }
+
+ mStream = CreateSimulatedMediaStream();
+
+ return NS_OK;
}
-nsresult
-TVTuner::InitMediaStream()
+already_AddRefed<DOMMediaStream>
+TVTuner::CreateHwMediaStream(nsITVGonkNativeHandleData* aHandleData)
{
- nsCOMPtr<nsPIDOMWindowInner> window = GetOwner();
- RefPtr<DOMMediaStream> stream = nullptr;
+ RefPtr<DOMMediaStream> stream;
+
if (mStreamType == nsITVTunerData::TV_STREAM_TYPE_HW) {
- stream = DOMHwMediaStream::CreateHwStream(window);
+#ifdef MOZ_WIDGET_GONK
+ nsCOMPtr<nsPIDOMWindowInner> window = GetOwner();
+
+ layers::OverlayImage::SidebandStreamData imageData;
+ aHandleData->GetHandle(imageData.mStream);
+ window->GetInnerWidth(&imageData.mSize.width);
+ window->GetInnerHeight(&imageData.mSize.height);
+
+ RefPtr<layers::OverlayImage> overlayImage = new layers::OverlayImage();
+ overlayImage->SetData(imageData);
+ stream = DOMHwMediaStream::CreateHwStream(window, overlayImage);
+#endif
} else if (mStreamType == nsITVTunerData::TV_STREAM_TYPE_SIMULATOR) {
stream = CreateSimulatedMediaStream();
}
- mStream = stream.forget();
- return NS_OK;
+ if (NS_WARN_IF(!stream)) {
+ return nullptr;
+ }
+
+ return stream.forget();
}
already_AddRefed<DOMMediaStream>
TVTuner::CreateSimulatedMediaStream()
{
nsCOMPtr<nsPIDOMWindowInner> domWin = GetOwner();
if (NS_WARN_IF(!domWin)) {
return nullptr;
@@ -255,17 +279,20 @@ TVTuner::CreateSimulatedMediaStream()
return nullptr;
}
mediaElement->SetLoop(true, error);
if (NS_WARN_IF(error.Failed())) {
return nullptr;
}
- nsCOMPtr<nsITVSimulatorService> simService(do_QueryInterface(mTVService));
+ nsCOMPtr<nsITVService> service = do_GetService(TV_SERVICE_CONTRACTID);
+ MOZ_ASSERT(service);
+
+ nsCOMPtr<nsITVSimulatorService> simService(do_QueryInterface(service));
if (NS_WARN_IF(!simService)) {
return nullptr;
}
if (NS_WARN_IF(!mCurrentSource)) {
return nullptr;
}
--- a/dom/tv/TVTuner.h
+++ b/dom/tv/TVTuner.h
@@ -8,17 +8,17 @@
#define mozilla_dom_TVTuner_h
#include "mozilla/DOMEventTargetHelper.h"
// Include TVTunerBinding.h since enum TVSourceType can't be forward declared.
#include "mozilla/dom/TVTunerBinding.h"
#define VIDEO_TAG NS_LITERAL_STRING("video")
-class nsITVService;
+class nsITVGonkNativeHandleData;
class nsITVTunerData;
namespace mozilla {
class DOMMediaStream;
namespace dom {
@@ -28,23 +28,25 @@ class TVSource;
class TVTuner final : public DOMEventTargetHelper
{
public:
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(TVTuner, DOMEventTargetHelper)
static already_AddRefed<TVTuner> Create(nsPIDOMWindowInner* aWindow,
nsITVTunerData* aData);
+
nsresult NotifyImageSizeChanged(uint32_t aWidth, uint32_t aHeight);
// WebIDL (internal functions)
virtual JSObject* WrapObject(JSContext *aCx, JS::Handle<JSObject*> aGivenProto) override;
- nsresult SetCurrentSource(TVSourceType aSourceType);
+ nsresult SetCurrentSource(TVSourceType aSourceType,
+ nsITVGonkNativeHandleData* aHandleData);
nsresult DispatchTVEvent(nsIDOMEvent* aEvent);
// WebIDL (public APIs)
void GetSupportedSourceTypes(nsTArray<TVSourceType>& aSourceTypes,
ErrorResult& aRv) const;
@@ -67,21 +69,23 @@ private:
explicit TVTuner(nsPIDOMWindowInner* aWindow);
~TVTuner();
bool Init(nsITVTunerData* aData);
nsresult InitMediaStream();
+ already_AddRefed<DOMMediaStream> CreateHwMediaStream(
+ nsITVGonkNativeHandleData* aHandleData);
+
already_AddRefed<DOMMediaStream> CreateSimulatedMediaStream();
nsresult DispatchCurrentSourceChangedEvent(TVSource* aSource);
- nsCOMPtr<nsITVService> mTVService;
RefPtr<DOMMediaStream> mStream;
uint16_t mStreamType;
RefPtr<TVSource> mCurrentSource;
nsTArray<RefPtr<TVSource>> mSources;
nsString mId;
nsTArray<TVSourceType> mSupportedSourceTypes;
};
--- a/dom/tv/TVTypes.cpp
+++ b/dom/tv/TVTypes.cpp
@@ -464,10 +464,34 @@ TVProgramData::SetSubtitleLanguages(uint
nullptr;
for (uint32_t i = 0; i < mSubtitleLanguageCount; i++) {
mSubtitleLanguages[i] = NS_strdup(aLanguages[i]);
}
return NS_OK;
}
+/*
+ * Implementation of TVGonkNativeHandleData
+ */
+
+NS_IMPL_ISUPPORTS(TVGonkNativeHandleData, nsITVGonkNativeHandleData)
+
+TVGonkNativeHandleData::TVGonkNativeHandleData() {}
+
+TVGonkNativeHandleData::~TVGonkNativeHandleData() {}
+
+/* virtual */ NS_IMETHODIMP
+TVGonkNativeHandleData::GetHandle(GonkNativeHandle& aHandle)
+{
+ aHandle = mHandle;
+ return NS_OK;
+}
+
+/* virtual */ NS_IMETHODIMP
+TVGonkNativeHandleData::SetHandle(GonkNativeHandle& aHandle)
+{
+ mHandle = aHandle;
+ return NS_OK;
+}
+
} // namespace dom
} // namespace mozilla
--- a/dom/tv/TVTypes.h
+++ b/dom/tv/TVTypes.h
@@ -2,42 +2,49 @@
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_TVTypes_h
#define mozilla_dom_TVTypes_h
+#include "mozilla/layers/GonkNativeHandle.h"
+#include "mozilla/Tuple.h"
#include "nsITVService.h"
namespace mozilla {
namespace dom {
+typedef Tuple<nsString, nsString, nsCOMPtr<nsITVSourceListener>>
+TVSourceListenerTuple;
+
+using mozilla::layers::GonkNativeHandle;
+
class TVTunerData final : public nsITVTunerData
{
public:
- NS_DECL_ISUPPORTS
+ NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSITVTUNERDATA
TVTunerData();
private:
~TVTunerData();
nsString mId;
char** mSupportedSourceTypes;
uint32_t mCount;
uint16_t mStreamType;
};
class TVChannelData final : public nsITVChannelData
{
public:
- NS_DECL_ISUPPORTS
+ NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSITVCHANNELDATA
TVChannelData();
private:
~TVChannelData();
nsString mNetworkId;
@@ -48,17 +55,17 @@ private:
nsString mName;
bool mIsEmergency;
bool mIsFree;
};
class TVProgramData final : public nsITVProgramData
{
public:
- NS_DECL_ISUPPORTS
+ NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSITVPROGRAMDATA
TVProgramData();
private:
~TVProgramData();
nsString mEventId;
@@ -68,12 +75,26 @@ private:
nsString mDescription;
nsString mRating;
char** mAudioLanguages;
uint32_t mAudioLanguageCount;
char** mSubtitleLanguages;
uint32_t mSubtitleLanguageCount;
};
+class TVGonkNativeHandleData final : public nsITVGonkNativeHandleData
+{
+public:
+ NS_DECL_THREADSAFE_ISUPPORTS
+ NS_DECL_NSITVGONKNATIVEHANDLEDATA
+
+ TVGonkNativeHandleData();
+
+private:
+ ~TVGonkNativeHandleData();
+
+ GonkNativeHandle mHandle;
+};
+
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_TVTypes_h
new file mode 100644
--- /dev/null
+++ b/dom/tv/gonk/TVGonkService.cpp
@@ -0,0 +1,183 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "TVGonkService.h"
+
+#include "mozilla/dom/TVServiceRunnables.h"
+#include "nsCOMPtr.h"
+#include "nsIMutableArray.h"
+#include "nsServiceManagerUtils.h"
+
+namespace mozilla {
+namespace dom {
+
+NS_IMPL_ISUPPORTS(TVGonkService, nsITVService)
+
+TVGonkService::TVGonkService() {}
+
+TVGonkService::~TVGonkService() {}
+
+NS_IMETHODIMP
+TVGonkService::RegisterSourceListener(const nsAString& aTunerId,
+ const nsAString& aSourceType,
+ nsITVSourceListener* aListener)
+{
+ MOZ_ASSERT(NS_IsMainThread());
+ MOZ_ASSERT(!aTunerId.IsEmpty());
+ MOZ_ASSERT(!aSourceType.IsEmpty());
+ MOZ_ASSERT(aListener);
+
+ mSourceListenerTuples.AppendElement(new TVSourceListenerTuple(
+ nsString(aTunerId), nsString(aSourceType), aListener));
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+TVGonkService::UnregisterSourceListener(const nsAString& aTunerId,
+ const nsAString& aSourceType,
+ nsITVSourceListener* aListener)
+{
+ MOZ_ASSERT(NS_IsMainThread());
+ MOZ_ASSERT(!aTunerId.IsEmpty());
+ MOZ_ASSERT(!aSourceType.IsEmpty());
+ MOZ_ASSERT(aListener);
+
+ for (uint32_t i = 0; i < mSourceListenerTuples.Length(); i++) {
+ const UniquePtr<TVSourceListenerTuple>& tuple = mSourceListenerTuples[i];
+ if (aTunerId.Equals(Get<0>(*tuple)) && aSourceType.Equals(Get<1>(*tuple)) &&
+ aListener == Get<2>(*tuple)) {
+ mSourceListenerTuples.RemoveElementAt(i);
+ break;
+ }
+ }
+
+ return NS_OK;
+}
+
+void
+TVGonkService::GetSourceListeners(
+ const nsAString& aTunerId, const nsAString& aSourceType,
+ nsTArray<nsCOMPtr<nsITVSourceListener> >& aListeners) const
+{
+ aListeners.Clear();
+
+ for (uint32_t i = 0; i < mSourceListenerTuples.Length(); i++) {
+ const UniquePtr<TVSourceListenerTuple>& tuple = mSourceListenerTuples[i];
+ nsCOMPtr<nsITVSourceListener> listener = Get<2>(*tuple);
+ if (aTunerId.Equals(Get<0>(*tuple)) && aSourceType.Equals(Get<1>(*tuple))) {
+ aListeners.AppendElement(listener);
+ break;
+ }
+ }
+}
+
+/* virtual */ NS_IMETHODIMP
+TVGonkService::GetTuners(nsITVServiceCallback* aCallback)
+{
+ MOZ_ASSERT(aCallback);
+
+ // TODO Bug 1229308 - Communicate with TV daemon process.
+
+ return NS_OK;
+}
+
+/* virtual */ NS_IMETHODIMP
+TVGonkService::SetSource(const nsAString& aTunerId,
+ const nsAString& aSourceType,
+ nsITVServiceCallback* aCallback)
+{
+ MOZ_ASSERT(!aTunerId.IsEmpty());
+ MOZ_ASSERT(!aSourceType.IsEmpty());
+ MOZ_ASSERT(aCallback);
+
+ // TODO Bug 1229308 - Communicate with TV daemon process.
+
+ return NS_OK;
+}
+
+/* virtual */ NS_IMETHODIMP
+TVGonkService::StartScanningChannels(const nsAString& aTunerId,
+ const nsAString& aSourceType,
+ nsITVServiceCallback* aCallback)
+{
+ MOZ_ASSERT(!aTunerId.IsEmpty());
+ MOZ_ASSERT(!aSourceType.IsEmpty());
+ MOZ_ASSERT(aCallback);
+
+ // TODO Bug 1229308 - Communicate with TV daemon process.
+
+ return NS_OK;
+}
+
+/* virtual */ NS_IMETHODIMP
+TVGonkService::StopScanningChannels(const nsAString& aTunerId,
+ const nsAString& aSourceType,
+ nsITVServiceCallback* aCallback)
+{
+ MOZ_ASSERT(!aTunerId.IsEmpty());
+ MOZ_ASSERT(!aSourceType.IsEmpty());
+ MOZ_ASSERT(aCallback);
+
+ // TODO Bug 1229308 - Communicate with TV daemon process.
+
+ return NS_OK;
+}
+
+/* virtual */ NS_IMETHODIMP
+TVGonkService::ClearScannedChannelsCache()
+{
+ // TODO Bug 1229308 - Communicate with TV daemon process.
+
+ return NS_OK;
+}
+
+/* virtual */ NS_IMETHODIMP
+TVGonkService::SetChannel(const nsAString& aTunerId,
+ const nsAString& aSourceType,
+ const nsAString& aChannelNumber,
+ nsITVServiceCallback* aCallback)
+{
+ MOZ_ASSERT(!aTunerId.IsEmpty());
+ MOZ_ASSERT(!aSourceType.IsEmpty());
+ MOZ_ASSERT(aCallback);
+
+ // TODO Bug 1229308 - Communicate with TV daemon process.
+
+ return NS_OK;
+}
+
+/* virtual */ NS_IMETHODIMP
+TVGonkService::GetChannels(const nsAString& aTunerId,
+ const nsAString& aSourceType,
+ nsITVServiceCallback* aCallback)
+{
+ MOZ_ASSERT(!aTunerId.IsEmpty());
+ MOZ_ASSERT(!aSourceType.IsEmpty());
+ MOZ_ASSERT(aCallback);
+
+ // TODO Bug 1229308 - Communicate with TV daemon process.
+
+ return NS_OK;
+}
+
+/* virtual */ NS_IMETHODIMP
+TVGonkService::GetPrograms(const nsAString& aTunerId,
+ const nsAString& aSourceType,
+ const nsAString& aChannelNumber, uint64_t startTime,
+ uint64_t endTime, nsITVServiceCallback* aCallback)
+{
+ MOZ_ASSERT(!aTunerId.IsEmpty());
+ MOZ_ASSERT(!aSourceType.IsEmpty());
+ MOZ_ASSERT(!aChannelNumber.IsEmpty());
+ MOZ_ASSERT(aCallback);
+
+ // TODO Bug 1229308 - Communicate with TV daemon process.
+
+ return NS_OK;
+}
+
+} // namespace dom
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/dom/tv/gonk/TVGonkService.h
@@ -0,0 +1,39 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_dom_TVGonkService_h
+#define mozilla_dom_TVGonkService_h
+
+#include "nsCOMPtr.h"
+#include "nsITVService.h"
+#include "nsTArray.h"
+#include "TVTypes.h"
+
+namespace mozilla {
+namespace dom {
+
+class TVGonkService final : public nsITVService
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSITVSERVICE
+
+ TVGonkService();
+
+private:
+ ~TVGonkService();
+
+ void GetSourceListeners(
+ const nsAString& aTunerId, const nsAString& aSourceType,
+ nsTArray<nsCOMPtr<nsITVSourceListener> >& aListeners) const;
+
+ nsTArray<UniquePtr<TVSourceListenerTuple>> mSourceListenerTuples;
+};
+
+} // namespace dom
+} // namespace mozilla
+
+#endif // mozilla_dom_TVGonkService_h
--- a/dom/tv/moz.build
+++ b/dom/tv/moz.build
@@ -35,16 +35,21 @@ XPIDL_SOURCES += [
'nsITVSimulatorService.idl',
]
EXTRA_COMPONENTS += [
'TVSimulatorService.js',
'TVSimulatorService.manifest',
]
+if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
+ UNIFIED_SOURCES += [
+ 'gonk/TVGonkService.cpp',
+ ];
+
XPIDL_MODULE = 'dom_tv'
MOCHITEST_MANIFESTS += ['test/mochitest/mochitest.ini']
XPCSHELL_TESTS_MANIFESTS += ['test/xpcshell/xpcshell.ini']
include('/ipc/chromium/chromium-config.mozbuild')
--- a/dom/tv/nsITVService.idl
+++ b/dom/tv/nsITVService.idl
@@ -203,16 +203,39 @@ interface nsITVSourceListener : nsISuppo
*/
void notifyEITBroadcasted(in DOMString tunerId,
in DOMString sourceType,
in nsITVChannelData channelData,
[array, size_is(count)] in nsITVProgramData programDataList,
in unsigned long count);
};
+%{C++
+#include "mozilla/layers/GonkNativeHandle.h"
+
+#define TV_GONK_NATIVE_HANDLE_DATA_CID \
+ { 0x1e72877a, 0xaacc, 0x425a, { 0xa3, 0x33, 0x85, 0xe1, 0xb2, 0x66, 0xcb, 0xb3 } }
+#define TV_GONK_NATIVE_HANDLE_DATA_CONTRACTID \
+ "@mozilla.org/tv/tvgonknativehandledata;1"
+%}
+
+[ref] native GonkNativeHandle(mozilla::layers::GonkNativeHandle);
+
+[scriptable, builtinclass, uuid(64acaf2e-3dc5-467a-962d-b4c2c920ec30)]
+interface nsITVGonkNativeHandleData : nsISupports
+{
+ /**
+ * A native handle associated with the TV stream.
+ *
+ * NOTE: It's only available for stream type |nsITVTunerData::TV_STREAM_TYPE_HW|.
+ */
+ [noscript]
+ attribute GonkNativeHandle handle;
+};
+
[scriptable, builtinclass, uuid(01582a11-4707-455d-8d2a-2c8de8227dad)]
interface nsITVServiceCallback : nsISupports
{
const unsigned short TV_ERROR_OK = 0;
const unsigned short TV_ERROR_FAILURE = 1;
const unsigned short TV_ERROR_INVALID_ARG = 2;
const unsigned short TV_ERROR_NO_SIGNAL = 3;
const unsigned short TV_ERROR_NOT_SUPPORTED = 4;
@@ -228,55 +251,58 @@ interface nsITVServiceCallback : nsISupp
* Called when the operation succeeds.
*
* @param dataList A list of data.
* An array of |nsITVTunerData| when used for |getTuners()|.
* An array of |nsITVChannelData| ordered by the LCN (Logical
* Channel Number) when used for |getChannels()|.
* An array of |nsITVProgramData| ordered by the start time
* for |getPrograms()|.
+ * An array of |nsITVGonkNativeHandleData| with only one
+ * element for |setSource()|.
* An array of |nsITVChannelData| with only one element for
* |setChannel()|.
- * An array of |nsISupportsString| with only one element for
- * |getOverlayId()|.
*
* NOTE: |nsIArray| is adopted to prevent this interface from being split into
* multiple interfaces with different |notifySuccess|. Though the
* implementation of TV service may need |nsIMutableArray| to fill in the
* array, it doesn't seem necessary for other places to use the mutable one.
*/
void notifySuccess([optional] in nsIArray dataList);
};
%{C++
#define TV_SERVICE_CONTRACTID \
"@mozilla.org/tv/tvservice;1"
%}
-/**
- * XPCOM component which interacts with the underlying TV components.
- *
- * NOTE: The implementation is expected to be done by TV vendors to cooperate
- * with their own TV stack. The methods should not be called on any thread
- * except for the XPCOM main thread.
- *
- * NOTE: The callbacks passing in the methods must be called asynchronously. In
- * the implementation, actual runnable objects may need to be created and call
- * the callback off of the runnables, after the function returns.
- * TVServiceRunnables.h provides some ready-made runnables and could be used in
- * the following way.
- *
- * nsCOMPtr<nsIRunnable> runnable =
- * new TVServiceNotifyRunnable(callback, dataList, optional errorCode);
- * return NS_DispatchToCurrentThread(runnable);
- */
-[scriptable, uuid(e52f93f1-6071-468b-a198-d8e6bc5ca348)]
+[scriptable, uuid(827f4e94-430a-47a6-954a-0c7470cfc5fe)]
interface nsITVService : nsISupports
{
- attribute nsITVSourceListener sourceListener;
+ /**
+ * Register a source listener.
+ *
+ * @param tunerId The ID of the tuner.
+ * @param sourceType The source type to be used.
+ * @param listener The listener to register.
+ */
+ void registerSourceListener(in DOMString tunerId,
+ in DOMString sourceType,
+ in nsITVSourceListener listener);
+
+ /**
+ * Unregister a source listener.
+ *
+ * @param tunerId The ID of the tuner.
+ * @param sourceType The source type to be used.
+ * @param listener The listener to register.
+ */
+ void unregisterSourceListener(in DOMString tunerId,
+ in DOMString sourceType,
+ in nsITVSourceListener listener);
/**
* Get all tuners.
*
* @param callback The callback object where either |notifyError| or
* |notifySuccess|, which takes an array of
* |nsITVTunerData|, is expected.
*/
@@ -373,21 +399,9 @@ interface nsITVService : nsISupports
* expected.
*/
void getPrograms(in DOMString tunerId,
in DOMString sourceType,
in DOMString channelNumber,
in unsigned long long startTime,
in unsigned long long endTime,
in nsITVServiceCallback callback);
-
- /**
- * Get the overlay ID of a given tuner.
- *
- * @param tunerId The ID of the tuner.
- * @param callback The callback object where either |notifyError| or
- * |notifySuccess|, which takes an array of
- * |nsISupportsString| with only one element, is expected.
- */
- void getOverlayId(in DOMString tunerId,
- in nsITVServiceCallback callback);
};
-
--- a/layout/build/nsLayoutModule.cpp
+++ b/layout/build/nsLayoutModule.cpp
@@ -390,19 +390,22 @@ NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR
NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsIMediaManagerService,
MediaManager::GetInstance)
NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsIMobileConnectionService,
NS_CreateMobileConnectionService)
NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsITelephonyService,
NS_CreateTelephonyService)
NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsIVoicemailService,
NS_CreateVoicemailService)
+NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsITVService,
+ TVServiceFactory::AutoCreateTVService)
NS_GENERIC_FACTORY_CONSTRUCTOR(TVTunerData)
NS_GENERIC_FACTORY_CONSTRUCTOR(TVChannelData)
NS_GENERIC_FACTORY_CONSTRUCTOR(TVProgramData)
+NS_GENERIC_FACTORY_CONSTRUCTOR(TVGonkNativeHandleData)
NS_GENERIC_FACTORY_CONSTRUCTOR(PresentationDeviceManager)
NS_GENERIC_FACTORY_CONSTRUCTOR(TextInputProcessor)
NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(FakeInputPortService,
InputPortServiceFactory::CreateFakeInputPortService)
NS_GENERIC_FACTORY_CONSTRUCTOR(InputPortData)
NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsIPresentationService,
NS_CreatePresentationService)
NS_GENERIC_FACTORY_CONSTRUCTOR(PresentationTCPSessionTransport)
@@ -856,19 +859,21 @@ NS_DEFINE_NAMED_CID(NS_POCKETSPHINX_SPEE
#endif
#ifdef MOZ_WEBSPEECH
NS_DEFINE_NAMED_CID(NS_SYNTHVOICEREGISTRY_CID);
#endif
#ifdef ACCESSIBILITY
NS_DEFINE_NAMED_CID(NS_ACCESSIBILITY_SERVICE_CID);
#endif
+NS_DEFINE_NAMED_CID(TV_SERVICE_CID);
NS_DEFINE_NAMED_CID(TV_TUNER_DATA_CID);
NS_DEFINE_NAMED_CID(TV_CHANNEL_DATA_CID);
NS_DEFINE_NAMED_CID(TV_PROGRAM_DATA_CID);
+NS_DEFINE_NAMED_CID(TV_GONK_NATIVE_HANDLE_DATA_CID);
NS_DEFINE_NAMED_CID(FAKE_INPUTPORT_SERVICE_CID);
NS_DEFINE_NAMED_CID(INPUTPORT_DATA_CID);
NS_DEFINE_NAMED_CID(GECKO_MEDIA_PLUGIN_SERVICE_CID);
NS_DEFINE_NAMED_CID(PRESENTATION_SERVICE_CID);
NS_DEFINE_NAMED_CID(PRESENTATION_DEVICE_MANAGER_CID);
@@ -1161,19 +1166,21 @@ static const mozilla::Module::CIDEntry k
{ &kNS_GAMEPAD_TEST_CID, false, nullptr, GamepadServiceTestConstructor },
#endif
#ifdef ACCESSIBILITY
{ &kNS_ACCESSIBILITY_SERVICE_CID, false, nullptr, CreateA11yService },
#endif
{ &kTELEPHONY_SERVICE_CID, false, nullptr, nsITelephonyServiceConstructor },
{ &kNS_MOBILE_CONNECTION_SERVICE_CID, false, NULL, nsIMobileConnectionServiceConstructor },
{ &kNS_VOICEMAIL_SERVICE_CID, false, nullptr, nsIVoicemailServiceConstructor },
+ { &kTV_SERVICE_CID, false, nullptr, nsITVServiceConstructor },
{ &kTV_TUNER_DATA_CID, false, nullptr, TVTunerDataConstructor },
{ &kTV_CHANNEL_DATA_CID, false, nullptr, TVChannelDataConstructor },
{ &kTV_PROGRAM_DATA_CID, false, nullptr, TVProgramDataConstructor },
+ { &kTV_GONK_NATIVE_HANDLE_DATA_CID, false, nullptr, TVGonkNativeHandleDataConstructor },
{ &kPRESENTATION_SERVICE_CID, false, nullptr, nsIPresentationServiceConstructor },
{ &kPRESENTATION_DEVICE_MANAGER_CID, false, nullptr, PresentationDeviceManagerConstructor },
{ &kPRESENTATION_TCP_SESSION_TRANSPORT_CID, false, nullptr, PresentationTCPSessionTransportConstructor },
{ &kTEXT_INPUT_PROCESSOR_CID, false, nullptr, TextInputProcessorConstructor },
{ &kFAKE_INPUTPORT_SERVICE_CID, false, nullptr, FakeInputPortServiceConstructor },
{ &kINPUTPORT_DATA_CID, false, nullptr, InputPortDataConstructor },
#ifdef MOZ_B2G
{ &kNS_HARDWARE_KEY_HANDLER_CID, false, nullptr, nsIHardwareKeyHandlerConstructor },
@@ -1327,19 +1334,21 @@ static const mozilla::Module::ContractID
{ NS_GAMEPAD_TEST_CONTRACTID, &kNS_GAMEPAD_TEST_CID },
#endif
{ MEDIAMANAGERSERVICE_CONTRACTID, &kNS_MEDIAMANAGERSERVICE_CID },
#ifdef ACCESSIBILITY
{ "@mozilla.org/accessibilityService;1", &kNS_ACCESSIBILITY_SERVICE_CID },
{ "@mozilla.org/accessibleRetrieval;1", &kNS_ACCESSIBILITY_SERVICE_CID },
#endif
{ TELEPHONY_SERVICE_CONTRACTID, &kTELEPHONY_SERVICE_CID },
+ { TV_SERVICE_CONTRACTID, &kTV_SERVICE_CID },
{ TV_TUNER_DATA_CONTRACTID, &kTV_TUNER_DATA_CID },
{ TV_CHANNEL_DATA_CONTRACTID, &kTV_CHANNEL_DATA_CID },
{ TV_PROGRAM_DATA_CONTRACTID, &kTV_PROGRAM_DATA_CID },
+ { TV_GONK_NATIVE_HANDLE_DATA_CONTRACTID, &kTV_GONK_NATIVE_HANDLE_DATA_CID },
{ "@mozilla.org/gecko-media-plugin-service;1", &kGECKO_MEDIA_PLUGIN_SERVICE_CID },
{ NS_MOBILE_CONNECTION_SERVICE_CONTRACTID, &kNS_MOBILE_CONNECTION_SERVICE_CID },
{ NS_VOICEMAIL_SERVICE_CONTRACTID, &kNS_VOICEMAIL_SERVICE_CID },
{ PRESENTATION_SERVICE_CONTRACTID, &kPRESENTATION_SERVICE_CID },
{ PRESENTATION_DEVICE_MANAGER_CONTRACTID, &kPRESENTATION_DEVICE_MANAGER_CID },
{ PRESENTATION_TCP_SESSION_TRANSPORT_CONTRACTID, &kPRESENTATION_TCP_SESSION_TRANSPORT_CID },
{ "@mozilla.org/text-input-processor;1", &kTEXT_INPUT_PROCESSOR_CID },
{ FAKE_INPUTPORT_SERVICE_CONTRACTID, &kFAKE_INPUTPORT_SERVICE_CID },