Bumping manifests a=b2g-bump
[gecko.git] / dom / tv / TVSource.cpp
blob3b784a35daccf54c7b330b541426122eb33b8f2d
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "mozilla/dom/Promise.h"
8 #include "mozilla/dom/TVChannel.h"
9 #include "mozilla/dom/TVCurrentChannelChangedEvent.h"
10 #include "mozilla/dom/TVEITBroadcastedEvent.h"
11 #include "mozilla/dom/TVListeners.h"
12 #include "mozilla/dom/TVScanningStateChangedEvent.h"
13 #include "mozilla/dom/TVServiceCallbacks.h"
14 #include "mozilla/dom/TVServiceFactory.h"
15 #include "mozilla/dom/TVTuner.h"
16 #include "mozilla/dom/TVUtils.h"
17 #include "nsITVService.h"
18 #include "nsServiceManagerUtils.h"
19 #include "TVSource.h"
21 namespace mozilla {
22 namespace dom {
24 NS_IMPL_CYCLE_COLLECTION_CLASS(TVSource)
26 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(TVSource,
27 DOMEventTargetHelper)
28 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTVService)
29 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTuner)
30 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCurrentChannel)
31 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
33 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(TVSource,
34 DOMEventTargetHelper)
35 tmp->Shutdown();
36 NS_IMPL_CYCLE_COLLECTION_UNLINK(mTVService)
37 NS_IMPL_CYCLE_COLLECTION_UNLINK(mTuner)
38 NS_IMPL_CYCLE_COLLECTION_UNLINK(mCurrentChannel)
39 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
41 NS_IMPL_ADDREF_INHERITED(TVSource, DOMEventTargetHelper)
42 NS_IMPL_RELEASE_INHERITED(TVSource, DOMEventTargetHelper)
44 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(TVSource)
45 NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
47 TVSource::TVSource(nsPIDOMWindow* aWindow,
48 TVSourceType aType,
49 TVTuner* aTuner)
50 : DOMEventTargetHelper(aWindow)
51 , mTuner(aTuner)
52 , mType(aType)
53 , mIsScanning(false)
55 MOZ_ASSERT(mTuner);
58 TVSource::~TVSource()
60 Shutdown();
63 /* static */ already_AddRefed<TVSource>
64 TVSource::Create(nsPIDOMWindow* aWindow,
65 TVSourceType aType,
66 TVTuner* aTuner)
68 nsRefPtr<TVSource> source = new TVSource(aWindow, aType, aTuner);
69 return (source->Init()) ? source.forget() : nullptr;
72 bool
73 TVSource::Init()
75 mTVService = TVServiceFactory::AutoCreateTVService();
76 NS_ENSURE_TRUE(mTVService, false);
78 nsCOMPtr<nsITVSourceListener> sourceListener;
79 mTVService->GetSourceListener(getter_AddRefs(sourceListener));
80 NS_ENSURE_TRUE(sourceListener, false);
81 (static_cast<TVSourceListener*>(sourceListener.get()))->RegisterSource(this);
83 return true;
86 void
87 TVSource::Shutdown()
89 if (!mTVService) {
90 return;
93 nsCOMPtr<nsITVSourceListener> sourceListener;
94 mTVService->GetSourceListener(getter_AddRefs(sourceListener));
95 if (!sourceListener) {
96 return;
98 (static_cast<TVSourceListener*>(sourceListener.get()))->UnregisterSource(this);
101 /* virtual */ JSObject*
102 TVSource::WrapObject(JSContext* aCx)
104 return TVSourceBinding::Wrap(aCx, this);
107 nsresult
108 TVSource::SetCurrentChannel(nsITVChannelData* aChannelData)
110 if (!aChannelData) {
111 return NS_ERROR_INVALID_ARG;
114 nsString newChannelNumber;
115 nsresult rv = aChannelData->GetNumber(newChannelNumber);
116 if (NS_FAILED(rv)) {
117 return rv;
120 if (newChannelNumber.IsEmpty()) {
121 return NS_ERROR_INVALID_ARG;
124 if (mCurrentChannel) {
125 nsString currentChannelNumber;
126 mCurrentChannel->GetNumber(currentChannelNumber);
127 if (newChannelNumber.Equals(currentChannelNumber)) {
128 // No actual change.
129 return NS_OK;
133 mCurrentChannel = TVChannel::Create(GetOwner(), this, aChannelData);
134 NS_ENSURE_TRUE(mCurrentChannel, NS_ERROR_DOM_ABORT_ERR);
136 return DispatchCurrentChannelChangedEvent(mCurrentChannel);
139 nsresult
140 TVSource::UnsetCurrentChannel()
142 mCurrentChannel = nullptr;
143 return DispatchCurrentChannelChangedEvent(mCurrentChannel);
146 void
147 TVSource::SetIsScanning(bool aIsScanning)
149 mIsScanning = aIsScanning;
152 nsresult
153 TVSource::DispatchTVEvent(nsIDOMEvent* aEvent)
155 return DispatchTrustedEvent(aEvent);
158 already_AddRefed<Promise>
159 TVSource::GetChannels(ErrorResult& aRv)
161 nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(GetOwner());
162 MOZ_ASSERT(global);
164 nsRefPtr<Promise> promise = Promise::Create(global, aRv);
165 if (NS_WARN_IF(aRv.Failed())) {
166 return nullptr;
169 // The operation is prohibited when the source is scanning channels.
170 if (mIsScanning) {
171 promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR);
172 return promise.forget();
175 nsString tunerId;
176 mTuner->GetId(tunerId);
178 nsCOMPtr<nsITVServiceCallback> callback =
179 new TVServiceChannelGetterCallback(this, promise);
180 nsresult rv =
181 mTVService->GetChannels(tunerId, ToTVSourceTypeStr(mType), callback);
182 if (NS_WARN_IF(NS_FAILED(rv))) {
183 promise->MaybeReject(NS_ERROR_DOM_ABORT_ERR);
186 return promise.forget();
189 already_AddRefed<Promise>
190 TVSource::SetCurrentChannel(const nsAString& aChannelNumber,
191 ErrorResult& aRv)
193 nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(GetOwner());
194 MOZ_ASSERT(global);
196 nsRefPtr<Promise> promise = Promise::Create(global, aRv);
197 if (NS_WARN_IF(aRv.Failed())) {
198 return nullptr;
201 // The operation is prohibited when the source is scanning channels.
202 if (mIsScanning) {
203 promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR);
204 return promise.forget();
207 nsString tunerId;
208 mTuner->GetId(tunerId);
210 nsCOMPtr<nsITVServiceCallback> callback =
211 new TVServiceChannelSetterCallback(this, promise, aChannelNumber);
212 nsresult rv =
213 mTVService->SetChannel(tunerId, ToTVSourceTypeStr(mType), aChannelNumber, callback);
214 if (NS_WARN_IF(NS_FAILED(rv))) {
215 promise->MaybeReject(NS_ERROR_DOM_ABORT_ERR);
218 return promise.forget();
221 already_AddRefed<Promise>
222 TVSource::StartScanning(const TVStartScanningOptions& aOptions,
223 ErrorResult& aRv)
225 nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(GetOwner());
226 MOZ_ASSERT(global);
228 nsRefPtr<Promise> promise = Promise::Create(global, aRv);
229 if (NS_WARN_IF(aRv.Failed())) {
230 return nullptr;
233 nsString tunerId;
234 mTuner->GetId(tunerId);
236 bool isRescanned = aOptions.mIsRescanned.WasPassed() &&
237 aOptions.mIsRescanned.Value();
239 if (isRescanned) {
240 nsresult rv = mTVService->ClearScannedChannelsCache();
241 if (NS_WARN_IF(NS_FAILED(rv))) {
242 promise->MaybeReject(NS_ERROR_DOM_ABORT_ERR);
243 return promise.forget();
246 rv = DispatchScanningStateChangedEvent(TVScanningState::Cleared, nullptr);
247 if (NS_WARN_IF(NS_FAILED(rv))) {
248 promise->MaybeReject(NS_ERROR_DOM_ABORT_ERR);
249 return promise.forget();
253 // |SetIsScanning(bool)| should be called once |notifySuccess()| of this
254 // callback is invoked.
255 nsCOMPtr<nsITVServiceCallback> callback =
256 new TVServiceChannelScanCallback(this, promise, true);
257 nsresult rv =
258 mTVService->StartScanningChannels(tunerId, ToTVSourceTypeStr(mType), callback);
259 if (NS_WARN_IF(NS_FAILED(rv))) {
260 promise->MaybeReject(NS_ERROR_DOM_ABORT_ERR);
263 return promise.forget();
266 already_AddRefed<Promise>
267 TVSource::StopScanning(ErrorResult& aRv)
269 nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(GetOwner());
270 MOZ_ASSERT(global);
272 nsRefPtr<Promise> promise = Promise::Create(global, aRv);
273 if (NS_WARN_IF(aRv.Failed())) {
274 return nullptr;
277 nsString tunerId;
278 mTuner->GetId(tunerId);
280 // |SetIsScanning(bool)| should be called once |notifySuccess()| of this
281 // callback is invoked.
282 nsCOMPtr<nsITVServiceCallback> callback =
283 new TVServiceChannelScanCallback(this, promise, false);
284 nsresult rv =
285 mTVService->StopScanningChannels(tunerId, ToTVSourceTypeStr(mType), callback);
286 if (NS_WARN_IF(NS_FAILED(rv))) {
287 promise->MaybeReject(NS_ERROR_DOM_ABORT_ERR);
290 return promise.forget();
293 already_AddRefed<TVTuner>
294 TVSource::Tuner() const
296 nsRefPtr<TVTuner> tuner = mTuner;
297 return tuner.forget();
300 TVSourceType
301 TVSource::Type() const
303 return mType;
306 bool
307 TVSource::IsScanning() const
309 return mIsScanning;
312 already_AddRefed<TVChannel>
313 TVSource::GetCurrentChannel() const
315 nsRefPtr<TVChannel> currentChannel = mCurrentChannel;
316 return currentChannel.forget();
319 nsresult
320 TVSource::NotifyChannelScanned(nsITVChannelData* aChannelData)
322 nsRefPtr<TVChannel> channel = TVChannel::Create(GetOwner(), this, aChannelData);
323 NS_ENSURE_TRUE(channel, NS_ERROR_DOM_ABORT_ERR);
325 return DispatchScanningStateChangedEvent(TVScanningState::Scanned, channel);
328 nsresult
329 TVSource::NotifyChannelScanComplete()
331 SetIsScanning(false);
332 return DispatchScanningStateChangedEvent(TVScanningState::Completed, nullptr);
335 nsresult
336 TVSource::NotifyChannelScanStopped()
338 SetIsScanning(false);
339 return DispatchScanningStateChangedEvent(TVScanningState::Stopped, nullptr);
342 nsresult
343 TVSource::NotifyEITBroadcasted(nsITVChannelData* aChannelData,
344 nsITVProgramData** aProgramDataList,
345 uint32_t aCount)
347 nsRefPtr<TVChannel> channel = TVChannel::Create(GetOwner(), this, aChannelData);
348 Sequence<OwningNonNull<TVProgram>> programs;
349 for (uint32_t i = 0; i < aCount; i++) {
350 nsRefPtr<TVProgram> program =
351 new TVProgram(GetOwner(), channel, aProgramDataList[i]);
352 *programs.AppendElement() = program;
354 return DispatchEITBroadcastedEvent(programs);
357 nsresult
358 TVSource::DispatchCurrentChannelChangedEvent(TVChannel* aChannel)
360 TVCurrentChannelChangedEventInit init;
361 init.mChannel = aChannel;
362 nsCOMPtr<nsIDOMEvent> event =
363 TVCurrentChannelChangedEvent::Constructor(this,
364 NS_LITERAL_STRING("currentchannelchanged"),
365 init);
366 nsCOMPtr<nsIRunnable> runnable =
367 NS_NewRunnableMethodWithArg<nsCOMPtr<nsIDOMEvent>>(this,
368 &TVSource::DispatchTVEvent,
369 event);
370 return NS_DispatchToCurrentThread(runnable);
373 nsresult
374 TVSource::DispatchScanningStateChangedEvent(TVScanningState aState,
375 TVChannel* aChannel)
377 TVScanningStateChangedEventInit init;
378 init.mState = aState;
379 init.mChannel = aChannel;
380 nsCOMPtr<nsIDOMEvent> event =
381 TVScanningStateChangedEvent::Constructor(this,
382 NS_LITERAL_STRING("scanningstatechanged"),
383 init);
384 nsCOMPtr<nsIRunnable> runnable =
385 NS_NewRunnableMethodWithArg<nsCOMPtr<nsIDOMEvent>>(this,
386 &TVSource::DispatchTVEvent,
387 event);
388 return NS_DispatchToCurrentThread(runnable);
391 nsresult
392 TVSource::DispatchEITBroadcastedEvent(const Sequence<OwningNonNull<TVProgram>>& aPrograms)
394 TVEITBroadcastedEventInit init;
395 init.mPrograms = aPrograms;
396 nsCOMPtr<nsIDOMEvent> event =
397 TVEITBroadcastedEvent::Constructor(this,
398 NS_LITERAL_STRING("eitbroadcasted"),
399 init);
400 nsCOMPtr<nsIRunnable> runnable =
401 NS_NewRunnableMethodWithArg<nsCOMPtr<nsIDOMEvent>>(this,
402 &TVSource::DispatchTVEvent,
403 event);
404 return NS_DispatchToCurrentThread(runnable);
407 } // namespace dom
408 } // namespace mozilla