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.ContentRestrictionException;
     21 import com.android.mms.LogTag;
     22 import com.android.mms.dom.events.EventImpl;
     23 import com.android.mms.dom.smil.SmilMediaElementImpl;
     24 import com.android.mms.drm.DrmWrapper;
     25 import com.google.android.mms.MmsException;
     26 import android.database.sqlite.SqliteWrapper;
     27 
     28 import org.w3c.dom.events.Event;
     29 import org.w3c.dom.smil.ElementTime;
     30 
     31 import android.content.ContentResolver;
     32 import android.content.Context;
     33 import android.database.Cursor;
     34 import android.net.Uri;
     35 import android.provider.MediaStore.Images;
     36 import android.text.TextUtils;
     37 import android.util.Log;
     38 import android.webkit.MimeTypeMap;
     39 
     40 import com.google.android.mms.ContentType;
     41 import java.io.IOException;
     42 
     43 public class VideoModel extends RegionMediaModel {
     44     private static final String TAG = MediaModel.TAG;
     45     private static final boolean DEBUG = true;
     46     private static final boolean LOCAL_LOGV = false;
     47 
     48     public VideoModel(Context context, Uri uri, RegionModel region)
     49             throws MmsException {
     50         this(context, null, null, uri, region);
     51         initModelFromUri(uri);
     52         checkContentRestriction();
     53     }
     54 
     55     public VideoModel(Context context, String contentType, String src,
     56             Uri uri, RegionModel region) throws MmsException {
     57         super(context, SmilHelper.ELEMENT_TAG_VIDEO, contentType, src, uri, region);
     58     }
     59 
     60     public VideoModel(Context context, String contentType, String src,
     61             DrmWrapper wrapper, RegionModel regionModel) throws IOException {
     62         super(context, SmilHelper.ELEMENT_TAG_VIDEO, contentType, src, wrapper, regionModel);
     63     }
     64 
     65     private void initModelFromUri(Uri uri) throws MmsException {
     66         String scheme = uri.getScheme();
     67         if (scheme.equals("content")) {
     68             initFromContentUri(uri);
     69         } else if (uri.getScheme().equals("file")) {
     70             initFromFile(uri);
     71         }
     72         initMediaDuration();
     73     }
     74 
     75     private void initFromFile(Uri uri) {
     76         mSrc = uri.getPath();
     77         MimeTypeMap mimeTypeMap = MimeTypeMap.getSingleton();
     78         String extension = MimeTypeMap.getFileExtensionFromUrl(mSrc);
     79         if (TextUtils.isEmpty(extension)) {
     80             // getMimeTypeFromExtension() doesn't handle spaces in filenames nor can it handle
     81             // urlEncoded strings. Let's try one last time at finding the extension.
     82             int dotPos = mSrc.lastIndexOf('.');
     83             if (0 <= dotPos) {
     84                 extension = mSrc.substring(dotPos + 1);
     85             }
     86         }
     87         mContentType = mimeTypeMap.getMimeTypeFromExtension(extension);
     88         // It's ok if mContentType is null. Eventually we'll show a toast telling the
     89         // user the video couldn't be attached.
     90 
     91         if (Log.isLoggable(LogTag.APP, Log.VERBOSE)) {
     92             Log.v(TAG, "New VideoModel initFromFile created:"
     93                     + " mSrc=" + mSrc
     94                     + " mContentType=" + mContentType
     95                     + " mUri=" + uri);
     96         }
     97     }
     98 
     99     private void initFromContentUri(Uri uri) throws MmsException {
    100         ContentResolver cr = mContext.getContentResolver();
    101         Cursor c = SqliteWrapper.query(mContext, cr, uri, null, null, null, null);
    102 
    103         if (c != null) {
    104             try {
    105                 if (c.moveToFirst()) {
    106                     String path;
    107                     try {
    108                         // Local videos will have a data column
    109                         path = c.getString(c.getColumnIndexOrThrow(Images.Media.DATA));
    110                     } catch (IllegalArgumentException e) {
    111                         // For non-local videos, the path is the uri
    112                         path = uri.toString();
    113                     }
    114                     mSrc = path.substring(path.lastIndexOf('/') + 1);
    115                     mContentType = c.getString(c.getColumnIndexOrThrow(
    116                             Images.Media.MIME_TYPE));
    117                     if (TextUtils.isEmpty(mContentType)) {
    118                         throw new MmsException("Type of media is unknown.");
    119                     }
    120 
    121                     if (mContentType.equals(ContentType.VIDEO_MP4) && !(TextUtils.isEmpty(mSrc))) {
    122                         int index = mSrc.lastIndexOf(".");
    123                         if (index != -1) {
    124                             try {
    125                                 String extension = mSrc.substring(index + 1);
    126                                 if (!(TextUtils.isEmpty(extension)) &&
    127                                         (extension.equalsIgnoreCase("3gp") ||
    128                                         extension.equalsIgnoreCase("3gpp") ||
    129                                         extension.equalsIgnoreCase("3g2"))) {
    130                                     mContentType = ContentType.VIDEO_3GPP;
    131                                 }
    132                             } catch(IndexOutOfBoundsException ex) {
    133                                 if (LOCAL_LOGV) {
    134                                     Log.v(TAG, "Media extension is unknown.");
    135                                 }
    136                             }
    137                         }
    138                     }
    139 
    140                     if (Log.isLoggable(LogTag.APP, Log.VERBOSE)) {
    141                         Log.v(TAG, "New VideoModel initFromContentUri created:"
    142                                 + " mSrc=" + mSrc
    143                                 + " mContentType=" + mContentType
    144                                 + " mUri=" + uri);
    145                     }
    146                 } else {
    147                     throw new MmsException("Nothing found: " + uri);
    148                 }
    149             } finally {
    150                 c.close();
    151             }
    152         } else {
    153             throw new MmsException("Bad URI: " + uri);
    154         }
    155     }
    156 
    157     // EventListener Interface
    158     public void handleEvent(Event evt) {
    159         String evtType = evt.getType();
    160         if (LOCAL_LOGV || Log.isLoggable(LogTag.APP, Log.VERBOSE)) {
    161             Log.v(TAG, "[VideoModel] handleEvent " + evt.getType() + " on " + this);
    162         }
    163 
    164         MediaAction action = MediaAction.NO_ACTIVE_ACTION;
    165         if (evtType.equals(SmilMediaElementImpl.SMIL_MEDIA_START_EVENT)) {
    166             action = MediaAction.START;
    167 
    168             // if the Music player app is playing audio, we should pause that so it won't
    169             // interfere with us playing video here.
    170             pauseMusicPlayer();
    171 
    172             mVisible = true;
    173         } else if (evtType.equals(SmilMediaElementImpl.SMIL_MEDIA_END_EVENT)) {
    174             action = MediaAction.STOP;
    175             if (mFill != ElementTime.FILL_FREEZE) {
    176                 mVisible = false;
    177             }
    178         } else if (evtType.equals(SmilMediaElementImpl.SMIL_MEDIA_PAUSE_EVENT)) {
    179             action = MediaAction.PAUSE;
    180             mVisible = true;
    181         } else if (evtType.equals(SmilMediaElementImpl.SMIL_MEDIA_SEEK_EVENT)) {
    182             action = MediaAction.SEEK;
    183             mSeekTo = ((EventImpl) evt).getSeekTo();
    184             mVisible = true;
    185         }
    186 
    187         appendAction(action);
    188         notifyModelChanged(false);
    189     }
    190 
    191     protected void checkContentRestriction() throws ContentRestrictionException {
    192         ContentRestriction cr = ContentRestrictionFactory.getContentRestriction();
    193         cr.checkVideoContentType(mContentType);
    194     }
    195 
    196     @Override
    197     protected boolean isPlayable() {
    198         return true;
    199     }
    200 }
    201