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(), dateModifiedInSec,
    156                 type, filePath);
    157     }
    158 
    159     public static class LocalVideoRequest extends ImageCacheRequest {
    160         private String mLocalFilePath;
    161 
    162         LocalVideoRequest(GalleryApp application, Path path, long timeModified,
    163                 int type, String localFilePath) {
    164             super(application, path, timeModified, type,
    165                     MediaItem.getTargetSize(type));
    166             mLocalFilePath = localFilePath;
    167         }
    168 
    169         @Override
    170         public Bitmap onDecodeOriginal(JobContext jc, int type) {
    171             Bitmap bitmap = BitmapUtils.createVideoThumbnail(mLocalFilePath);
    172             if (bitmap == null || jc.isCancelled()) return null;
    173             return bitmap;
    174         }
    175     }
    176 
    177     @Override
    178     public Job<BitmapRegionDecoder> requestLargeImage() {
    179         throw new UnsupportedOperationException("Cannot regquest a large image"
    180                 + " to a local video!");
    181     }
    182 
    183     @Override
    184     public int getSupportedOperations() {
    185         return SUPPORT_DELETE | SUPPORT_SHARE | SUPPORT_PLAY | SUPPORT_INFO | SUPPORT_TRIM | SUPPORT_MUTE;
    186     }
    187 
    188     @Override
    189     public void delete() {
    190         GalleryUtils.assertNotInRenderThread();
    191         Uri baseUri = Video.Media.EXTERNAL_CONTENT_URI;
    192         mApplication.getContentResolver().delete(baseUri, "_id=?",
    193                 new String[]{String.valueOf(id)});
    194     }
    195 
    196     @Override
    197     public void rotate(int degrees) {
    198         // TODO
    199     }
    200 
    201     @Override
    202     public Uri getContentUri() {
    203         Uri baseUri = Video.Media.EXTERNAL_CONTENT_URI;
    204         return baseUri.buildUpon().appendPath(String.valueOf(id)).build();
    205     }
    206 
    207     @Override
    208     public Uri getPlayUri() {
    209         return getContentUri();
    210     }
    211 
    212     @Override
    213     public int getMediaType() {
    214         return MEDIA_TYPE_VIDEO;
    215     }
    216 
    217     @Override
    218     public MediaDetails getDetails() {
    219         MediaDetails details = super.getDetails();
    220         int s = durationInSec;
    221         if (s > 0) {
    222             details.addDetail(MediaDetails.INDEX_DURATION, GalleryUtils.formatDuration(
    223                     mApplication.getAndroidContext(), durationInSec));
    224         }
    225         return details;
    226     }
    227 
    228     @Override
    229     public int getWidth() {
    230         return width;
    231     }
    232 
    233     @Override
    234     public int getHeight() {
    235         return height;
    236     }
    237 
    238     @Override
    239     public String getFilePath() {
    240         return filePath;
    241     }
    242 }
    243