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