blob: a71e455d34901069837d336ddede7e07738a53e9 [file] [log] [blame]
/*
* Copyright (C) 2008 Esmertec AG.
* Copyright (C) 2008 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.mms.model;
import org.w3c.dom.events.Event;
import org.w3c.dom.smil.ElementTime;
import android.content.ContentResolver;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SqliteWrapper;
import android.net.Uri;
import android.provider.MediaStore.Images;
import android.text.TextUtils;
import android.util.Log;
import android.webkit.MimeTypeMap;
import com.android.mms.ContentRestrictionException;
import com.android.mms.LogTag;
import com.android.mms.MmsApp;
import com.android.mms.dom.events.EventImpl;
import com.android.mms.dom.smil.SmilMediaElementImpl;
import com.android.mms.util.ItemLoadedCallback;
import com.android.mms.util.ItemLoadedFuture;
import com.android.mms.util.ThumbnailManager;
import com.google.android.mms.ContentType;
import com.google.android.mms.MmsException;
public class VideoModel extends RegionMediaModel {
private static final String TAG = MediaModel.TAG;
private static final boolean DEBUG = true;
private static final boolean LOCAL_LOGV = false;
private ItemLoadedFuture mItemLoadedFuture;
public VideoModel(Context context, Uri uri, RegionModel region)
throws MmsException {
this(context, null, null, uri, region);
initModelFromUri(uri);
checkContentRestriction();
}
public VideoModel(Context context, String contentType, String src,
Uri uri, RegionModel region) throws MmsException {
super(context, SmilHelper.ELEMENT_TAG_VIDEO, contentType, src, uri, region);
}
private void initModelFromUri(Uri uri) throws MmsException {
String scheme = uri.getScheme();
if (scheme.equals("content")) {
initFromContentUri(uri);
} else if (uri.getScheme().equals("file")) {
initFromFile(uri);
}
initMediaDuration();
}
private void initFromFile(Uri uri) {
String path = uri.getPath();
mSrc = path.substring(path.lastIndexOf('/') + 1);
MimeTypeMap mimeTypeMap = MimeTypeMap.getSingleton();
String extension = MimeTypeMap.getFileExtensionFromUrl(mSrc);
if (TextUtils.isEmpty(extension)) {
// getMimeTypeFromExtension() doesn't handle spaces in filenames nor can it handle
// urlEncoded strings. Let's try one last time at finding the extension.
int dotPos = mSrc.lastIndexOf('.');
if (0 <= dotPos) {
extension = mSrc.substring(dotPos + 1);
}
}
mContentType = mimeTypeMap.getMimeTypeFromExtension(extension);
// It's ok if mContentType is null. Eventually we'll show a toast telling the
// user the video couldn't be attached.
if (Log.isLoggable(LogTag.APP, Log.VERBOSE)) {
Log.v(TAG, "New VideoModel initFromFile created:"
+ " mSrc=" + mSrc
+ " mContentType=" + mContentType
+ " mUri=" + uri);
}
}
private void initFromContentUri(Uri uri) throws MmsException {
ContentResolver cr = mContext.getContentResolver();
Cursor c = SqliteWrapper.query(mContext, cr, uri, null, null, null, null);
if (c != null) {
try {
if (c.moveToFirst()) {
String path;
try {
// Local videos will have a data column
path = c.getString(c.getColumnIndexOrThrow(Images.Media.DATA));
} catch (IllegalArgumentException e) {
// For non-local videos, the path is the uri
path = uri.toString();
}
mSrc = path.substring(path.lastIndexOf('/') + 1);
mContentType = c.getString(c.getColumnIndexOrThrow(
Images.Media.MIME_TYPE));
if (TextUtils.isEmpty(mContentType)) {
throw new MmsException("Type of media is unknown.");
}
if (mContentType.equals(ContentType.VIDEO_MP4) && !(TextUtils.isEmpty(mSrc))) {
int index = mSrc.lastIndexOf(".");
if (index != -1) {
try {
String extension = mSrc.substring(index + 1);
if (!(TextUtils.isEmpty(extension)) &&
(extension.equalsIgnoreCase("3gp") ||
extension.equalsIgnoreCase("3gpp") ||
extension.equalsIgnoreCase("3g2"))) {
mContentType = ContentType.VIDEO_3GPP;
}
} catch(IndexOutOfBoundsException ex) {
if (LOCAL_LOGV) {
Log.v(TAG, "Media extension is unknown.");
}
}
}
}
if (Log.isLoggable(LogTag.APP, Log.VERBOSE)) {
Log.v(TAG, "New VideoModel initFromContentUri created:"
+ " mSrc=" + mSrc
+ " mContentType=" + mContentType
+ " mUri=" + uri);
}
} else {
throw new MmsException("Nothing found: " + uri);
}
} finally {
c.close();
}
} else {
throw new MmsException("Bad URI: " + uri);
}
}
// EventListener Interface
public void handleEvent(Event evt) {
String evtType = evt.getType();
if (LOCAL_LOGV || Log.isLoggable(LogTag.APP, Log.VERBOSE)) {
Log.v(TAG, "[VideoModel] handleEvent " + evt.getType() + " on " + this);
}
MediaAction action = MediaAction.NO_ACTIVE_ACTION;
if (evtType.equals(SmilMediaElementImpl.SMIL_MEDIA_START_EVENT)) {
action = MediaAction.START;
// if the Music player app is playing audio, we should pause that so it won't
// interfere with us playing video here.
pauseMusicPlayer();
mVisible = true;
} else if (evtType.equals(SmilMediaElementImpl.SMIL_MEDIA_END_EVENT)) {
action = MediaAction.STOP;
if (mFill != ElementTime.FILL_FREEZE) {
mVisible = false;
}
} else if (evtType.equals(SmilMediaElementImpl.SMIL_MEDIA_PAUSE_EVENT)) {
action = MediaAction.PAUSE;
mVisible = true;
} else if (evtType.equals(SmilMediaElementImpl.SMIL_MEDIA_SEEK_EVENT)) {
action = MediaAction.SEEK;
mSeekTo = ((EventImpl) evt).getSeekTo();
mVisible = true;
}
appendAction(action);
notifyModelChanged(false);
}
protected void checkContentRestriction() throws ContentRestrictionException {
ContentRestriction cr = ContentRestrictionFactory.getContentRestriction();
cr.checkVideoContentType(mContentType);
}
@Override
protected boolean isPlayable() {
return true;
}
public ItemLoadedFuture loadThumbnailBitmap(ItemLoadedCallback callback) {
ThumbnailManager thumbnailManager = MmsApp.getApplication().getThumbnailManager();
mItemLoadedFuture = thumbnailManager.getVideoThumbnail(getUri(), callback);
return mItemLoadedFuture;
}
public void cancelThumbnailLoading() {
if (mItemLoadedFuture != null && !mItemLoadedFuture.isDone()) {
if (Log.isLoggable(LogTag.APP, Log.DEBUG)) {
Log.v(TAG, "cancelThumbnailLoading for: " + this);
}
mItemLoadedFuture.cancel(getUri());
mItemLoadedFuture = null;
}
}
}