• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2008 Esmertec AG.
3  * Copyright (C) 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.model;
19 
20 import com.android.mms.ContentRestrictionException;
21 import com.android.mms.dom.smil.SmilParElementImpl;
22 
23 import org.w3c.dom.events.Event;
24 import org.w3c.dom.events.EventListener;
25 import org.w3c.dom.smil.ElementTime;
26 
27 import android.util.Config;
28 import android.util.Log;
29 import android.text.TextUtils;
30 
31 import java.util.ArrayList;
32 import java.util.Collection;
33 import java.util.Iterator;
34 import java.util.List;
35 import java.util.ListIterator;
36 
37 public class SlideModel extends Model implements List<MediaModel>, EventListener {
38     public static final String TAG = "Mms/slideshow";
39     private static final boolean DEBUG = false;
40     private static final boolean LOCAL_LOGV = DEBUG ? Config.LOGD : Config.LOGV;
41     private static final int DEFAULT_SLIDE_DURATION = 5000;
42 
43     private final ArrayList<MediaModel> mMedia = new ArrayList<MediaModel>();
44 
45     private MediaModel mText;
46     private MediaModel mImage;
47     private MediaModel mAudio;
48     private MediaModel mVideo;
49 
50     private boolean mCanAddImage = true;
51     private boolean mCanAddAudio = true;
52     private boolean mCanAddVideo = true;
53 
54     private int mDuration;
55     private boolean mVisible = true;
56     private short mFill;
57     private int mSlideSize;
58     private SlideshowModel mParent;
59 
SlideModel(SlideshowModel slideshow)60     public SlideModel(SlideshowModel slideshow) {
61         this(DEFAULT_SLIDE_DURATION, slideshow);
62     }
63 
SlideModel(int duration, SlideshowModel slideshow)64     public SlideModel(int duration, SlideshowModel slideshow) {
65         mDuration = duration;
66         mParent = slideshow;
67     }
68 
69     /**
70      * Create a SlideModel with exist media collection.
71      *
72      * @param duration The duration of the slide.
73      * @param mediaList The exist media collection.
74      *
75      * @throws IllegalStateException One or more media in the mediaList cannot
76      *         be added into the slide due to a slide cannot contain image
77      *         and video or audio and video at the same time.
78      */
SlideModel(int duration, ArrayList<MediaModel> mediaList)79     public SlideModel(int duration, ArrayList<MediaModel> mediaList) {
80         mDuration = duration;
81 
82         int maxDur = 0;
83         for (MediaModel media : mediaList) {
84             internalAdd(media);
85 
86             int mediaDur = media.getDuration();
87             if (mediaDur > maxDur) {
88                 maxDur = mediaDur;
89             }
90         }
91 
92         updateDuration(maxDur);
93     }
94 
internalAdd(MediaModel media)95     private void internalAdd(MediaModel media) throws IllegalStateException {
96         if (media == null) {
97             // Don't add null value into the list.
98             return;
99         }
100 
101         if (media.isText()) {
102             String contentType = media.getContentType();
103             if (TextUtils.isEmpty(contentType) || "text/plain".equals(contentType)) {
104                 internalAddOrReplace(mText, media);
105                 mText = media;
106             } else {
107                 Log.w(TAG, "[SlideModel] content type " + media.getContentType() +
108                         " isn't supported (as text)");
109             }
110         } else if (media.isImage()) {
111             if (mCanAddImage) {
112                 internalAddOrReplace(mImage, media);
113                 mImage = media;
114                 mCanAddVideo = false;
115             } else {
116                 throw new IllegalStateException();
117             }
118         } else if (media.isAudio()) {
119             if (mCanAddAudio) {
120                 internalAddOrReplace(mAudio, media);
121                 mAudio = media;
122                 mCanAddVideo = false;
123             } else {
124                 throw new IllegalStateException();
125             }
126         } else if (media.isVideo()) {
127             if (mCanAddVideo) {
128                 internalAddOrReplace(mVideo, media);
129                 mVideo = media;
130                 mCanAddImage = false;
131                 mCanAddAudio = false;
132             } else {
133                 throw new IllegalStateException();
134             }
135         }
136     }
137 
internalAddOrReplace(MediaModel old, MediaModel media)138     private void internalAddOrReplace(MediaModel old, MediaModel media) {
139         int addSize = media.getMediaSize();
140         int removeSize;
141         if (old == null) {
142             if (null != mParent) {
143                 mParent.checkMessageSize(addSize);
144             }
145             mMedia.add(media);
146             increaseSlideSize(addSize);
147             increaseMessageSize(addSize);
148         } else {
149             removeSize = old.getMediaSize();
150             if (addSize > removeSize) {
151                 if (null != mParent) {
152                     mParent.checkMessageSize(addSize - removeSize);
153                 }
154                 increaseSlideSize(addSize - removeSize);
155                 increaseMessageSize(addSize - removeSize);
156             } else {
157                 decreaseSlideSize(removeSize - addSize);
158                 decreaseMessageSize(removeSize - addSize);
159             }
160             mMedia.set(mMedia.indexOf(old), media);
161             old.unregisterAllModelChangedObservers();
162         }
163 
164         for (IModelChangedObserver observer : mModelChangedObservers) {
165             media.registerModelChangedObserver(observer);
166         }
167     }
168 
internalRemove(Object object)169     private boolean internalRemove(Object object) {
170         if (mMedia.remove(object)) {
171             if (object instanceof TextModel) {
172                 mText = null;
173             } else if (object instanceof ImageModel) {
174                 mImage = null;
175                 mCanAddVideo = true;
176             } else if (object instanceof AudioModel) {
177                 mAudio = null;
178                 mCanAddVideo = true;
179             } else if (object instanceof VideoModel) {
180                 mVideo = null;
181                 mCanAddImage = true;
182                 mCanAddAudio = true;
183             }
184             int decreaseSize = ((MediaModel) object).getMediaSize();
185             decreaseSlideSize(decreaseSize);
186             decreaseMessageSize(decreaseSize);
187 
188             ((Model) object).unregisterAllModelChangedObservers();
189 
190             return true;
191         }
192 
193         return false;
194     }
195 
196     /**
197      * @return the mDuration
198      */
getDuration()199     public int getDuration() {
200         return mDuration;
201     }
202 
203     /**
204      * @param duration the mDuration to set
205      */
setDuration(int duration)206     public void setDuration(int duration) {
207         mDuration = duration;
208         notifyModelChanged(true);
209     }
210 
getSlideSize()211     public int getSlideSize() {
212         return mSlideSize;
213     }
214 
increaseSlideSize(int increaseSize)215     public void increaseSlideSize(int increaseSize) {
216         if (increaseSize > 0) {
217             mSlideSize += increaseSize;
218         }
219     }
220 
decreaseSlideSize(int decreaseSize)221     public void decreaseSlideSize(int decreaseSize) {
222         if (decreaseSize > 0) {
223             mSlideSize -= decreaseSize;
224         }
225     }
226 
setParent(SlideshowModel parent)227     public void setParent(SlideshowModel parent) {
228         mParent = parent;
229     }
230 
increaseMessageSize(int increaseSize)231     public void increaseMessageSize(int increaseSize) {
232         if ((increaseSize > 0) && (null != mParent)) {
233             int size = mParent.getCurrentMessageSize();
234             size += increaseSize;
235             mParent.setCurrentMessageSize(size);
236         }
237     }
238 
decreaseMessageSize(int decreaseSize)239     public void decreaseMessageSize(int decreaseSize) {
240         if ((decreaseSize > 0) && (null != mParent)) {
241             int size = mParent.getCurrentMessageSize();
242             size -= decreaseSize;
243             mParent.setCurrentMessageSize(size);
244         }
245     }
246 
247     //
248     // Implement List<E> interface.
249     //
250 
251     /**
252      * Add a MediaModel to the slide. If the slide has already contained
253      * a media object in the same type, the media object will be replaced by
254      * the new one.
255      *
256      * @param object A media object to be added into the slide.
257      * @return true
258      * @throws IllegalStateException One or more media in the mediaList cannot
259      *         be added into the slide due to a slide cannot contain image
260      *         and video or audio and video at the same time.
261      * @throws ContentRestrictionException when can not add this object.
262      *
263      */
add(MediaModel object)264     public boolean add(MediaModel object) {
265         internalAdd(object);
266         notifyModelChanged(true);
267         return true;
268     }
269 
addAll(Collection<? extends MediaModel> collection)270     public boolean addAll(Collection<? extends MediaModel> collection) {
271         throw new UnsupportedOperationException("Operation not supported.");
272     }
273 
clear()274     public void clear() {
275         if (mMedia.size() > 0) {
276             for (MediaModel media : mMedia) {
277                 media.unregisterAllModelChangedObservers();
278                 int decreaseSize = media.getMediaSize();
279                 decreaseSlideSize(decreaseSize);
280                 decreaseMessageSize(decreaseSize);
281             }
282             mMedia.clear();
283 
284             mText = null;
285             mImage = null;
286             mAudio = null;
287             mVideo = null;
288 
289             mCanAddImage = true;
290             mCanAddAudio = true;
291             mCanAddVideo = true;
292 
293             notifyModelChanged(true);
294         }
295     }
296 
contains(Object object)297     public boolean contains(Object object) {
298         return mMedia.contains(object);
299     }
300 
containsAll(Collection<?> collection)301     public boolean containsAll(Collection<?> collection) {
302         return mMedia.containsAll(collection);
303     }
304 
isEmpty()305     public boolean isEmpty() {
306         return mMedia.isEmpty();
307     }
308 
iterator()309     public Iterator<MediaModel> iterator() {
310         return mMedia.iterator();
311     }
312 
remove(Object object)313     public boolean remove(Object object) {
314         if ((object != null) && (object instanceof MediaModel)
315                 && internalRemove(object)) {
316             notifyModelChanged(true);
317             return true;
318         }
319         return false;
320     }
321 
removeAll(Collection<?> collection)322     public boolean removeAll(Collection<?> collection) {
323         throw new UnsupportedOperationException("Operation not supported.");
324     }
325 
retainAll(Collection<?> collection)326     public boolean retainAll(Collection<?> collection) {
327         throw new UnsupportedOperationException("Operation not supported.");
328     }
329 
size()330     public int size() {
331         return mMedia.size();
332     }
333 
toArray()334     public Object[] toArray() {
335         return mMedia.toArray();
336     }
337 
toArray(T[] array)338     public <T> T[] toArray(T[] array) {
339         return mMedia.toArray(array);
340     }
341 
add(int location, MediaModel object)342     public void add(int location, MediaModel object) {
343         throw new UnsupportedOperationException("Operation not supported.");
344     }
345 
addAll(int location, Collection<? extends MediaModel> collection)346     public boolean addAll(int location,
347             Collection<? extends MediaModel> collection) {
348         throw new UnsupportedOperationException("Operation not supported.");
349     }
350 
get(int location)351     public MediaModel get(int location) {
352         return mMedia.get(location);
353     }
354 
indexOf(Object object)355     public int indexOf(Object object) {
356         return mMedia.indexOf(object);
357     }
358 
lastIndexOf(Object object)359     public int lastIndexOf(Object object) {
360         return mMedia.lastIndexOf(object);
361     }
362 
listIterator()363     public ListIterator<MediaModel> listIterator() {
364         return mMedia.listIterator();
365     }
366 
listIterator(int location)367     public ListIterator<MediaModel> listIterator(int location) {
368         return mMedia.listIterator(location);
369     }
370 
remove(int location)371     public MediaModel remove(int location) {
372         MediaModel media = mMedia.get(location);
373         if ((media != null) && internalRemove(media)) {
374             notifyModelChanged(true);
375         }
376         return media;
377     }
378 
set(int location, MediaModel object)379     public MediaModel set(int location, MediaModel object) {
380         throw new UnsupportedOperationException("Operation not supported.");
381     }
382 
subList(int start, int end)383     public List<MediaModel> subList(int start, int end) {
384         return mMedia.subList(start, end);
385     }
386 
387     /**
388      * @return the mVisible
389      */
isVisible()390     public boolean isVisible() {
391         return mVisible;
392     }
393 
394     /**
395      * @param visible the mVisible to set
396      */
setVisible(boolean visible)397     public void setVisible(boolean visible) {
398         mVisible = visible;
399         notifyModelChanged(true);
400     }
401 
402     /**
403      * @return the mFill
404      */
getFill()405     public short getFill() {
406         return mFill;
407     }
408 
409     /**
410      * @param fill the mFill to set
411      */
setFill(short fill)412     public void setFill(short fill) {
413         mFill = fill;
414         notifyModelChanged(true);
415     }
416 
417     @Override
registerModelChangedObserverInDescendants( IModelChangedObserver observer)418     protected void registerModelChangedObserverInDescendants(
419             IModelChangedObserver observer) {
420         for (MediaModel media : mMedia) {
421             media.registerModelChangedObserver(observer);
422         }
423     }
424 
425     @Override
unregisterModelChangedObserverInDescendants( IModelChangedObserver observer)426     protected void unregisterModelChangedObserverInDescendants(
427             IModelChangedObserver observer) {
428         for (MediaModel media : mMedia) {
429             media.unregisterModelChangedObserver(observer);
430         }
431     }
432 
433     @Override
unregisterAllModelChangedObserversInDescendants()434     protected void unregisterAllModelChangedObserversInDescendants() {
435         for (MediaModel media : mMedia) {
436             media.unregisterAllModelChangedObservers();
437         }
438     }
439 
440     // EventListener Interface
handleEvent(Event evt)441     public void handleEvent(Event evt) {
442         if (evt.getType().equals(SmilParElementImpl.SMIL_SLIDE_START_EVENT)) {
443             if (LOCAL_LOGV) {
444                 Log.v(TAG, "Start to play slide: " + this);
445             }
446             mVisible = true;
447         } else if (mFill != ElementTime.FILL_FREEZE) {
448             if (LOCAL_LOGV) {
449                 Log.v(TAG, "Stop playing slide: " + this);
450             }
451             mVisible = false;
452         }
453 
454         notifyModelChanged(false);
455     }
456 
hasText()457     public boolean hasText() {
458         return mText != null;
459     }
460 
hasImage()461     public boolean hasImage() {
462         return mImage != null;
463     }
464 
hasAudio()465     public boolean hasAudio() {
466         return mAudio != null;
467     }
468 
hasVideo()469     public boolean hasVideo() {
470         return mVideo != null;
471     }
472 
removeText()473     public boolean removeText() {
474         return remove(mText);
475     }
476 
removeImage()477     public boolean removeImage() {
478         return remove(mImage);
479     }
480 
removeAudio()481     public boolean removeAudio() {
482         return remove(mAudio);
483     }
484 
removeVideo()485     public boolean removeVideo() {
486         return remove(mVideo);
487     }
488 
getText()489     public TextModel getText() {
490         return (TextModel) mText;
491     }
492 
getImage()493     public ImageModel getImage() {
494         return (ImageModel) mImage;
495     }
496 
getAudio()497     public AudioModel getAudio() {
498         return (AudioModel) mAudio;
499     }
500 
getVideo()501     public VideoModel getVideo() {
502         return (VideoModel) mVideo;
503     }
504 
updateDuration(int duration)505     public void updateDuration(int duration) {
506         if (duration <= 0) {
507             return;
508         }
509 
510         if ((duration > mDuration)
511                 || (mDuration == DEFAULT_SLIDE_DURATION)) {
512             mDuration = duration;
513         }
514     }
515 }
516