• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2007-2008 Esmertec AG.
3  * Copyright (C) 2007-2008 The Android Open Source Project
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 package com.android.mms.dom.smil;
19 
20 import java.util.ArrayList;
21 
22 import org.w3c.dom.DOMException;
23 import org.w3c.dom.smil.ElementTime;
24 import org.w3c.dom.smil.SMILElement;
25 import org.w3c.dom.smil.Time;
26 import org.w3c.dom.smil.TimeList;
27 
28 import android.util.Log;
29 
30 public abstract class ElementTimeImpl implements ElementTime {
31     private static final String TAG = "ElementTimeImpl";
32 
33     private static final String FILL_REMOVE_ATTRIBUTE = "remove";
34     private static final String FILL_FREEZE_ATTRIBUTE = "freeze";
35     private static final String FILL_HOLD_ATTRIBUTE = "hold";
36     private static final String FILL_TRANSITION_ATTRIBUTE = "transition";
37     private static final String FILL_AUTO_ATTRIBUTE   = "auto";
38     private static final String FILL_ATTRIBUTE_NAME   = "fill";
39     private static final String FILLDEFAULT_ATTRIBUTE_NAME   = "fillDefault";
40 
41     final SMILElement mSmilElement;
42 
43     /*
44      * Internal Interface
45      */
ElementTimeImpl(SMILElement element)46     ElementTimeImpl(SMILElement element) {
47         mSmilElement = element;
48     }
49 
50     // Default implementation. Override if required.
getBeginConstraints()51     int getBeginConstraints() {
52         return TimeImpl.ALLOW_ALL;
53     }
54 
55     // Default implementation. Override if required
getEndConstraints()56     int getEndConstraints() {
57         return TimeImpl.ALLOW_ALL;
58     }
59 
60     /**
61      * To get the parent node on the ElementTime tree. It is in opposition to getTimeChildren.
62      * @return the parent ElementTime. Returns <code>null</code> if there is no parent.
63      */
getParentElementTime()64     abstract ElementTime getParentElementTime();
65 
66     /*
67      * ElementTime Interface
68      */
69 
getBegin()70     public TimeList getBegin() {
71         String[] beginTimeStringList = mSmilElement.getAttribute("begin").split(";");
72 
73         // TODO: Check other constraints on parsed values, e.g., "single, non-negative offset values
74         ArrayList<Time> beginTimeList = new ArrayList<Time>();
75         // Initialize Time instances and add them to Vector
76         for (int i = 0; i < beginTimeStringList.length; i++) {
77             try {
78                 beginTimeList.add(new TimeImpl(beginTimeStringList[i], getBeginConstraints()));
79             } catch (IllegalArgumentException e) {
80                 // Ignore badly formatted times
81             }
82         }
83         if (beginTimeList.size() == 0) {
84             /*
85              * What is the right default value?
86              *
87              * In MMS SMIL, this method may be called either on an instance of:
88              *
89              * 1 - ElementSequentialTimeContainer (The SMILDocument)
90              * 2 - ElementParallelTimeContainer (A Time-Child of the SMILDocument, which is a seq)
91              * 3 - ElementTime (A SMILMediaElement).
92              *
93              * 1 - In the first case, the default start time is obviously 0.
94              * 2 - In the second case, the specifications mentions that
95              *      "For children of a sequence, the only legal value for begin is
96              *      a (single) non-negative offset value. The default begin value is 0."
97              * 3 - In the third case, the specification mentions that
98              *      "The default value of begin for children of a par is 0."
99              *
100              * In short, if no value is specified, the default is always 0.
101              */
102 
103             beginTimeList.add(new TimeImpl("0", TimeImpl.ALLOW_ALL));
104         }
105         return new TimeListImpl(beginTimeList);
106     }
107 
getDur()108     public float getDur() {
109         float dur = 0;
110         try {
111             String durString = mSmilElement.getAttribute("dur");
112             if (durString != null) {
113                 dur = TimeImpl.parseClockValue(durString) / 1000f;
114             }
115         } catch (IllegalArgumentException e) {
116             // Do nothing and return the minimum value
117         }
118 
119         return dur;
120     }
121 
getEnd()122     public TimeList getEnd() {
123         ArrayList<Time> endTimeList = new ArrayList<Time>();
124 
125         String[] endTimeStringList = mSmilElement.getAttribute("end").split(";");
126         int len = endTimeStringList.length;
127         if (!((len == 1) && (endTimeStringList[0].length() == 0))) {  // Ensure the end field is set.
128             // Initialize Time instances and add them to Vector
129             for (int i = 0; i < len; i++) {
130                 try {
131                     endTimeList.add(new TimeImpl(endTimeStringList[i],
132                             getEndConstraints()));
133                 } catch (IllegalArgumentException e) {
134                     // Ignore badly formatted times
135                     Log.e(TAG, "Malformed time value.", e);
136                 }
137             }
138         }
139 
140         // "end" time is not specified
141         if (endTimeList.size() == 0) {
142             // Get duration
143             float duration = getDur();
144 
145             if (duration < 0) {
146                 endTimeList.add(new TimeImpl("indefinite", getEndConstraints()));
147             } else {
148                 // Get begin
149                 TimeList begin = getBegin();
150                 for (int i = 0; i < begin.getLength(); i++) {
151                     endTimeList.add(new TimeImpl(
152                             // end = begin + dur
153                             begin.item(i).getResolvedOffset() + duration + "s",
154                             getEndConstraints()));
155                 }
156             }
157         }
158 
159         return new TimeListImpl(endTimeList);
160     }
161 
beginAndEndAreZero()162     private boolean beginAndEndAreZero() {
163         TimeList begin = getBegin();
164         TimeList end = getEnd();
165         if (begin.getLength() == 1 && end.getLength() == 1) {
166             Time beginTime = begin.item(0);
167             Time endTime = end.item(0);
168             return beginTime.getOffset() == 0. && endTime.getOffset() == 0.;
169         }
170         return false;
171     }
172 
getFill()173     public short getFill() {
174         String fill = mSmilElement.getAttribute(FILL_ATTRIBUTE_NAME);
175         if (fill.equalsIgnoreCase(FILL_FREEZE_ATTRIBUTE)) {
176             return FILL_FREEZE;
177         } else if (fill.equalsIgnoreCase(FILL_REMOVE_ATTRIBUTE)) {
178             return FILL_REMOVE;
179         } else if (fill.equalsIgnoreCase(FILL_HOLD_ATTRIBUTE)) {
180             // FIXME handle it as freeze for now
181             return FILL_FREEZE;
182         } else if (fill.equalsIgnoreCase(FILL_TRANSITION_ATTRIBUTE)) {
183             // FIXME handle it as freeze for now
184             return FILL_FREEZE;
185         } else if (!fill.equalsIgnoreCase(FILL_AUTO_ATTRIBUTE)) {
186             /*
187              * fill = default
188              * The fill behavior for the element is determined by the value of the fillDefault
189              * attribute.  This is the default value.
190              */
191             short fillDefault = getFillDefault();
192             if (fillDefault != FILL_AUTO) {
193                 return fillDefault;
194             }
195         }
196 
197         /*
198          * fill = auto
199          * The fill behavior for this element depends on whether the element specifies any of
200          * the attributes that define the simple or active duration:
201          *  - If none of the attributes dur, end, repeatCount or repeatDur are specified on
202          *    the element, then the element will have a fill behavior identical to that if it were
203          *    specified as "freeze".
204          *  - Otherwise, the element will have a fill behavior identical to that if it were
205          *    specified as "remove".
206          */
207         if (((mSmilElement.getAttribute("dur").length() == 0) &&
208                 (mSmilElement.getAttribute("end").length() == 0) &&
209                 (mSmilElement.getAttribute("repeatCount").length() == 0) &&
210                 (mSmilElement.getAttribute("repeatDur").length() == 0)) ||
211                 beginAndEndAreZero()) {
212             return FILL_FREEZE;
213         } else {
214             return FILL_REMOVE;
215         }
216     }
217 
getFillDefault()218     public short getFillDefault() {
219         String fillDefault = mSmilElement.getAttribute(FILLDEFAULT_ATTRIBUTE_NAME);
220         if (fillDefault.equalsIgnoreCase(FILL_REMOVE_ATTRIBUTE)) {
221             return FILL_REMOVE;
222         } else if (fillDefault.equalsIgnoreCase(FILL_FREEZE_ATTRIBUTE)) {
223             return FILL_FREEZE;
224         } else if (fillDefault.equalsIgnoreCase(FILL_AUTO_ATTRIBUTE)) {
225             return FILL_AUTO;
226         } else if (fillDefault.equalsIgnoreCase(FILL_HOLD_ATTRIBUTE)) {
227             // FIXME handle it as freeze for now
228             return FILL_FREEZE;
229         } else if (fillDefault.equalsIgnoreCase(FILL_TRANSITION_ATTRIBUTE)) {
230             // FIXME handle it as freeze for now
231             return FILL_FREEZE;
232         } else {
233             /*
234              * fillDefault = inherit
235              * Specifies that the value of this attribute (and of the fill behavior) are
236              * inherited from the fillDefault value of the parent element.
237              * This is the default value.
238              */
239             ElementTime parent = getParentElementTime();
240             if (parent == null) {
241                 /*
242                  * fillDefault = auto
243                  * If there is no parent element, the value is "auto".
244                  */
245                 return FILL_AUTO;
246             } else {
247                 return ((ElementTimeImpl) parent).getFillDefault();
248             }
249         }
250     }
251 
getRepeatCount()252     public float getRepeatCount() {
253         String repeatCount = mSmilElement.getAttribute("repeatCount");
254         try {
255             float value = Float.parseFloat(repeatCount);
256             if (value > 0) {
257                 return value;
258             } else {
259                 return 0; // default
260             }
261         } catch (NumberFormatException e) {
262             return 0; // default
263         }
264     }
265 
getRepeatDur()266     public float getRepeatDur() {
267         try {
268             float repeatDur =
269                 TimeImpl.parseClockValue(mSmilElement.getAttribute("repeatDur"));
270             if (repeatDur > 0) {
271                 return repeatDur;
272             } else {
273                 return 0; // default
274             }
275         } catch (IllegalArgumentException e) {
276             return 0; // default
277         }
278     }
279 
getRestart()280     public short getRestart() {
281         String restart = mSmilElement.getAttribute("restart");
282         if (restart.equalsIgnoreCase("never")) {
283             return RESTART_NEVER;
284         } else if (restart.equalsIgnoreCase("whenNotActive")) {
285             return RESTART_WHEN_NOT_ACTIVE;
286         } else {
287             return RESTART_ALWAYS; // default
288         }
289     }
290 
setBegin(TimeList begin)291     public void setBegin(TimeList begin) throws DOMException {
292         // TODO Implement this
293         mSmilElement.setAttribute("begin", "indefinite");
294     }
295 
setDur(float dur)296     public void setDur(float dur) throws DOMException {
297         // In SMIL 3.0, the dur could be a timecount-value which may contain fractions.
298         // However, in MMS 1.3, the dur SHALL be expressed in integer milliseconds.
299         mSmilElement.setAttribute("dur", Integer.toString((int)(dur * 1000)) + "ms");
300     }
301 
setEnd(TimeList end)302     public void setEnd(TimeList end) throws DOMException {
303         // TODO Implement this
304         mSmilElement.setAttribute("end", "indefinite");
305     }
306 
setFill(short fill)307     public void setFill(short fill) throws DOMException {
308         if (fill == FILL_FREEZE) {
309             mSmilElement.setAttribute(FILL_ATTRIBUTE_NAME, FILL_FREEZE_ATTRIBUTE);
310         } else {
311             mSmilElement.setAttribute(FILL_ATTRIBUTE_NAME, FILL_REMOVE_ATTRIBUTE); // default
312         }
313     }
314 
setFillDefault(short fillDefault)315     public void setFillDefault(short fillDefault) throws DOMException {
316         if (fillDefault == FILL_FREEZE) {
317             mSmilElement.setAttribute(FILLDEFAULT_ATTRIBUTE_NAME, FILL_FREEZE_ATTRIBUTE);
318         } else {
319             mSmilElement.setAttribute(FILLDEFAULT_ATTRIBUTE_NAME, FILL_REMOVE_ATTRIBUTE);
320         }
321     }
322 
setRepeatCount(float repeatCount)323     public void setRepeatCount(float repeatCount) throws DOMException {
324         String repeatCountString = "indefinite";
325         if (repeatCount > 0) {
326             repeatCountString = Float.toString(repeatCount);
327         }
328         mSmilElement.setAttribute("repeatCount", repeatCountString);
329     }
330 
setRepeatDur(float repeatDur)331     public void setRepeatDur(float repeatDur) throws DOMException {
332         String repeatDurString = "indefinite";
333         if (repeatDur > 0) {
334             repeatDurString = Float.toString(repeatDur) + "ms";
335         }
336         mSmilElement.setAttribute("repeatDur", repeatDurString);
337     }
338 
setRestart(short restart)339     public void setRestart(short restart) throws DOMException {
340         if (restart == RESTART_NEVER) {
341             mSmilElement.setAttribute("restart", "never");
342         } else if (restart == RESTART_WHEN_NOT_ACTIVE) {
343             mSmilElement.setAttribute("restart", "whenNotActive");
344         } else {
345             mSmilElement.setAttribute("restart", "always");
346         }
347     }
348 }
349