• 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 
getFill()162     public short getFill() {
163         String fill = mSmilElement.getAttribute(FILL_ATTRIBUTE_NAME);
164         if (fill.equalsIgnoreCase(FILL_FREEZE_ATTRIBUTE)) {
165             return FILL_FREEZE;
166         } else if (fill.equalsIgnoreCase(FILL_REMOVE_ATTRIBUTE)) {
167             return FILL_REMOVE;
168         } else if (fill.equalsIgnoreCase(FILL_HOLD_ATTRIBUTE)) {
169             // FIXME handle it as freeze for now
170             return FILL_FREEZE;
171         } else if (fill.equalsIgnoreCase(FILL_TRANSITION_ATTRIBUTE)) {
172             // FIXME handle it as freeze for now
173             return FILL_FREEZE;
174         } else if (!fill.equalsIgnoreCase(FILL_AUTO_ATTRIBUTE)) {
175             /*
176              * fill = default
177              * The fill behavior for the element is determined by the value of the fillDefault
178              * attribute.  This is the default value.
179              */
180             short fillDefault = getFillDefault();
181             if (fillDefault != FILL_AUTO) {
182                 return fillDefault;
183             }
184         }
185 
186         /*
187          * fill = auto
188          * The fill behavior for this element depends on whether the element specifies any of
189          * the attributes that define the simple or active duration:
190          *  - If none of the attributes dur, end, repeatCount or repeatDur are specified on
191          *    the element, then the element will have a fill behavior identical to that if it were
192          *    specified as "freeze".
193          *  - Otherwise, the element will have a fill behavior identical to that if it were
194          *    specified as "remove".
195          */
196         if ((mSmilElement.getAttribute("dur").length() == 0) &&
197                 (mSmilElement.getAttribute("end").length() == 0) &&
198                 (mSmilElement.getAttribute("repeatCount").length() == 0) &&
199                 (mSmilElement.getAttribute("repeatDur").length() == 0)) {
200             return FILL_FREEZE;
201         } else {
202             return FILL_REMOVE;
203         }
204     }
205 
getFillDefault()206     public short getFillDefault() {
207         String fillDefault = mSmilElement.getAttribute(FILLDEFAULT_ATTRIBUTE_NAME);
208         if (fillDefault.equalsIgnoreCase(FILL_REMOVE_ATTRIBUTE)) {
209             return FILL_REMOVE;
210         } else if (fillDefault.equalsIgnoreCase(FILL_FREEZE_ATTRIBUTE)) {
211             return FILL_FREEZE;
212         } else if (fillDefault.equalsIgnoreCase(FILL_AUTO_ATTRIBUTE)) {
213             return FILL_AUTO;
214         } else if (fillDefault.equalsIgnoreCase(FILL_HOLD_ATTRIBUTE)) {
215             // FIXME handle it as freeze for now
216             return FILL_FREEZE;
217         } else if (fillDefault.equalsIgnoreCase(FILL_TRANSITION_ATTRIBUTE)) {
218             // FIXME handle it as freeze for now
219             return FILL_FREEZE;
220         } else {
221             /*
222              * fillDefault = inherit
223              * Specifies that the value of this attribute (and of the fill behavior) are
224              * inherited from the fillDefault value of the parent element.
225              * This is the default value.
226              */
227             ElementTime parent = getParentElementTime();
228             if (parent == null) {
229                 /*
230                  * fillDefault = auto
231                  * If there is no parent element, the value is "auto".
232                  */
233                 return FILL_AUTO;
234             } else {
235                 return ((ElementTimeImpl) parent).getFillDefault();
236             }
237         }
238     }
239 
getRepeatCount()240     public float getRepeatCount() {
241         String repeatCount = mSmilElement.getAttribute("repeatCount");
242         try {
243             float value = Float.parseFloat(repeatCount);
244             if (value > 0) {
245                 return value;
246             } else {
247                 return 0; // default
248             }
249         } catch (NumberFormatException e) {
250             return 0; // default
251         }
252     }
253 
getRepeatDur()254     public float getRepeatDur() {
255         try {
256             float repeatDur =
257                 TimeImpl.parseClockValue(mSmilElement.getAttribute("repeatDur"));
258             if (repeatDur > 0) {
259                 return repeatDur;
260             } else {
261                 return 0; // default
262             }
263         } catch (IllegalArgumentException e) {
264             return 0; // default
265         }
266     }
267 
getRestart()268     public short getRestart() {
269         String restart = mSmilElement.getAttribute("restart");
270         if (restart.equalsIgnoreCase("never")) {
271             return RESTART_NEVER;
272         } else if (restart.equalsIgnoreCase("whenNotActive")) {
273             return RESTART_WHEN_NOT_ACTIVE;
274         } else {
275             return RESTART_ALWAYS; // default
276         }
277     }
278 
setBegin(TimeList begin)279     public void setBegin(TimeList begin) throws DOMException {
280         // TODO Implement this
281         mSmilElement.setAttribute("begin", "indefinite");
282     }
283 
setDur(float dur)284     public void setDur(float dur) throws DOMException {
285         // In SMIL 3.0, the dur could be a timecount-value which may contain fractions.
286         // However, in MMS 1.3, the dur SHALL be expressed in integer milliseconds.
287         mSmilElement.setAttribute("dur", Integer.toString((int)(dur * 1000)) + "ms");
288     }
289 
setEnd(TimeList end)290     public void setEnd(TimeList end) throws DOMException {
291         // TODO Implement this
292         mSmilElement.setAttribute("end", "indefinite");
293     }
294 
setFill(short fill)295     public void setFill(short fill) throws DOMException {
296         if (fill == FILL_FREEZE) {
297             mSmilElement.setAttribute(FILL_ATTRIBUTE_NAME, FILL_FREEZE_ATTRIBUTE);
298         } else {
299             mSmilElement.setAttribute(FILL_ATTRIBUTE_NAME, FILL_REMOVE_ATTRIBUTE); // default
300         }
301     }
302 
setFillDefault(short fillDefault)303     public void setFillDefault(short fillDefault) throws DOMException {
304         if (fillDefault == FILL_FREEZE) {
305             mSmilElement.setAttribute(FILLDEFAULT_ATTRIBUTE_NAME, FILL_FREEZE_ATTRIBUTE);
306         } else {
307             mSmilElement.setAttribute(FILLDEFAULT_ATTRIBUTE_NAME, FILL_REMOVE_ATTRIBUTE);
308         }
309     }
310 
setRepeatCount(float repeatCount)311     public void setRepeatCount(float repeatCount) throws DOMException {
312         String repeatCountString = "indefinite";
313         if (repeatCount > 0) {
314             repeatCountString = Float.toString(repeatCount);
315         }
316         mSmilElement.setAttribute("repeatCount", repeatCountString);
317     }
318 
setRepeatDur(float repeatDur)319     public void setRepeatDur(float repeatDur) throws DOMException {
320         String repeatDurString = "indefinite";
321         if (repeatDur > 0) {
322             repeatDurString = Float.toString(repeatDur) + "ms";
323         }
324         mSmilElement.setAttribute("repeatDur", repeatDurString);
325     }
326 
setRestart(short restart)327     public void setRestart(short restart) throws DOMException {
328         if (restart == RESTART_NEVER) {
329             mSmilElement.setAttribute("restart", "never");
330         } else if (restart == RESTART_WHEN_NOT_ACTIVE) {
331             mSmilElement.setAttribute("restart", "whenNotActive");
332         } else {
333             mSmilElement.setAttribute("restart", "always");
334         }
335     }
336 }
337