LocalVideo.java revision 7b83fb8e3a8978b33a6b9bfc56d85fe2c1a9cf06
1/* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.gallery3d.data; 18 19import com.android.gallery3d.R; 20import com.android.gallery3d.app.GalleryApp; 21import com.android.gallery3d.common.BitmapUtils; 22import com.android.gallery3d.util.UpdateHelper; 23import com.android.gallery3d.util.GalleryUtils; 24import com.android.gallery3d.util.ThreadPool.Job; 25import com.android.gallery3d.util.ThreadPool.JobContext; 26 27import android.content.ContentResolver; 28import android.database.Cursor; 29import android.graphics.Bitmap; 30import android.graphics.BitmapFactory; 31import android.graphics.BitmapRegionDecoder; 32import android.graphics.Canvas; 33import android.graphics.Paint; 34import android.net.Uri; 35import android.provider.MediaStore.Video; 36import android.provider.MediaStore.Video.VideoColumns; 37 38import java.io.File; 39 40// LocalVideo represents a video in the local storage. 41public class LocalVideo extends LocalMediaItem { 42 43 static final Path ITEM_PATH = Path.fromString("/local/video/item"); 44 45 // Must preserve order between these indices and the order of the terms in 46 // the following PROJECTION array. 47 private static final int INDEX_ID = 0; 48 private static final int INDEX_CAPTION = 1; 49 private static final int INDEX_MIME_TYPE = 2; 50 private static final int INDEX_LATITUDE = 3; 51 private static final int INDEX_LONGITUDE = 4; 52 private static final int INDEX_DATE_TAKEN = 5; 53 private static final int INDEX_DATE_ADDED = 6; 54 private static final int INDEX_DATE_MODIFIED = 7; 55 private static final int INDEX_DATA = 8; 56 private static final int INDEX_DURATION = 9; 57 private static final int INDEX_BUCKET_ID = 10; 58 private static final int INDEX_SIZE_ID = 11; 59 60 static final String[] PROJECTION = new String[] { 61 VideoColumns._ID, 62 VideoColumns.TITLE, 63 VideoColumns.MIME_TYPE, 64 VideoColumns.LATITUDE, 65 VideoColumns.LONGITUDE, 66 VideoColumns.DATE_TAKEN, 67 VideoColumns.DATE_ADDED, 68 VideoColumns.DATE_MODIFIED, 69 VideoColumns.DATA, 70 VideoColumns.DURATION, 71 VideoColumns.BUCKET_ID, 72 VideoColumns.SIZE 73 }; 74 75 private final GalleryApp mApplication; 76 77 public int durationInSec; 78 79 public LocalVideo(Path path, GalleryApp application, Cursor cursor) { 80 super(path, nextVersionNumber()); 81 mApplication = application; 82 loadFromCursor(cursor); 83 } 84 85 public LocalVideo(Path path, GalleryApp context, int id) { 86 super(path, nextVersionNumber()); 87 mApplication = context; 88 ContentResolver resolver = mApplication.getContentResolver(); 89 Uri uri = Video.Media.EXTERNAL_CONTENT_URI; 90 Cursor cursor = LocalAlbum.getItemCursor(resolver, uri, PROJECTION, id); 91 if (cursor == null) { 92 throw new RuntimeException("cannot get cursor for: " + path); 93 } 94 try { 95 if (cursor.moveToNext()) { 96 loadFromCursor(cursor); 97 } else { 98 throw new RuntimeException("cannot find data for: " + path); 99 } 100 } finally { 101 cursor.close(); 102 } 103 } 104 105 private void loadFromCursor(Cursor cursor) { 106 id = cursor.getInt(INDEX_ID); 107 caption = cursor.getString(INDEX_CAPTION); 108 mimeType = cursor.getString(INDEX_MIME_TYPE); 109 latitude = cursor.getDouble(INDEX_LATITUDE); 110 longitude = cursor.getDouble(INDEX_LONGITUDE); 111 dateTakenInMs = cursor.getLong(INDEX_DATE_TAKEN); 112 filePath = cursor.getString(INDEX_DATA); 113 durationInSec = cursor.getInt(INDEX_DURATION) / 1000; 114 bucketId = cursor.getInt(INDEX_BUCKET_ID); 115 fileSize = cursor.getLong(INDEX_SIZE_ID); 116 } 117 118 @Override 119 protected boolean updateFromCursor(Cursor cursor) { 120 UpdateHelper uh = new UpdateHelper(); 121 id = uh.update(id, cursor.getInt(INDEX_ID)); 122 caption = uh.update(caption, cursor.getString(INDEX_CAPTION)); 123 mimeType = uh.update(mimeType, cursor.getString(INDEX_MIME_TYPE)); 124 latitude = uh.update(latitude, cursor.getDouble(INDEX_LATITUDE)); 125 longitude = uh.update(longitude, cursor.getDouble(INDEX_LONGITUDE)); 126 dateTakenInMs = uh.update( 127 dateTakenInMs, cursor.getLong(INDEX_DATE_TAKEN)); 128 dateAddedInSec = uh.update( 129 dateAddedInSec, cursor.getLong(INDEX_DATE_ADDED)); 130 dateModifiedInSec = uh.update( 131 dateModifiedInSec, cursor.getLong(INDEX_DATE_MODIFIED)); 132 filePath = uh.update(filePath, cursor.getString(INDEX_DATA)); 133 durationInSec = uh.update( 134 durationInSec, cursor.getInt(INDEX_DURATION) / 1000); 135 bucketId = uh.update(bucketId, cursor.getInt(INDEX_BUCKET_ID)); 136 fileSize = uh.update(fileSize, cursor.getLong(INDEX_SIZE_ID)); 137 return uh.isUpdated(); 138 } 139 140 @Override 141 public Job<Bitmap> requestImage(int type) { 142 return new LocalVideoRequest(mApplication, getPath(), type, filePath); 143 } 144 145 public static class LocalVideoRequest extends ImageCacheRequest { 146 private String mLocalFilePath; 147 148 LocalVideoRequest(GalleryApp application, Path path, int type, 149 String localFilePath) { 150 super(application, path, type, LocalImage.getTargetSize(type)); 151 mLocalFilePath = localFilePath; 152 } 153 154 @Override 155 public Bitmap onDecodeOriginal(JobContext jc, int type) { 156 Bitmap bitmap = BitmapUtils.createVideoThumbnail(mLocalFilePath); 157 if (bitmap == null || jc.isCancelled()) return null; 158 return bitmap; 159 } 160 } 161 162 @Override 163 public Job<BitmapRegionDecoder> requestLargeImage() { 164 throw new UnsupportedOperationException("Cannot regquest a large image" 165 + " to a local video!"); 166 } 167 168 @Override 169 public int getSupportedOperations() { 170 return SUPPORT_DELETE | SUPPORT_SHARE | SUPPORT_PLAY | SUPPORT_INFO; 171 } 172 173 @Override 174 public void delete() { 175 GalleryUtils.assertNotInRenderThread(); 176 Uri baseUri = Video.Media.EXTERNAL_CONTENT_URI; 177 mApplication.getContentResolver().delete(baseUri, "_id=?", 178 new String[]{String.valueOf(id)}); 179 } 180 181 @Override 182 public void rotate(int degrees) { 183 // TODO 184 } 185 186 @Override 187 public Uri getContentUri() { 188 Uri baseUri = Video.Media.EXTERNAL_CONTENT_URI; 189 return baseUri.buildUpon().appendPath(String.valueOf(id)).build(); 190 } 191 192 @Override 193 public Uri getPlayUri() { 194 return getContentUri(); 195 } 196 197 @Override 198 public int getMediaType() { 199 return MEDIA_TYPE_VIDEO; 200 } 201 202 @Override 203 public MediaDetails getDetails() { 204 MediaDetails details = super.getDetails(); 205 int s = durationInSec; 206 if (s > 0) { 207 details.addDetail(MediaDetails.INDEX_DURATION, GalleryUtils.formatDuration( 208 mApplication.getAndroidContext(), durationInSec)); 209 } 210 return details; 211 } 212 213 @Override 214 public int getWidth() { 215 return 0; 216 } 217 218 @Override 219 public int getHeight() { 220 return 0; 221 } 222} 223