michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* vim:set ts=2 sw=2 et tw=78: */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "mozilla/dom/TextTrack.h" michael@0: #include "mozilla/dom/TextTrackBinding.h" michael@0: #include "mozilla/dom/TextTrackList.h" michael@0: #include "mozilla/dom/TextTrackCue.h" michael@0: #include "mozilla/dom/TextTrackCueList.h" michael@0: #include "mozilla/dom/TextTrackRegion.h" michael@0: #include "mozilla/dom/HTMLMediaElement.h" michael@0: #include "mozilla/dom/HTMLTrackElement.h" michael@0: michael@0: namespace mozilla { michael@0: namespace dom { michael@0: michael@0: NS_IMPL_CYCLE_COLLECTION_INHERITED(TextTrack, michael@0: DOMEventTargetHelper, michael@0: mCueList, michael@0: mActiveCueList, michael@0: mTextTrackList, michael@0: mTrackElement) michael@0: michael@0: NS_IMPL_ADDREF_INHERITED(TextTrack, DOMEventTargetHelper) michael@0: NS_IMPL_RELEASE_INHERITED(TextTrack, DOMEventTargetHelper) michael@0: NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(TextTrack) michael@0: NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper) michael@0: michael@0: TextTrack::TextTrack(nsPIDOMWindow* aOwnerWindow, michael@0: TextTrackKind aKind, michael@0: const nsAString& aLabel, michael@0: const nsAString& aLanguage, michael@0: TextTrackMode aMode, michael@0: TextTrackReadyState aReadyState, michael@0: TextTrackSource aTextTrackSource) michael@0: : DOMEventTargetHelper(aOwnerWindow) michael@0: , mKind(aKind) michael@0: , mLabel(aLabel) michael@0: , mLanguage(aLanguage) michael@0: , mMode(aMode) michael@0: , mReadyState(aReadyState) michael@0: , mTextTrackSource(aTextTrackSource) michael@0: { michael@0: SetDefaultSettings(); michael@0: } michael@0: michael@0: TextTrack::TextTrack(nsPIDOMWindow* aOwnerWindow, michael@0: TextTrackList* aTextTrackList, michael@0: TextTrackKind aKind, michael@0: const nsAString& aLabel, michael@0: const nsAString& aLanguage, michael@0: TextTrackMode aMode, michael@0: TextTrackReadyState aReadyState, michael@0: TextTrackSource aTextTrackSource) michael@0: : DOMEventTargetHelper(aOwnerWindow) michael@0: , mTextTrackList(aTextTrackList) michael@0: , mKind(aKind) michael@0: , mLabel(aLabel) michael@0: , mLanguage(aLanguage) michael@0: , mMode(aMode) michael@0: , mReadyState(aReadyState) michael@0: , mTextTrackSource(aTextTrackSource) michael@0: { michael@0: SetDefaultSettings(); michael@0: } michael@0: michael@0: void michael@0: TextTrack::SetDefaultSettings() michael@0: { michael@0: nsPIDOMWindow* ownerWindow = GetOwner(); michael@0: mCueList = new TextTrackCueList(ownerWindow); michael@0: mActiveCueList = new TextTrackCueList(ownerWindow); michael@0: mCuePos = 0; michael@0: mDirty = false; michael@0: } michael@0: michael@0: JSObject* michael@0: TextTrack::WrapObject(JSContext* aCx) michael@0: { michael@0: return TextTrackBinding::Wrap(aCx, this); michael@0: } michael@0: michael@0: void michael@0: TextTrack::SetMode(TextTrackMode aValue) michael@0: { michael@0: if (mMode != aValue) { michael@0: mMode = aValue; michael@0: if (mTextTrackList) { michael@0: mTextTrackList->CreateAndDispatchChangeEvent(); michael@0: } michael@0: } michael@0: } michael@0: michael@0: void michael@0: TextTrack::GetId(nsAString& aId) const michael@0: { michael@0: // If the track has a track element then its id should be the same as the michael@0: // track element's id. michael@0: if (mTrackElement) { michael@0: mTrackElement->GetAttribute(NS_LITERAL_STRING("id"), aId); michael@0: } michael@0: } michael@0: michael@0: void michael@0: TextTrack::AddCue(TextTrackCue& aCue) michael@0: { michael@0: mCueList->AddCue(aCue); michael@0: aCue.SetTrack(this); michael@0: if (mTextTrackList) { michael@0: HTMLMediaElement* mediaElement = mTextTrackList->GetMediaElement(); michael@0: if (mediaElement) { michael@0: mediaElement->AddCue(aCue); michael@0: } michael@0: } michael@0: SetDirty(); michael@0: } michael@0: michael@0: void michael@0: TextTrack::RemoveCue(TextTrackCue& aCue, ErrorResult& aRv) michael@0: { michael@0: mCueList->RemoveCue(aCue, aRv); michael@0: SetDirty(); michael@0: } michael@0: michael@0: void michael@0: TextTrack::SetCuesDirty() michael@0: { michael@0: for (uint32_t i = 0; i < mCueList->Length(); i++) { michael@0: ((*mCueList)[i])->Reset(); michael@0: } michael@0: } michael@0: michael@0: void michael@0: TextTrack::UpdateActiveCueList() michael@0: { michael@0: if (!mTextTrackList) { michael@0: return; michael@0: } michael@0: michael@0: HTMLMediaElement* mediaElement = mTextTrackList->GetMediaElement(); michael@0: if (!mediaElement) { michael@0: return; michael@0: } michael@0: michael@0: // If we are dirty, i.e. an event happened that may cause the sorted mCueList michael@0: // to have changed like a seek or an insert for a cue, than we need to rebuild michael@0: // the active cue list from scratch. michael@0: if (mDirty) { michael@0: mCuePos = 0; michael@0: mDirty = false; michael@0: mActiveCueList->RemoveAll(); michael@0: } michael@0: michael@0: double playbackTime = mediaElement->CurrentTime(); michael@0: // Remove all the cues from the active cue list whose end times now occur michael@0: // earlier then the current playback time. michael@0: for (uint32_t i = mActiveCueList->Length(); i > 0; i--) { michael@0: if ((*mActiveCueList)[i - 1]->EndTime() < playbackTime) { michael@0: mActiveCueList->RemoveCueAt(i - 1); michael@0: } michael@0: } michael@0: // Add all the cues, starting from the position of the last cue that was michael@0: // added, that have valid start and end times for the current playback time. michael@0: // We can stop iterating safely once we encounter a cue that does not have michael@0: // a valid start time as the cue list is sorted. michael@0: for (; mCuePos < mCueList->Length() && michael@0: (*mCueList)[mCuePos]->StartTime() <= playbackTime; mCuePos++) { michael@0: if ((*mCueList)[mCuePos]->EndTime() >= playbackTime) { michael@0: mActiveCueList->AddCue(*(*mCueList)[mCuePos]); michael@0: } michael@0: } michael@0: } michael@0: michael@0: TextTrackCueList* michael@0: TextTrack::GetActiveCues() { michael@0: if (mMode != TextTrackMode::Disabled) { michael@0: UpdateActiveCueList(); michael@0: return mActiveCueList; michael@0: } michael@0: return nullptr; michael@0: } michael@0: michael@0: void michael@0: TextTrack::GetActiveCueArray(nsTArray >& aCues) michael@0: { michael@0: if (mMode != TextTrackMode::Disabled) { michael@0: UpdateActiveCueList(); michael@0: mActiveCueList->GetArray(aCues); michael@0: } michael@0: } michael@0: michael@0: TextTrackReadyState michael@0: TextTrack::ReadyState() const michael@0: { michael@0: return mReadyState; michael@0: } michael@0: michael@0: void michael@0: TextTrack::SetReadyState(uint32_t aReadyState) michael@0: { michael@0: if (aReadyState <= TextTrackReadyState::FailedToLoad) { michael@0: SetReadyState(static_cast(aReadyState)); michael@0: } michael@0: } michael@0: michael@0: void michael@0: TextTrack::SetReadyState(TextTrackReadyState aState) michael@0: { michael@0: mReadyState = aState; michael@0: michael@0: if (!mTextTrackList) { michael@0: return; michael@0: } michael@0: michael@0: HTMLMediaElement* mediaElement = mTextTrackList->GetMediaElement(); michael@0: if (mediaElement && (mReadyState == TextTrackReadyState::Loaded|| michael@0: mReadyState == TextTrackReadyState::FailedToLoad)) { michael@0: mediaElement->RemoveTextTrack(this, true); michael@0: } michael@0: } michael@0: michael@0: TextTrackList* michael@0: TextTrack::GetTextTrackList() michael@0: { michael@0: return mTextTrackList; michael@0: } michael@0: michael@0: void michael@0: TextTrack::SetTextTrackList(TextTrackList* aTextTrackList) michael@0: { michael@0: mTextTrackList = aTextTrackList; michael@0: } michael@0: michael@0: HTMLTrackElement* michael@0: TextTrack::GetTrackElement() { michael@0: return mTrackElement; michael@0: } michael@0: michael@0: void michael@0: TextTrack::SetTrackElement(HTMLTrackElement* aTrackElement) { michael@0: mTrackElement = aTrackElement; michael@0: } michael@0: michael@0: } // namespace dom michael@0: } // namespace mozilla