diff options
Diffstat (limited to 'src/com/android/gallery3d/data/LocalSource.java')
-rw-r--r-- | src/com/android/gallery3d/data/LocalSource.java | 272 |
1 files changed, 272 insertions, 0 deletions
diff --git a/src/com/android/gallery3d/data/LocalSource.java b/src/com/android/gallery3d/data/LocalSource.java new file mode 100644 index 000000000..58ac22490 --- /dev/null +++ b/src/com/android/gallery3d/data/LocalSource.java @@ -0,0 +1,272 @@ +/* + * Copyright (C) 2010 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.gallery3d.data; + +import com.android.gallery3d.app.Gallery; +import com.android.gallery3d.app.GalleryApp; +import com.android.gallery3d.data.MediaSet.ItemConsumer; + +import android.content.ContentProviderClient; +import android.content.ContentUris; +import android.content.UriMatcher; +import android.net.Uri; +import android.provider.MediaStore; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; + +class LocalSource extends MediaSource { + + public static final String KEY_BUCKET_ID = "bucketId"; + + private GalleryApp mApplication; + private PathMatcher mMatcher; + private static final int NO_MATCH = -1; + private final UriMatcher mUriMatcher = new UriMatcher(NO_MATCH); + public static final Comparator<PathId> sIdComparator = new IdComparator(); + + private static final int LOCAL_IMAGE_ALBUMSET = 0; + private static final int LOCAL_VIDEO_ALBUMSET = 1; + private static final int LOCAL_IMAGE_ALBUM = 2; + private static final int LOCAL_VIDEO_ALBUM = 3; + private static final int LOCAL_IMAGE_ITEM = 4; + private static final int LOCAL_VIDEO_ITEM = 5; + private static final int LOCAL_ALL_ALBUMSET = 6; + private static final int LOCAL_ALL_ALBUM = 7; + + private static final String TAG = "LocalSource"; + + private ContentProviderClient mClient; + + public LocalSource(GalleryApp context) { + super("local"); + mApplication = context; + mMatcher = new PathMatcher(); + mMatcher.add("/local/image", LOCAL_IMAGE_ALBUMSET); + mMatcher.add("/local/video", LOCAL_VIDEO_ALBUMSET); + mMatcher.add("/local/all", LOCAL_ALL_ALBUMSET); + + mMatcher.add("/local/image/*", LOCAL_IMAGE_ALBUM); + mMatcher.add("/local/video/*", LOCAL_VIDEO_ALBUM); + mMatcher.add("/local/all/*", LOCAL_ALL_ALBUM); + mMatcher.add("/local/image/item/*", LOCAL_IMAGE_ITEM); + mMatcher.add("/local/video/item/*", LOCAL_VIDEO_ITEM); + + mUriMatcher.addURI(MediaStore.AUTHORITY, + "external/images/media/#", LOCAL_IMAGE_ITEM); + mUriMatcher.addURI(MediaStore.AUTHORITY, + "external/video/media/#", LOCAL_VIDEO_ITEM); + mUriMatcher.addURI(MediaStore.AUTHORITY, + "external/images/media", LOCAL_IMAGE_ALBUM); + mUriMatcher.addURI(MediaStore.AUTHORITY, + "external/video/media", LOCAL_VIDEO_ALBUM); + } + + @Override + public MediaObject createMediaObject(Path path) { + GalleryApp app = mApplication; + switch (mMatcher.match(path)) { + case LOCAL_ALL_ALBUMSET: + case LOCAL_IMAGE_ALBUMSET: + case LOCAL_VIDEO_ALBUMSET: + return new LocalAlbumSet(path, mApplication); + case LOCAL_IMAGE_ALBUM: + return new LocalAlbum(path, app, mMatcher.getIntVar(0), true); + case LOCAL_VIDEO_ALBUM: + return new LocalAlbum(path, app, mMatcher.getIntVar(0), false); + case LOCAL_ALL_ALBUM: { + int bucketId = mMatcher.getIntVar(0); + DataManager dataManager = app.getDataManager(); + MediaSet imageSet = (MediaSet) dataManager.getMediaObject( + LocalAlbumSet.PATH_IMAGE.getChild(bucketId)); + MediaSet videoSet = (MediaSet) dataManager.getMediaObject( + LocalAlbumSet.PATH_VIDEO.getChild(bucketId)); + Comparator<MediaItem> comp = DataManager.sDateTakenComparator; + return new LocalMergeAlbum( + path, comp, new MediaSet[] {imageSet, videoSet}); + } + case LOCAL_IMAGE_ITEM: + return new LocalImage(path, mApplication, mMatcher.getIntVar(0)); + case LOCAL_VIDEO_ITEM: + return new LocalVideo(path, mApplication, mMatcher.getIntVar(0)); + default: + throw new RuntimeException("bad path: " + path); + } + } + + private static int getMediaType(String type, int defaultType) { + if (type == null) return defaultType; + try { + int value = Integer.parseInt(type); + if ((value & (MEDIA_TYPE_IMAGE + | MEDIA_TYPE_VIDEO)) != 0) return value; + } catch (NumberFormatException e) { + Log.w(TAG, "invalid type: " + type, e); + } + return defaultType; + } + + // The media type bit passed by the intent + private static final int MEDIA_TYPE_IMAGE = 1; + private static final int MEDIA_TYPE_VIDEO = 4; + + private Path getAlbumPath(Uri uri, int defaultType) { + int mediaType = getMediaType( + uri.getQueryParameter(Gallery.KEY_MEDIA_TYPES), + defaultType); + String bucketId = uri.getQueryParameter(KEY_BUCKET_ID); + int id = 0; + try { + id = Integer.parseInt(bucketId); + } catch (NumberFormatException e) { + Log.w(TAG, "invalid bucket id: " + bucketId, e); + return null; + } + switch (mediaType) { + case MEDIA_TYPE_IMAGE: + return Path.fromString("/local/image").getChild(id); + case MEDIA_TYPE_VIDEO: + return Path.fromString("/local/video").getChild(id); + default: + return Path.fromString("/merge/{/local/image,/local/video}") + .getChild(id); + } + } + + @Override + public Path findPathByUri(Uri uri) { + try { + switch (mUriMatcher.match(uri)) { + case LOCAL_IMAGE_ITEM: { + long id = ContentUris.parseId(uri); + return id >= 0 ? LocalImage.ITEM_PATH.getChild(id) : null; + } + case LOCAL_VIDEO_ITEM: { + long id = ContentUris.parseId(uri); + return id >= 0 ? LocalVideo.ITEM_PATH.getChild(id) : null; + } + case LOCAL_IMAGE_ALBUM: { + return getAlbumPath(uri, MEDIA_TYPE_IMAGE); + } + case LOCAL_VIDEO_ALBUM: { + return getAlbumPath(uri, MEDIA_TYPE_VIDEO); + } + } + } catch (NumberFormatException e) { + Log.w(TAG, "uri: " + uri.toString(), e); + } + return null; + } + + @Override + public Path getDefaultSetOf(Path item) { + MediaObject object = mApplication.getDataManager().getMediaObject(item); + if (object instanceof LocalImage) { + return Path.fromString("/local/image/").getChild( + String.valueOf(((LocalImage) object).getBucketId())); + } else if (object instanceof LocalVideo) { + return Path.fromString("/local/video/").getChild( + String.valueOf(((LocalVideo) object).getBucketId())); + } + return null; + } + + @Override + public void mapMediaItems(ArrayList<PathId> list, ItemConsumer consumer) { + ArrayList<PathId> imageList = new ArrayList<PathId>(); + ArrayList<PathId> videoList = new ArrayList<PathId>(); + int n = list.size(); + for (int i = 0; i < n; i++) { + PathId pid = list.get(i); + // We assume the form is: "/local/{image,video}/item/#" + // We don't use mMatcher for efficiency's reason. + Path parent = pid.path.getParent(); + if (parent == LocalImage.ITEM_PATH) { + imageList.add(pid); + } else if (parent == LocalVideo.ITEM_PATH) { + videoList.add(pid); + } + } + // TODO: use "files" table so we can merge the two cases. + processMapMediaItems(imageList, consumer, true); + processMapMediaItems(videoList, consumer, false); + } + + private void processMapMediaItems(ArrayList<PathId> list, + ItemConsumer consumer, boolean isImage) { + // Sort path by path id + Collections.sort(list, sIdComparator); + int n = list.size(); + for (int i = 0; i < n; ) { + PathId pid = list.get(i); + + // Find a range of items. + ArrayList<Integer> ids = new ArrayList<Integer>(); + int startId = Integer.parseInt(pid.path.getSuffix()); + ids.add(startId); + + int j; + for (j = i + 1; j < n; j++) { + PathId pid2 = list.get(j); + int curId = Integer.parseInt(pid2.path.getSuffix()); + if (curId - startId >= MediaSet.MEDIAITEM_BATCH_FETCH_COUNT) { + break; + } + ids.add(curId); + } + + MediaItem[] items = LocalAlbum.getMediaItemById( + mApplication, isImage, ids); + for(int k = i ; k < j; k++) { + PathId pid2 = list.get(k); + consumer.consume(pid2.id, items[k - i]); + } + + i = j; + } + } + + // This is a comparator which compares the suffix number in two Paths. + private static class IdComparator implements Comparator<PathId> { + public int compare(PathId p1, PathId p2) { + String s1 = p1.path.getSuffix(); + String s2 = p2.path.getSuffix(); + int len1 = s1.length(); + int len2 = s2.length(); + if (len1 < len2) { + return -1; + } else if (len1 > len2) { + return 1; + } else { + return s1.compareTo(s2); + } + } + } + + @Override + public void resume() { + mClient = mApplication.getContentResolver() + .acquireContentProviderClient(MediaStore.AUTHORITY); + } + + @Override + public void pause() { + mClient.release(); + mClient = null; + } +} |