Home | History | Annotate | Download | only in model
      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.UnsupportContentTypeException;
     21 import com.android.mms.LogTag;
     22 import com.android.mms.MmsConfig;
     23 import android.drm.mobile1.DrmException;
     24 import com.android.mms.drm.DrmWrapper;
     25 import com.google.android.mms.ContentType;
     26 import com.google.android.mms.MmsException;
     27 import com.google.android.mms.pdu.PduBody;
     28 import com.google.android.mms.pdu.PduPart;
     29 
     30 import org.w3c.dom.smil.SMILMediaElement;
     31 import org.w3c.dom.smil.SMILRegionElement;
     32 import org.w3c.dom.smil.SMILRegionMediaElement;
     33 import org.w3c.dom.smil.Time;
     34 import org.w3c.dom.smil.TimeList;
     35 
     36 import android.content.Context;
     37 import android.util.Log;
     38 
     39 import java.io.IOException;
     40 
     41 public class MediaModelFactory {
     42     private static final String TAG = "Mms:media";
     43 
     44     public static MediaModel getMediaModel(Context context,
     45             SMILMediaElement sme, LayoutModel layouts, PduBody pb)
     46             throws DrmException, IOException, IllegalArgumentException, MmsException {
     47         String tag = sme.getTagName();
     48         String src = sme.getSrc();
     49         PduPart part = findPart(pb, src);
     50 
     51         if (sme instanceof SMILRegionMediaElement) {
     52             return getRegionMediaModel(
     53                     context, tag, src, (SMILRegionMediaElement) sme, layouts, part);
     54         } else {
     55             return getGenericMediaModel(
     56                     context, tag, src, sme, part, null);
     57         }
     58     }
     59 
     60     private static PduPart findPart(PduBody pb, String src) {
     61         PduPart part = null;
     62 
     63         if (src != null) {
     64             if (src.startsWith("cid:")) {
     65                 part = pb.getPartByContentId("<" + src.substring("cid:".length()) + ">");
     66             } else {
     67                 part = pb.getPartByName(src);
     68                 if (part == null) {
     69                     part = pb.getPartByFileName(src);
     70                     if (part == null) {
     71                         part = pb.getPartByContentLocation(src);
     72                     }
     73                 }
     74             }
     75         }
     76 
     77         if (part != null) {
     78             return part;
     79         }
     80 
     81         throw new IllegalArgumentException("No part found for the model.");
     82     }
     83 
     84     private static MediaModel getRegionMediaModel(Context context,
     85             String tag, String src, SMILRegionMediaElement srme,
     86             LayoutModel layouts, PduPart part) throws DrmException, IOException, MmsException {
     87         SMILRegionElement sre = srme.getRegion();
     88         if (sre != null) {
     89             RegionModel region = layouts.findRegionById(sre.getId());
     90             if (region != null) {
     91                 return getGenericMediaModel(context, tag, src, srme, part, region);
     92             }
     93         } else {
     94             String rId = null;
     95 
     96             if (tag.equals(SmilHelper.ELEMENT_TAG_TEXT)) {
     97                 rId = LayoutModel.TEXT_REGION_ID;
     98             } else {
     99                 rId = LayoutModel.IMAGE_REGION_ID;
    100             }
    101 
    102             RegionModel region = layouts.findRegionById(rId);
    103             if (region != null) {
    104                 return getGenericMediaModel(context, tag, src, srme, part, region);
    105             }
    106         }
    107 
    108         throw new IllegalArgumentException("Region not found or bad region ID.");
    109     }
    110 
    111     private static MediaModel getGenericMediaModel(Context context,
    112             String tag, String src, SMILMediaElement sme, PduPart part,
    113             RegionModel regionModel) throws DrmException, IOException, MmsException {
    114         byte[] bytes = part.getContentType();
    115         if (bytes == null) {
    116             throw new IllegalArgumentException(
    117                     "Content-Type of the part may not be null.");
    118         }
    119 
    120         String contentType = new String(bytes);
    121         MediaModel media = null;
    122         if (ContentType.isDrmType(contentType)) {
    123             DrmWrapper wrapper = new DrmWrapper(
    124                     contentType, part.getDataUri(), part.getData());
    125             if (tag.equals(SmilHelper.ELEMENT_TAG_TEXT)) {
    126                 media = new TextModel(context, contentType, src,
    127                         part.getCharset(), wrapper, regionModel);
    128             } else if (tag.equals(SmilHelper.ELEMENT_TAG_IMAGE)) {
    129                 media = new ImageModel(context, contentType, src,
    130                         wrapper, regionModel);
    131             } else if (tag.equals(SmilHelper.ELEMENT_TAG_VIDEO)) {
    132                 media = new VideoModel(context, contentType, src,
    133                         wrapper, regionModel);
    134             } else if (tag.equals(SmilHelper.ELEMENT_TAG_AUDIO)) {
    135                 media = new AudioModel(context, contentType, src,
    136                         wrapper);
    137             } else if (tag.equals(SmilHelper.ELEMENT_TAG_REF)) {
    138                 String drmContentType = wrapper.getContentType();
    139                 if (ContentType.isTextType(drmContentType)) {
    140                     media = new TextModel(context, contentType, src,
    141                             part.getCharset(), wrapper, regionModel);
    142                 } else if (ContentType.isImageType(drmContentType)) {
    143                     media = new ImageModel(context, contentType, src,
    144                             wrapper, regionModel);
    145                 } else if (ContentType.isVideoType(drmContentType)) {
    146                     media = new VideoModel(context, contentType, src,
    147                             wrapper, regionModel);
    148                 } else if (ContentType.isAudioType(drmContentType)) {
    149                     media = new AudioModel(context, contentType, src,
    150                             wrapper);
    151                 } else {
    152                     throw new UnsupportContentTypeException(
    153                         "Unsupported Content-Type: " + drmContentType);
    154                 }
    155             } else {
    156                 throw new IllegalArgumentException("Unsupported TAG: " + tag);
    157             }
    158         } else {
    159             if (tag.equals(SmilHelper.ELEMENT_TAG_TEXT)) {
    160                 media = new TextModel(context, contentType, src,
    161                         part.getCharset(), part.getData(), regionModel);
    162             } else if (tag.equals(SmilHelper.ELEMENT_TAG_IMAGE)) {
    163                 media = new ImageModel(context, contentType, src,
    164                         part.getDataUri(), regionModel);
    165             } else if (tag.equals(SmilHelper.ELEMENT_TAG_VIDEO)) {
    166                 media = new VideoModel(context, contentType, src,
    167                         part.getDataUri(), regionModel);
    168             } else if (tag.equals(SmilHelper.ELEMENT_TAG_AUDIO)) {
    169                 media = new AudioModel(context, contentType, src,
    170                         part.getDataUri());
    171             } else if (tag.equals(SmilHelper.ELEMENT_TAG_REF)) {
    172                 if (ContentType.isTextType(contentType)) {
    173                     media = new TextModel(context, contentType, src,
    174                             part.getCharset(), part.getData(), regionModel);
    175                 } else if (ContentType.isImageType(contentType)) {
    176                     media = new ImageModel(context, contentType, src,
    177                             part.getDataUri(), regionModel);
    178                 } else if (ContentType.isVideoType(contentType)) {
    179                     media = new VideoModel(context, contentType, src,
    180                             part.getDataUri(), regionModel);
    181                 } else if (ContentType.isAudioType(contentType)) {
    182                     media = new AudioModel(context, contentType, src,
    183                             part.getDataUri());
    184                 } else {
    185                     throw new UnsupportContentTypeException(
    186                         "Unsupported Content-Type: " + contentType);
    187                 }
    188             } else {
    189                 throw new IllegalArgumentException("Unsupported TAG: " + tag);
    190             }
    191         }
    192 
    193         // Set 'begin' property.
    194         int begin = 0;
    195         TimeList tl = sme.getBegin();
    196         if ((tl != null) && (tl.getLength() > 0)) {
    197             // We only support a single begin value.
    198             Time t = tl.item(0);
    199             begin = (int) (t.getResolvedOffset() * 1000);
    200         }
    201         media.setBegin(begin);
    202 
    203         // Set 'duration' property.
    204         int duration = (int) (sme.getDur() * 1000);
    205         if (duration <= 0) {
    206             tl = sme.getEnd();
    207             if ((tl != null) && (tl.getLength() > 0)) {
    208                 // We only support a single end value.
    209                 Time t = tl.item(0);
    210                 if (t.getTimeType() != Time.SMIL_TIME_INDEFINITE) {
    211                     duration = (int) (t.getResolvedOffset() * 1000) - begin;
    212 
    213                     if (duration == 0 &&
    214                             (media instanceof AudioModel || media instanceof VideoModel)) {
    215                         duration = MmsConfig.getMinimumSlideElementDuration();
    216                         if (Log.isLoggable(LogTag.APP, Log.VERBOSE)) {
    217                             Log.d(TAG, "[MediaModelFactory] compute new duration for " + tag +
    218                                     ", duration=" + duration);
    219                         }
    220                     }
    221                 }
    222             }
    223         }
    224 
    225         media.setDuration(duration);
    226 
    227         // Set 'fill' property.
    228         media.setFill(sme.getFill());
    229         return media;
    230     }
    231 }
    232