Line data Source code
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/. */
6 :
7 : #include "mozilla/dom/TimeRanges.h"
8 : #include "mozilla/dom/TimeRangesBinding.h"
9 : #include "mozilla/dom/HTMLMediaElement.h"
10 : #include "nsError.h"
11 :
12 : namespace mozilla {
13 : namespace dom {
14 :
15 0 : NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(TimeRanges, mParent)
16 1 : NS_IMPL_CYCLE_COLLECTING_ADDREF(TimeRanges)
17 0 : NS_IMPL_CYCLE_COLLECTING_RELEASE(TimeRanges)
18 1 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(TimeRanges)
19 0 : NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
20 0 : NS_INTERFACE_MAP_ENTRY(nsIDOMTimeRanges)
21 0 : NS_INTERFACE_MAP_ENTRY(nsISupports)
22 0 : NS_INTERFACE_MAP_END
23 :
24 0 : TimeRanges::TimeRanges()
25 0 : : mParent(nullptr)
26 : {
27 0 : }
28 :
29 1 : TimeRanges::TimeRanges(nsISupports* aParent)
30 1 : : mParent(aParent)
31 : {
32 1 : }
33 :
34 0 : TimeRanges::~TimeRanges()
35 : {
36 0 : }
37 :
38 : NS_IMETHODIMP
39 0 : TimeRanges::GetLength(uint32_t* aLength)
40 : {
41 0 : *aLength = Length();
42 0 : return NS_OK;
43 : }
44 :
45 : double
46 0 : TimeRanges::Start(uint32_t aIndex, ErrorResult& aRv)
47 : {
48 0 : if (aIndex >= mRanges.Length()) {
49 0 : aRv = NS_ERROR_DOM_INDEX_SIZE_ERR;
50 0 : return 0;
51 : }
52 :
53 0 : return mRanges[aIndex].mStart;
54 : }
55 :
56 : NS_IMETHODIMP
57 0 : TimeRanges::Start(uint32_t aIndex, double* aTime)
58 : {
59 0 : ErrorResult rv;
60 0 : *aTime = Start(aIndex, rv);
61 0 : return rv.StealNSResult();
62 : }
63 :
64 : double
65 0 : TimeRanges::End(uint32_t aIndex, ErrorResult& aRv)
66 : {
67 0 : if (aIndex >= mRanges.Length()) {
68 0 : aRv = NS_ERROR_DOM_INDEX_SIZE_ERR;
69 0 : return 0;
70 : }
71 :
72 0 : return mRanges[aIndex].mEnd;
73 : }
74 :
75 : NS_IMETHODIMP
76 0 : TimeRanges::End(uint32_t aIndex, double* aTime)
77 : {
78 0 : ErrorResult rv;
79 0 : *aTime = End(aIndex, rv);
80 0 : return rv.StealNSResult();
81 : }
82 :
83 : void
84 0 : TimeRanges::Add(double aStart, double aEnd)
85 : {
86 0 : if (aStart > aEnd) {
87 0 : NS_WARNING("Can't add a range if the end is older that the start.");
88 0 : return;
89 : }
90 0 : mRanges.AppendElement(TimeRange(aStart,aEnd));
91 : }
92 :
93 : double
94 0 : TimeRanges::GetStartTime()
95 : {
96 0 : if (mRanges.IsEmpty()) {
97 0 : return -1.0;
98 : }
99 0 : return mRanges[0].mStart;
100 : }
101 :
102 : double
103 0 : TimeRanges::GetEndTime()
104 : {
105 0 : if (mRanges.IsEmpty()) {
106 0 : return -1.0;
107 : }
108 0 : return mRanges[mRanges.Length() - 1].mEnd;
109 : }
110 :
111 : void
112 0 : TimeRanges::Normalize(double aTolerance)
113 : {
114 0 : if (mRanges.Length() >= 2) {
115 0 : AutoTArray<TimeRange,4> normalized;
116 :
117 0 : mRanges.Sort(CompareTimeRanges());
118 :
119 : // This merges the intervals.
120 0 : TimeRange current(mRanges[0]);
121 0 : for (uint32_t i = 1; i < mRanges.Length(); i++) {
122 0 : if (current.mStart <= mRanges[i].mStart &&
123 0 : current.mEnd >= mRanges[i].mEnd) {
124 0 : continue;
125 : }
126 0 : if (current.mEnd + aTolerance >= mRanges[i].mStart) {
127 0 : current.mEnd = mRanges[i].mEnd;
128 : } else {
129 0 : normalized.AppendElement(current);
130 0 : current = mRanges[i];
131 : }
132 : }
133 :
134 0 : normalized.AppendElement(current);
135 :
136 0 : mRanges = normalized;
137 : }
138 0 : }
139 :
140 : void
141 0 : TimeRanges::Union(const TimeRanges* aOtherRanges, double aTolerance)
142 : {
143 0 : mRanges.AppendElements(aOtherRanges->mRanges);
144 0 : Normalize(aTolerance);
145 0 : }
146 :
147 : void
148 0 : TimeRanges::Intersection(const TimeRanges* aOtherRanges)
149 : {
150 0 : AutoTArray<TimeRange,4> intersection;
151 :
152 0 : const nsTArray<TimeRange>& otherRanges = aOtherRanges->mRanges;
153 0 : for (index_type i = 0, j = 0; i < mRanges.Length() && j < otherRanges.Length();) {
154 0 : double start = std::max(mRanges[i].mStart, otherRanges[j].mStart);
155 0 : double end = std::min(mRanges[i].mEnd, otherRanges[j].mEnd);
156 0 : if (start < end) {
157 0 : intersection.AppendElement(TimeRange(start, end));
158 : }
159 0 : if (mRanges[i].mEnd < otherRanges[j].mEnd) {
160 0 : i += 1;
161 : } else {
162 0 : j += 1;
163 : }
164 : }
165 :
166 0 : mRanges = intersection;
167 0 : }
168 :
169 : TimeRanges::index_type
170 0 : TimeRanges::Find(double aTime, double aTolerance /* = 0 */)
171 : {
172 0 : for (index_type i = 0; i < mRanges.Length(); ++i) {
173 0 : if (aTime < mRanges[i].mEnd && (aTime + aTolerance) >= mRanges[i].mStart) {
174 0 : return i;
175 : }
176 : }
177 0 : return NoIndex;
178 : }
179 :
180 : JSObject*
181 0 : TimeRanges::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
182 : {
183 0 : return TimeRangesBinding::Wrap(aCx, this, aGivenProto);
184 : }
185 :
186 : nsISupports*
187 0 : TimeRanges::GetParentObject() const
188 : {
189 0 : return mParent;
190 : }
191 :
192 : void
193 0 : TimeRanges::Shift(double aOffset)
194 : {
195 0 : for (index_type i = 0; i < mRanges.Length(); ++i) {
196 0 : mRanges[i].mStart += aOffset;
197 0 : mRanges[i].mEnd += aOffset;
198 : }
199 0 : }
200 :
201 : } // namespace dom
202 : } // namespace mozilla
|