Home | History | Annotate | Download | only in data
      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 
     17 package com.android.gallery3d.data;
     18 
     19 import android.content.ContentResolver;
     20 import android.database.Cursor;
     21 import android.graphics.Bitmap;
     22 import android.graphics.BitmapRegionDecoder;
     23 import android.net.Uri;
     24 import android.provider.MediaStore.Video;
     25 import android.provider.MediaStore.Video.VideoColumns;
     26 
     27 import com.android.gallery3d.app.GalleryApp;
     28 import com.android.gallery3d.common.BitmapUtils;
     29 import com.android.gallery3d.util.GalleryUtils;
     30 import com.android.gallery3d.util.ThreadPool.Job;
     31 import com.android.gallery3d.util.ThreadPool.JobContext;
     32 import com.android.gallery3d.util.UpdateHelper;
     33 
     34 // LocalVideo represents a video in the local storage.
     35 public class LocalVideo extends LocalMediaItem {
     36     private static final String TAG = "LocalVideo";
     37     static final Path ITEM_PATH = Path.fromString("/local/video/item");
     38 
     39     // Must preserve order between these indices and the order of the terms in
     40     // the following PROJECTION array.
     41     private static final int INDEX_ID = 0;
     42     private static final int INDEX_CAPTION = 1;
     43     private static final int INDEX_MIME_TYPE = 2;
     44     private static final int INDEX_LATITUDE = 3;
     45     private static final int INDEX_LONGITUDE = 4;
     46     private static final int INDEX_DATE_TAKEN = 5;
     47     private static final int INDEX_DATE_ADDED = 6;
     48     private static final int INDEX_DATE_MODIFIED = 7;
     49     private static final int INDEX_DATA = 8;
     50     private static final int INDEX_DURATION = 9;
     51     private static final int INDEX_BUCKET_ID = 10;
     52     private static final int INDEX_SIZE = 11;
     53     private static final int INDEX_RESOLUTION = 12;
     54 
     55     static final String[] PROJECTION = new String[] {
     56             VideoColumns._ID,
     57             VideoColumns.TITLE,
     58             VideoColumns.MIME_TYPE,
     59             VideoColumns.LATITUDE,
     60             VideoColumns.LONGITUDE,
     61             VideoColumns.DATE_TAKEN,
     62             VideoColumns.DATE_ADDED,
     63             VideoColumns.DATE_MODIFIED,
     64             VideoColumns.DATA,
     65             VideoColumns.DURATION,
     66             VideoColumns.BUCKET_ID,
     67             VideoColumns.SIZE,
     68             VideoColumns.RESOLUTION,
     69     };
     70 
     71     private final GalleryApp mApplication;
     72 
     73     public int durationInSec;
     74 
     75     public LocalVideo(Path path, GalleryApp application, Cursor cursor) {
     76         super(path, nextVersionNumber());
     77         mApplication = application;
     78         loadFromCursor(cursor);
     79     }
     80 
     81     public LocalVideo(Path path, GalleryApp context, int id) {
     82         super(path, nextVersionNumber());
     83         mApplication = context;
     84         ContentResolver resolver = mApplication.getContentResolver();
     85         Uri uri = Video.Media.EXTERNAL_CONTENT_URI;
     86         Cursor cursor = LocalAlbum.getItemCursor(resolver, uri, PROJECTION, id);
     87         if (cursor == null) {
     88             throw new RuntimeException("cannot get cursor for: " + path);
     89         }
     90         try {
     91             if (cursor.moveToNext()) {
     92                 loadFromCursor(cursor);
     93             } else {
     94                 throw new RuntimeException("cannot find data for: " + path);
     95             }
     96         } finally {
     97             cursor.close();
     98         }
     99     }
    100 
    101     private void loadFromCursor(Cursor cursor) {
    102         id = cursor.getInt(INDEX_ID);
    103         caption = cursor.getString(INDEX_CAPTION);
    104         mimeType = cursor.getString(INDEX_MIME_TYPE);
    105         latitude = cursor.getDouble(INDEX_LATITUDE);
    106         longitude = cursor.getDouble(INDEX_LONGITUDE);
    107         dateTakenInMs = cursor.getLong(INDEX_DATE_TAKEN);
    108         dateAddedInSec = cursor.getLong(INDEX_DATE_ADDED);
    109         dateModifiedInSec = cursor.getLong(INDEX_DATE_MODIFIED);
    110         filePath = cursor.getString(INDEX_DATA);
    111         durationInSec = cursor.getInt(INDEX_DURATION) / 1000;
    112         bucketId = cursor.getInt(INDEX_BUCKET_ID);
    113         fileSize = cursor.getLong(INDEX_SIZE);
    114         parseResolution(cursor.getString(INDEX_RESOLUTION));
    115     }
    116 
    117     private void parseResolution(String resolution) {
    118         if (resolution == null) return;
    119         int m = resolution.indexOf('x');
    120         if (m == -1) return;
    121         try {
    122             int w = Integer.parseInt(resolution.substring(0, m));
    123             int h = Integer.parseInt(resolution.substring(m + 1));
    124             width = w;
    125             height = h;
    126         } catch (Throwable t) {
    127             Log.w(TAG, t);
    128         }
    129     }
    130 
    131     @Override
    132     protected boolean updateFromCursor(Cursor cursor) {
    133         UpdateHelper uh = new UpdateHelper();
    134         id = uh.update(id, cursor.getInt(INDEX_ID));
    135         caption = uh.update(caption, cursor.getString(INDEX_CAPTION));
    136         mimeType = uh.update(mimeType, cursor.getString(INDEX_MIME_TYPE));
    137         latitude = uh.update(latitude, cursor.getDouble(INDEX_LATITUDE));
    138         longitude = uh.update(longitude, cursor.getDouble(INDEX_LONGITUDE));
    139         dateTakenInMs = uh.update(
    140                 dateTakenInMs, cursor.getLong(INDEX_DATE_TAKEN));
    141         dateAddedInSec = uh.update(
    142                 dateAddedInSec, cursor.getLong(INDEX_DATE_ADDED));
    143         dateModifiedInSec = uh.update(
    144                 dateModifiedInSec, cursor.getLong(INDEX_DATE_MODIFIED));
    145         filePath = uh.update(filePath, cursor.getString(INDEX_DATA));
    146         durationInSec = uh.update(
    147                 durationInSec, cursor.getInt(INDEX_DURATION) / 1000);
    148         bucketId = uh.update(bucketId, cursor.getInt(INDEX_BUCKET_ID));
    149         fileSize = uh.update(fileSize, cursor.getLong(INDEX_SIZE));
    150         return uh.isUpdated();
    151     }
    152 
    153     @Override
    154     public Job<Bitmap> requestImage(int type) {
    155         return new LocalVideoRequest(mApplication, getPath(), type, filePath);
    156     }
    157 
    158     public static class LocalVideoRequest extends ImageCacheRequest {
    159         private String mLocalFilePath;
    160 
    161         LocalVideoRequest(GalleryApp application, Path path, int type,
    162                 String localFilePath) {
    163             super(application, path, type, MediaItem.getTargetSize(type));
    164             mLocalFilePath = localFilePath;
    165         }
    166 
    167         @Override
    168         public Bitmap onDecodeOriginal(JobContext jc, int type) {
    169             Bitmap bitmap = BitmapUtils.createVideoThumbnail(mLocalFilePath);
    170             if (bitmap == null || jc.isCancelled()) return null;
    171             return bitmap;
    172         }
    173     }
    174 
    175     @Override
    176     public Job<BitmapRegionDecoder> requestLargeImage() {
    177         throw new UnsupportedOperationException("Cannot regquest a large image"
    178                 + " to a local video!");
    179     }
    180 
    181     @Override
    182     public int getSupportedOperations() {
    183         return SUPPORT_DELETE | SUPPORT_SHARE | SUPPORT_PLAY | SUPPORT_INFO | SUPPORT_TRIM | SUPPORT_MUTE;
    184     }
    185 
    186     @Override
    187     public void delete() {
    188         GalleryUtils.assertNotInRenderThread();
    189         Uri baseUri = Video.Media.EXTERNAL_CONTENT_URI;
    190         mApplication.getContentResolver().delete(baseUri, "_id=?",
    191                 new String[]{String.valueOf(id)});
    192     }
    193 
    194     @Override
    195     public void rotate(int degrees) {
    196         // TODO
    197     }
    198 
    199     @Override
    200     public Uri getContentUri() {
    201         Uri baseUri = Video.Media.EXTERNAL_CONTENT_URI;
    202         return baseUri.buildUpon().appendPath(String.valueOf(id)).build();
    203     }
    204 
    205     @Override
    206     public Uri getPlayUri() {
    207         return getContentUri();
    208     }
    209 
    210     @Override
    211     public int getMediaType() {
    212         return MEDIA_TYPE_VIDEO;
    213     }
    214 
    215     @Override
    216     public MediaDetails getDetails() {
    217         MediaDetails details = super.getDetails();
    218         int s = durationInSec;
    219         if (s > 0) {
    220             details.addDetail(MediaDetails.INDEX_DURATION, GalleryUtils.formatDuration(
    221                     mApplication.getAndroidContext(), durationInSec));
    222         }
    223         return details;
    224     }
    225 
    226     @Override
    227     public int getWidth() {
    228         return width;
    229     }
    230 
    231     @Override
    232     public int getHeight() {
    233         return height;
    234     }
    235 
    236     @Override
    237     public String getFilePath() {
    238         return filePath;
    239     }
    240 }
    241