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 com.android.mms.drm.DrmWrapper; 24 import com.google.android.mms.ContentType; 25 import com.google.android.mms.MmsException; 26 import com.google.android.mms.pdu.PduBody; 27 import com.google.android.mms.pdu.PduPart; 28 29 import org.w3c.dom.smil.SMILMediaElement; 30 import org.w3c.dom.smil.SMILRegionElement; 31 import org.w3c.dom.smil.SMILRegionMediaElement; 32 import org.w3c.dom.smil.Time; 33 import org.w3c.dom.smil.TimeList; 34 35 import android.content.Context; 36 import android.drm.mobile1.DrmException; 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 getMediaModel(Context context, SMILMediaElement sme, LayoutModel layouts, PduBody pb)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 findPart(PduBody pb, String src)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 getRegionMediaModel(Context context, String tag, String src, SMILRegionMediaElement srme, LayoutModel layouts, PduPart part)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 getGenericMediaModel(Context context, String tag, String src, SMILMediaElement sme, PduPart part, RegionModel regionModel)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