123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342 |
- /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
- /* vim:set ts=2 sw=2 et tw=78: */
- /* 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/AsyncEventDispatcher.h"
- #include "mozilla/dom/TextTrack.h"
- #include "mozilla/dom/TextTrackBinding.h"
- #include "mozilla/dom/TextTrackList.h"
- #include "mozilla/dom/TextTrackCue.h"
- #include "mozilla/dom/TextTrackCueList.h"
- #include "mozilla/dom/TextTrackRegion.h"
- #include "mozilla/dom/HTMLMediaElement.h"
- #include "mozilla/dom/HTMLTrackElement.h"
- namespace mozilla {
- namespace dom {
- NS_IMPL_CYCLE_COLLECTION_INHERITED(TextTrack,
- DOMEventTargetHelper,
- mCueList,
- mActiveCueList,
- mTextTrackList,
- mTrackElement)
- NS_IMPL_ADDREF_INHERITED(TextTrack, DOMEventTargetHelper)
- NS_IMPL_RELEASE_INHERITED(TextTrack, DOMEventTargetHelper)
- NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(TextTrack)
- NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
- TextTrack::TextTrack(nsPIDOMWindowInner* aOwnerWindow,
- TextTrackKind aKind,
- const nsAString& aLabel,
- const nsAString& aLanguage,
- TextTrackMode aMode,
- TextTrackReadyState aReadyState,
- TextTrackSource aTextTrackSource)
- : DOMEventTargetHelper(aOwnerWindow)
- , mKind(aKind)
- , mLabel(aLabel)
- , mLanguage(aLanguage)
- , mMode(aMode)
- , mReadyState(aReadyState)
- , mTextTrackSource(aTextTrackSource)
- {
- SetDefaultSettings();
- }
- TextTrack::TextTrack(nsPIDOMWindowInner* aOwnerWindow,
- TextTrackList* aTextTrackList,
- TextTrackKind aKind,
- const nsAString& aLabel,
- const nsAString& aLanguage,
- TextTrackMode aMode,
- TextTrackReadyState aReadyState,
- TextTrackSource aTextTrackSource)
- : DOMEventTargetHelper(aOwnerWindow)
- , mTextTrackList(aTextTrackList)
- , mKind(aKind)
- , mLabel(aLabel)
- , mLanguage(aLanguage)
- , mMode(aMode)
- , mReadyState(aReadyState)
- , mTextTrackSource(aTextTrackSource)
- {
- SetDefaultSettings();
- }
- TextTrack::~TextTrack()
- {
- }
- void
- TextTrack::SetDefaultSettings()
- {
- nsPIDOMWindowInner* ownerWindow = GetOwner();
- mCueList = new TextTrackCueList(ownerWindow);
- mActiveCueList = new TextTrackCueList(ownerWindow);
- mCuePos = 0;
- mDirty = false;
- }
- JSObject*
- TextTrack::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
- {
- return TextTrackBinding::Wrap(aCx, this, aGivenProto);
- }
- void
- TextTrack::SetMode(TextTrackMode aValue)
- {
- if (mMode != aValue) {
- mMode = aValue;
- if (aValue == TextTrackMode::Disabled) {
- // Remove all the cues in MediaElement.
- if (mTextTrackList) {
- HTMLMediaElement* mediaElement = mTextTrackList->GetMediaElement();
- if (mediaElement) {
- for (size_t i = 0; i < mCueList->Length(); ++i) {
- mediaElement->NotifyCueRemoved(*(*mCueList)[i]);
- }
- }
- }
- SetCuesInactive();
- } else {
- // Add all the cues into MediaElement.
- if (mTextTrackList) {
- HTMLMediaElement* mediaElement = mTextTrackList->GetMediaElement();
- if (mediaElement) {
- for (size_t i = 0; i < mCueList->Length(); ++i) {
- mediaElement->NotifyCueAdded(*(*mCueList)[i]);
- }
- }
- }
- }
- if (mTextTrackList) {
- mTextTrackList->CreateAndDispatchChangeEvent();
- }
- // Ensure the TimeMarchesOn is called in case that the mCueList
- // is empty.
- NotifyCueUpdated(nullptr);
- }
- }
- void
- TextTrack::GetId(nsAString& aId) const
- {
- // If the track has a track element then its id should be the same as the
- // track element's id.
- if (mTrackElement) {
- mTrackElement->GetAttribute(NS_LITERAL_STRING("id"), aId);
- }
- }
- void
- TextTrack::AddCue(TextTrackCue& aCue)
- {
- TextTrack* oldTextTrack = aCue.GetTrack();
- if (oldTextTrack) {
- ErrorResult dummy;
- oldTextTrack->RemoveCue(aCue, dummy);
- }
- mCueList->AddCue(aCue);
- aCue.SetTrack(this);
- if (mTextTrackList) {
- HTMLMediaElement* mediaElement = mTextTrackList->GetMediaElement();
- if (mediaElement && (mMode != TextTrackMode::Disabled)) {
- mediaElement->NotifyCueAdded(aCue);
- }
- }
- SetDirty();
- }
- void
- TextTrack::RemoveCue(TextTrackCue& aCue, ErrorResult& aRv)
- {
- // Bug1304948, check the aCue belongs to the TextTrack.
- mCueList->RemoveCue(aCue, aRv);
- if (aRv.Failed()) {
- return;
- }
- aCue.SetActive(false);
- aCue.SetTrack(nullptr);
- if (mTextTrackList) {
- HTMLMediaElement* mediaElement = mTextTrackList->GetMediaElement();
- if (mediaElement) {
- mediaElement->NotifyCueRemoved(aCue);
- }
- }
- SetDirty();
- }
- void
- TextTrack::SetCuesDirty()
- {
- for (uint32_t i = 0; i < mCueList->Length(); i++) {
- ((*mCueList)[i])->Reset();
- }
- }
- void
- TextTrack::UpdateActiveCueList()
- {
- if (!mTextTrackList) {
- return;
- }
- HTMLMediaElement* mediaElement = mTextTrackList->GetMediaElement();
- if (!mediaElement) {
- return;
- }
- // If we are dirty, i.e. an event happened that may cause the sorted mCueList
- // to have changed like a seek or an insert for a cue, than we need to rebuild
- // the active cue list from scratch.
- if (mDirty) {
- mCuePos = 0;
- mDirty = false;
- mActiveCueList->RemoveAll();
- }
- double playbackTime = mediaElement->CurrentTime();
- // Remove all the cues from the active cue list whose end times now occur
- // earlier then the current playback time.
- for (uint32_t i = mActiveCueList->Length(); i > 0; i--) {
- if ((*mActiveCueList)[i - 1]->EndTime() < playbackTime) {
- mActiveCueList->RemoveCueAt(i - 1);
- }
- }
- // Add all the cues, starting from the position of the last cue that was
- // added, that have valid start and end times for the current playback time.
- // We can stop iterating safely once we encounter a cue that does not have
- // a valid start time as the cue list is sorted.
- for (; mCuePos < mCueList->Length() &&
- (*mCueList)[mCuePos]->StartTime() <= playbackTime; mCuePos++) {
- if ((*mCueList)[mCuePos]->EndTime() >= playbackTime) {
- mActiveCueList->AddCue(*(*mCueList)[mCuePos]);
- }
- }
- }
- TextTrackCueList*
- TextTrack::GetActiveCues() {
- if (mMode != TextTrackMode::Disabled) {
- return mActiveCueList;
- }
- return nullptr;
- }
- void
- TextTrack::GetActiveCueArray(nsTArray<RefPtr<TextTrackCue> >& aCues)
- {
- if (mMode != TextTrackMode::Disabled) {
- mActiveCueList->GetArray(aCues);
- }
- }
- TextTrackReadyState
- TextTrack::ReadyState() const
- {
- return mReadyState;
- }
- void
- TextTrack::SetReadyState(uint32_t aReadyState)
- {
- if (aReadyState <= TextTrackReadyState::FailedToLoad) {
- SetReadyState(static_cast<TextTrackReadyState>(aReadyState));
- }
- }
- void
- TextTrack::SetReadyState(TextTrackReadyState aState)
- {
- mReadyState = aState;
- if (!mTextTrackList) {
- return;
- }
- HTMLMediaElement* mediaElement = mTextTrackList->GetMediaElement();
- if (mediaElement && (mReadyState == TextTrackReadyState::Loaded||
- mReadyState == TextTrackReadyState::FailedToLoad)) {
- mediaElement->RemoveTextTrack(this, true);
- }
- }
- TextTrackList*
- TextTrack::GetTextTrackList()
- {
- return mTextTrackList;
- }
- void
- TextTrack::SetTextTrackList(TextTrackList* aTextTrackList)
- {
- mTextTrackList = aTextTrackList;
- }
- HTMLTrackElement*
- TextTrack::GetTrackElement() {
- return mTrackElement;
- }
- void
- TextTrack::SetTrackElement(HTMLTrackElement* aTrackElement) {
- mTrackElement = aTrackElement;
- }
- void
- TextTrack::SetCuesInactive()
- {
- mCueList->SetCuesInactive();
- }
- void
- TextTrack::NotifyCueUpdated(TextTrackCue *aCue)
- {
- mCueList->NotifyCueUpdated(aCue);
- if (mTextTrackList) {
- HTMLMediaElement* mediaElement = mTextTrackList->GetMediaElement();
- if (mediaElement) {
- mediaElement->NotifyCueUpdated(aCue);
- }
- }
- SetDirty();
- }
- void
- TextTrack::GetLabel(nsAString& aLabel) const
- {
- if (mTrackElement) {
- mTrackElement->GetLabel(aLabel);
- } else {
- aLabel = mLabel;
- }
- }
- void
- TextTrack::GetLanguage(nsAString& aLanguage) const
- {
- if (mTrackElement) {
- mTrackElement->GetSrclang(aLanguage);
- } else {
- aLanguage = mLanguage;
- }
- }
- void
- TextTrack::DispatchAsyncTrustedEvent(const nsString& aEventName)
- {
- RefPtr<TextTrack> self = this;
- NS_DispatchToMainThread(
- NS_NewRunnableFunction([self, aEventName]() {
- self->DispatchTrustedEvent(aEventName);
- })
- );
- }
- } // namespace dom
- } // namespace mozilla
|