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"
24 NS_IMPL_CYCLE_COLLECTION_CLASS(TVSource
)
26 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(TVSource
,
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
,
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
,
50 : DOMEventTargetHelper(aWindow
)
63 /* static */ already_AddRefed
<TVSource
>
64 TVSource::Create(nsPIDOMWindow
* aWindow
,
68 nsRefPtr
<TVSource
> source
= new TVSource(aWindow
, aType
, aTuner
);
69 return (source
->Init()) ? source
.forget() : nullptr;
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);
93 nsCOMPtr
<nsITVSourceListener
> sourceListener
;
94 mTVService
->GetSourceListener(getter_AddRefs(sourceListener
));
95 if (!sourceListener
) {
98 (static_cast<TVSourceListener
*>(sourceListener
.get()))->UnregisterSource(this);
101 /* virtual */ JSObject
*
102 TVSource::WrapObject(JSContext
* aCx
)
104 return TVSourceBinding::Wrap(aCx
, this);
108 TVSource::SetCurrentChannel(nsITVChannelData
* aChannelData
)
111 return NS_ERROR_INVALID_ARG
;
114 nsString newChannelNumber
;
115 nsresult rv
= aChannelData
->GetNumber(newChannelNumber
);
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
)) {
133 mCurrentChannel
= TVChannel::Create(GetOwner(), this, aChannelData
);
134 NS_ENSURE_TRUE(mCurrentChannel
, NS_ERROR_DOM_ABORT_ERR
);
136 return DispatchCurrentChannelChangedEvent(mCurrentChannel
);
140 TVSource::UnsetCurrentChannel()
142 mCurrentChannel
= nullptr;
143 return DispatchCurrentChannelChangedEvent(mCurrentChannel
);
147 TVSource::SetIsScanning(bool aIsScanning
)
149 mIsScanning
= aIsScanning
;
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());
164 nsRefPtr
<Promise
> promise
= Promise::Create(global
, aRv
);
165 if (NS_WARN_IF(aRv
.Failed())) {
169 // The operation is prohibited when the source is scanning channels.
171 promise
->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR
);
172 return promise
.forget();
176 mTuner
->GetId(tunerId
);
178 nsCOMPtr
<nsITVServiceCallback
> callback
=
179 new TVServiceChannelGetterCallback(this, promise
);
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
,
193 nsCOMPtr
<nsIGlobalObject
> global
= do_QueryInterface(GetOwner());
196 nsRefPtr
<Promise
> promise
= Promise::Create(global
, aRv
);
197 if (NS_WARN_IF(aRv
.Failed())) {
201 // The operation is prohibited when the source is scanning channels.
203 promise
->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR
);
204 return promise
.forget();
208 mTuner
->GetId(tunerId
);
210 nsCOMPtr
<nsITVServiceCallback
> callback
=
211 new TVServiceChannelSetterCallback(this, promise
, aChannelNumber
);
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
,
225 nsCOMPtr
<nsIGlobalObject
> global
= do_QueryInterface(GetOwner());
228 nsRefPtr
<Promise
> promise
= Promise::Create(global
, aRv
);
229 if (NS_WARN_IF(aRv
.Failed())) {
234 mTuner
->GetId(tunerId
);
236 bool isRescanned
= aOptions
.mIsRescanned
.WasPassed() &&
237 aOptions
.mIsRescanned
.Value();
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);
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());
272 nsRefPtr
<Promise
> promise
= Promise::Create(global
, aRv
);
273 if (NS_WARN_IF(aRv
.Failed())) {
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);
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();
301 TVSource::Type() const
307 TVSource::IsScanning() const
312 already_AddRefed
<TVChannel
>
313 TVSource::GetCurrentChannel() const
315 nsRefPtr
<TVChannel
> currentChannel
= mCurrentChannel
;
316 return currentChannel
.forget();
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
);
329 TVSource::NotifyChannelScanComplete()
331 SetIsScanning(false);
332 return DispatchScanningStateChangedEvent(TVScanningState::Completed
, nullptr);
336 TVSource::NotifyChannelScanStopped()
338 SetIsScanning(false);
339 return DispatchScanningStateChangedEvent(TVScanningState::Stopped
, nullptr);
343 TVSource::NotifyEITBroadcasted(nsITVChannelData
* aChannelData
,
344 nsITVProgramData
** aProgramDataList
,
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
);
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"),
366 nsCOMPtr
<nsIRunnable
> runnable
=
367 NS_NewRunnableMethodWithArg
<nsCOMPtr
<nsIDOMEvent
>>(this,
368 &TVSource::DispatchTVEvent
,
370 return NS_DispatchToCurrentThread(runnable
);
374 TVSource::DispatchScanningStateChangedEvent(TVScanningState aState
,
377 TVScanningStateChangedEventInit init
;
378 init
.mState
= aState
;
379 init
.mChannel
= aChannel
;
380 nsCOMPtr
<nsIDOMEvent
> event
=
381 TVScanningStateChangedEvent::Constructor(this,
382 NS_LITERAL_STRING("scanningstatechanged"),
384 nsCOMPtr
<nsIRunnable
> runnable
=
385 NS_NewRunnableMethodWithArg
<nsCOMPtr
<nsIDOMEvent
>>(this,
386 &TVSource::DispatchTVEvent
,
388 return NS_DispatchToCurrentThread(runnable
);
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"),
400 nsCOMPtr
<nsIRunnable
> runnable
=
401 NS_NewRunnableMethodWithArg
<nsCOMPtr
<nsIDOMEvent
>>(this,
402 &TVSource::DispatchTVEvent
,
404 return NS_DispatchToCurrentThread(runnable
);
408 } // namespace mozilla