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