|
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
|
2 /* vim:set ts=2 sw=2 et tw=78: */ |
|
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/. */ |
|
6 |
|
7 #include "mozilla/dom/TextTrack.h" |
|
8 #include "mozilla/dom/TextTrackBinding.h" |
|
9 #include "mozilla/dom/TextTrackList.h" |
|
10 #include "mozilla/dom/TextTrackCue.h" |
|
11 #include "mozilla/dom/TextTrackCueList.h" |
|
12 #include "mozilla/dom/TextTrackRegion.h" |
|
13 #include "mozilla/dom/HTMLMediaElement.h" |
|
14 #include "mozilla/dom/HTMLTrackElement.h" |
|
15 |
|
16 namespace mozilla { |
|
17 namespace dom { |
|
18 |
|
19 NS_IMPL_CYCLE_COLLECTION_INHERITED(TextTrack, |
|
20 DOMEventTargetHelper, |
|
21 mCueList, |
|
22 mActiveCueList, |
|
23 mTextTrackList, |
|
24 mTrackElement) |
|
25 |
|
26 NS_IMPL_ADDREF_INHERITED(TextTrack, DOMEventTargetHelper) |
|
27 NS_IMPL_RELEASE_INHERITED(TextTrack, DOMEventTargetHelper) |
|
28 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(TextTrack) |
|
29 NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper) |
|
30 |
|
31 TextTrack::TextTrack(nsPIDOMWindow* aOwnerWindow, |
|
32 TextTrackKind aKind, |
|
33 const nsAString& aLabel, |
|
34 const nsAString& aLanguage, |
|
35 TextTrackMode aMode, |
|
36 TextTrackReadyState aReadyState, |
|
37 TextTrackSource aTextTrackSource) |
|
38 : DOMEventTargetHelper(aOwnerWindow) |
|
39 , mKind(aKind) |
|
40 , mLabel(aLabel) |
|
41 , mLanguage(aLanguage) |
|
42 , mMode(aMode) |
|
43 , mReadyState(aReadyState) |
|
44 , mTextTrackSource(aTextTrackSource) |
|
45 { |
|
46 SetDefaultSettings(); |
|
47 } |
|
48 |
|
49 TextTrack::TextTrack(nsPIDOMWindow* aOwnerWindow, |
|
50 TextTrackList* aTextTrackList, |
|
51 TextTrackKind aKind, |
|
52 const nsAString& aLabel, |
|
53 const nsAString& aLanguage, |
|
54 TextTrackMode aMode, |
|
55 TextTrackReadyState aReadyState, |
|
56 TextTrackSource aTextTrackSource) |
|
57 : DOMEventTargetHelper(aOwnerWindow) |
|
58 , mTextTrackList(aTextTrackList) |
|
59 , mKind(aKind) |
|
60 , mLabel(aLabel) |
|
61 , mLanguage(aLanguage) |
|
62 , mMode(aMode) |
|
63 , mReadyState(aReadyState) |
|
64 , mTextTrackSource(aTextTrackSource) |
|
65 { |
|
66 SetDefaultSettings(); |
|
67 } |
|
68 |
|
69 void |
|
70 TextTrack::SetDefaultSettings() |
|
71 { |
|
72 nsPIDOMWindow* ownerWindow = GetOwner(); |
|
73 mCueList = new TextTrackCueList(ownerWindow); |
|
74 mActiveCueList = new TextTrackCueList(ownerWindow); |
|
75 mCuePos = 0; |
|
76 mDirty = false; |
|
77 } |
|
78 |
|
79 JSObject* |
|
80 TextTrack::WrapObject(JSContext* aCx) |
|
81 { |
|
82 return TextTrackBinding::Wrap(aCx, this); |
|
83 } |
|
84 |
|
85 void |
|
86 TextTrack::SetMode(TextTrackMode aValue) |
|
87 { |
|
88 if (mMode != aValue) { |
|
89 mMode = aValue; |
|
90 if (mTextTrackList) { |
|
91 mTextTrackList->CreateAndDispatchChangeEvent(); |
|
92 } |
|
93 } |
|
94 } |
|
95 |
|
96 void |
|
97 TextTrack::GetId(nsAString& aId) const |
|
98 { |
|
99 // If the track has a track element then its id should be the same as the |
|
100 // track element's id. |
|
101 if (mTrackElement) { |
|
102 mTrackElement->GetAttribute(NS_LITERAL_STRING("id"), aId); |
|
103 } |
|
104 } |
|
105 |
|
106 void |
|
107 TextTrack::AddCue(TextTrackCue& aCue) |
|
108 { |
|
109 mCueList->AddCue(aCue); |
|
110 aCue.SetTrack(this); |
|
111 if (mTextTrackList) { |
|
112 HTMLMediaElement* mediaElement = mTextTrackList->GetMediaElement(); |
|
113 if (mediaElement) { |
|
114 mediaElement->AddCue(aCue); |
|
115 } |
|
116 } |
|
117 SetDirty(); |
|
118 } |
|
119 |
|
120 void |
|
121 TextTrack::RemoveCue(TextTrackCue& aCue, ErrorResult& aRv) |
|
122 { |
|
123 mCueList->RemoveCue(aCue, aRv); |
|
124 SetDirty(); |
|
125 } |
|
126 |
|
127 void |
|
128 TextTrack::SetCuesDirty() |
|
129 { |
|
130 for (uint32_t i = 0; i < mCueList->Length(); i++) { |
|
131 ((*mCueList)[i])->Reset(); |
|
132 } |
|
133 } |
|
134 |
|
135 void |
|
136 TextTrack::UpdateActiveCueList() |
|
137 { |
|
138 if (!mTextTrackList) { |
|
139 return; |
|
140 } |
|
141 |
|
142 HTMLMediaElement* mediaElement = mTextTrackList->GetMediaElement(); |
|
143 if (!mediaElement) { |
|
144 return; |
|
145 } |
|
146 |
|
147 // If we are dirty, i.e. an event happened that may cause the sorted mCueList |
|
148 // to have changed like a seek or an insert for a cue, than we need to rebuild |
|
149 // the active cue list from scratch. |
|
150 if (mDirty) { |
|
151 mCuePos = 0; |
|
152 mDirty = false; |
|
153 mActiveCueList->RemoveAll(); |
|
154 } |
|
155 |
|
156 double playbackTime = mediaElement->CurrentTime(); |
|
157 // Remove all the cues from the active cue list whose end times now occur |
|
158 // earlier then the current playback time. |
|
159 for (uint32_t i = mActiveCueList->Length(); i > 0; i--) { |
|
160 if ((*mActiveCueList)[i - 1]->EndTime() < playbackTime) { |
|
161 mActiveCueList->RemoveCueAt(i - 1); |
|
162 } |
|
163 } |
|
164 // Add all the cues, starting from the position of the last cue that was |
|
165 // added, that have valid start and end times for the current playback time. |
|
166 // We can stop iterating safely once we encounter a cue that does not have |
|
167 // a valid start time as the cue list is sorted. |
|
168 for (; mCuePos < mCueList->Length() && |
|
169 (*mCueList)[mCuePos]->StartTime() <= playbackTime; mCuePos++) { |
|
170 if ((*mCueList)[mCuePos]->EndTime() >= playbackTime) { |
|
171 mActiveCueList->AddCue(*(*mCueList)[mCuePos]); |
|
172 } |
|
173 } |
|
174 } |
|
175 |
|
176 TextTrackCueList* |
|
177 TextTrack::GetActiveCues() { |
|
178 if (mMode != TextTrackMode::Disabled) { |
|
179 UpdateActiveCueList(); |
|
180 return mActiveCueList; |
|
181 } |
|
182 return nullptr; |
|
183 } |
|
184 |
|
185 void |
|
186 TextTrack::GetActiveCueArray(nsTArray<nsRefPtr<TextTrackCue> >& aCues) |
|
187 { |
|
188 if (mMode != TextTrackMode::Disabled) { |
|
189 UpdateActiveCueList(); |
|
190 mActiveCueList->GetArray(aCues); |
|
191 } |
|
192 } |
|
193 |
|
194 TextTrackReadyState |
|
195 TextTrack::ReadyState() const |
|
196 { |
|
197 return mReadyState; |
|
198 } |
|
199 |
|
200 void |
|
201 TextTrack::SetReadyState(uint32_t aReadyState) |
|
202 { |
|
203 if (aReadyState <= TextTrackReadyState::FailedToLoad) { |
|
204 SetReadyState(static_cast<TextTrackReadyState>(aReadyState)); |
|
205 } |
|
206 } |
|
207 |
|
208 void |
|
209 TextTrack::SetReadyState(TextTrackReadyState aState) |
|
210 { |
|
211 mReadyState = aState; |
|
212 |
|
213 if (!mTextTrackList) { |
|
214 return; |
|
215 } |
|
216 |
|
217 HTMLMediaElement* mediaElement = mTextTrackList->GetMediaElement(); |
|
218 if (mediaElement && (mReadyState == TextTrackReadyState::Loaded|| |
|
219 mReadyState == TextTrackReadyState::FailedToLoad)) { |
|
220 mediaElement->RemoveTextTrack(this, true); |
|
221 } |
|
222 } |
|
223 |
|
224 TextTrackList* |
|
225 TextTrack::GetTextTrackList() |
|
226 { |
|
227 return mTextTrackList; |
|
228 } |
|
229 |
|
230 void |
|
231 TextTrack::SetTextTrackList(TextTrackList* aTextTrackList) |
|
232 { |
|
233 mTextTrackList = aTextTrackList; |
|
234 } |
|
235 |
|
236 HTMLTrackElement* |
|
237 TextTrack::GetTrackElement() { |
|
238 return mTrackElement; |
|
239 } |
|
240 |
|
241 void |
|
242 TextTrack::SetTrackElement(HTMLTrackElement* aTrackElement) { |
|
243 mTrackElement = aTrackElement; |
|
244 } |
|
245 |
|
246 } // namespace dom |
|
247 } // namespace mozilla |