OSDN Git Service

android-2.1_r1 snapshot
[android-x86/packages-apps-Gallery2.git] / src / com / cooliris / media / LocalDataSource.java
diff --git a/src/com/cooliris/media/LocalDataSource.java b/src/com/cooliris/media/LocalDataSource.java
new file mode 100644 (file)
index 0000000..2c92295
--- /dev/null
@@ -0,0 +1,301 @@
+package com.cooliris.media;
+
+import java.io.File;
+import java.net.URI;
+import java.util.ArrayList;
+
+import android.content.ContentResolver;
+import android.content.ContentUris;
+import android.content.ContentValues;
+import android.content.Context;
+import android.database.ContentObserver;
+import android.database.Cursor;
+import android.media.ExifInterface;
+import android.net.Uri;
+import android.os.Environment;
+import android.os.Handler;
+import android.provider.MediaStore.Images;
+import android.provider.MediaStore.Video;
+import android.util.Log;
+
+import com.cooliris.cache.CacheService;
+
+public final class LocalDataSource implements DataSource {
+    private static final String TAG = "LocalDataSource";
+
+    public static final DiskCache sThumbnailCache = new DiskCache("local-image-thumbs");
+    public static final DiskCache sThumbnailCacheVideo = new DiskCache("local-video-thumbs");
+
+    public static final String CAMERA_STRING = "Camera";
+    public static final String DOWNLOAD_STRING = "download";
+    public static final String CAMERA_BUCKET_NAME = Environment.getExternalStorageDirectory().toString() + "/DCIM/" + CAMERA_STRING;
+    public static final String DOWNLOAD_BUCKET_NAME = Environment.getExternalStorageDirectory().toString() + "/" + DOWNLOAD_STRING;
+    public static final int CAMERA_BUCKET_ID = getBucketId(CAMERA_BUCKET_NAME);
+    public static final int DOWNLOAD_BUCKET_ID = getBucketId(DOWNLOAD_BUCKET_NAME);
+
+    public static boolean sObserverActive = false;
+    private boolean mDisableImages;
+    private boolean mDisableVideos;
+
+    /**
+     * Matches code in MediaProvider.computeBucketValues. Should be a common
+     * function.
+     */
+    public static int getBucketId(String path) {
+        return (path.toLowerCase().hashCode());
+    }
+
+    private Context mContext;
+    private ContentObserver mObserver;
+
+    public LocalDataSource(Context context) {
+        mContext = context;
+    }
+
+    public void setMimeFilter(boolean disableImages, boolean disableVideos) {
+        mDisableImages = disableImages;
+        mDisableVideos = disableVideos;
+    }
+
+    public void loadMediaSets(final MediaFeed feed) {
+        if (mContext == null) {
+            return;
+        }
+        stopListeners();
+        CacheService.loadMediaSets(feed, this, !mDisableImages, !mDisableVideos);
+        Handler handler = ((Gallery) mContext).getHandler();
+        ContentObserver observer = new ContentObserver(handler) {
+            public void onChange(boolean selfChange) {
+                final boolean isPaused = ((Gallery) mContext).isPaused();
+                if (isPaused) {
+                    MediaSet mediaSet = feed.getCurrentSet();
+                    if (mediaSet != null) {
+                        CacheService.markDirtyImmediate(mediaSet.mId);
+                        refreshUI(feed, mediaSet.mId);
+                    }
+                }
+                CacheService.senseDirty(mContext, new CacheService.Observer() {
+                    public void onChange(long[] ids) {
+                        if (!isPaused)
+                            return;
+                        if (ids != null) {
+                            int numLongs = ids.length;
+                            for (int i = 0; i < numLongs; ++i) {
+                                refreshUI(feed, ids[i]);
+                            }
+                        }
+                    }
+                });
+            }
+        };
+
+        // Start listening.
+        Uri uriImages = Images.Media.EXTERNAL_CONTENT_URI;
+        Uri uriVideos = Video.Media.EXTERNAL_CONTENT_URI;
+        ContentResolver cr = mContext.getContentResolver();
+        mObserver = observer;
+        cr.registerContentObserver(uriImages, true, observer);
+        cr.registerContentObserver(uriVideos, true, observer);
+        sObserverActive = true;
+    }
+
+    public void shutdown() {
+        stopListeners();
+    }
+
+    private void stopListeners() {
+        ContentResolver cr = mContext.getContentResolver();
+        if (mObserver != null) {
+            cr.unregisterContentObserver(mObserver);
+            cr.unregisterContentObserver(mObserver);
+        }
+        sObserverActive = false;
+    }
+
+    protected void refreshUI(MediaFeed feed, long setIdToUse) {
+        if (setIdToUse == Shared.INVALID) {
+            return;
+        }
+        if (feed.getMediaSet(setIdToUse) == null) {
+            MediaSet mediaSet = feed.addMediaSet(setIdToUse, this);
+            if (setIdToUse == CAMERA_BUCKET_ID) {
+                mediaSet.mName = CAMERA_STRING;
+            } else if (setIdToUse == DOWNLOAD_BUCKET_ID) {
+                mediaSet.mName = DOWNLOAD_STRING;
+            }
+            mediaSet.generateTitle(true);
+        } else {
+            MediaSet mediaSet = feed.replaceMediaSet(setIdToUse, this);
+            Log.i(TAG, "Replacing mediaset " + mediaSet.mName + " id " + setIdToUse + " current Id " + mediaSet.mId);
+            if (setIdToUse == CAMERA_BUCKET_ID) {
+                mediaSet.mName = CAMERA_STRING;
+            } else if (setIdToUse == DOWNLOAD_BUCKET_ID) {
+                mediaSet.mName = DOWNLOAD_STRING;
+            }
+            mediaSet.generateTitle(true);
+        }
+    }
+
+    public void loadItemsForSet(final MediaFeed feed, final MediaSet parentSet, int rangeStart, int rangeEnd) {
+        // Quick load from the cache.
+        if (mContext == null || parentSet == null) {
+            return;
+        }
+        loadMediaItemsIntoMediaFeed(feed, parentSet, rangeStart, rangeEnd);
+    }
+
+    private void loadMediaItemsIntoMediaFeed(final MediaFeed mediaFeed, final MediaSet set, int rangeStart, int rangeEnd) {
+        if (rangeEnd - rangeStart < 0) {
+            return;
+        }
+        CacheService.loadMediaItemsIntoMediaFeed(mediaFeed, set, rangeStart, rangeEnd, !mDisableImages, !mDisableVideos);
+        if (set.mId == CAMERA_BUCKET_ID) {
+            mediaFeed.moveSetToFront(set);
+        }
+    }
+
+    public boolean performOperation(final int operation, final ArrayList<MediaBucket> mediaBuckets, final Object data) {
+        int numBuckets = mediaBuckets.size();
+        ContentResolver cr = mContext.getContentResolver();
+        switch (operation) {
+        case MediaFeed.OPERATION_DELETE:
+            for (int i = 0; i < numBuckets; ++i) {
+                MediaBucket bucket = mediaBuckets.get(i);
+                MediaSet set = bucket.mediaSet;
+                ArrayList<MediaItem> items = bucket.mediaItems;
+                if (set != null && items == null) {
+                    // Remove the entire bucket.
+                    final Uri uriImages = Images.Media.EXTERNAL_CONTENT_URI;
+                    final Uri uriVideos = Video.Media.EXTERNAL_CONTENT_URI;
+                    final String whereImages = Images.ImageColumns.BUCKET_ID + "=" + Long.toString(set.mId);
+                    final String whereVideos = Video.VideoColumns.BUCKET_ID + "=" + Long.toString(set.mId);
+                    cr.delete(uriImages, whereImages, null);
+                    cr.delete(uriVideos, whereVideos, null);
+                    CacheService.markDirty(mContext);
+                }
+                if (set != null && items != null) {
+                    // We need to remove these items from the set.
+                    int numItems = items.size();
+                    try {
+                        for (int j = 0; j < numItems; ++j) {
+                            MediaItem item = items.get(j);
+                            cr.delete(Uri.parse(item.mContentUri), null, null);
+                        }
+                    } catch (Exception e) {
+                        // If the database operation failed for any reason.
+                        ;
+                    }
+                    set.updateNumExpectedItems();
+                    set.generateTitle(true);
+                    CacheService.markDirty(mContext, set.mId);
+                }
+            }
+            break;
+        case MediaFeed.OPERATION_ROTATE:
+            for (int i = 0; i < numBuckets; ++i) {
+                MediaBucket bucket = mediaBuckets.get(i);
+                ArrayList<MediaItem> items = bucket.mediaItems;
+                if (items == null) {
+                    continue;
+                }
+                float angleToRotate = ((Float) data).floatValue();
+                if (angleToRotate == 0) {
+                    return true;
+                }
+                int numItems = items.size();
+                for (int j = 0; j < numItems; ++j) {
+                    rotateItem(items.get(j), angleToRotate);
+                }
+            }
+            break;
+        }
+        return true;
+    }
+
+    private void rotateItem(final MediaItem item, float angleToRotate) {
+        ContentResolver cr = mContext.getContentResolver();
+        try {
+            int currentOrientation = (int) item.mRotation;
+            angleToRotate += currentOrientation;
+            float rotation = Shared.normalizePositive(angleToRotate);
+            String rotationString = Integer.toString((int) rotation);
+
+            // Update the database entry.
+            ContentValues values = new ContentValues();
+            values.put(Images.ImageColumns.ORIENTATION, rotationString);
+            try {
+                cr.update(Uri.parse(item.mContentUri), values, null, null);
+            } catch (Exception e) {
+                // If the database operation fails for any reason.
+                ;
+            }
+
+            // Update the file EXIF information.
+            Uri uri = Uri.parse(item.mContentUri);
+            String uriScheme = uri.getScheme();
+            if (uriScheme.equals("file")) {
+                ExifInterface exif = new ExifInterface(uri.getPath());
+                exif.setAttribute(ExifInterface.TAG_ORIENTATION, Integer.toString(Shared.degreesToExifOrientation(rotation)));
+                exif.saveAttributes();
+            }
+
+            // Invalidate the cache entry.
+            CacheService.markDirty(mContext, item.mParentMediaSet.mId);
+
+            // Update the object representation of the item.
+            item.mRotation = rotation;
+        } catch (Exception e) {
+            // System.out.println("Apparently not a JPEG");
+        }
+    }
+
+    public DiskCache getThumbnailCache() {
+        return sThumbnailCache;
+    }
+
+    public static MediaItem createMediaItemFromUri(Context context, Uri target) {
+        MediaItem item = null;
+        long id = ContentUris.parseId(target);
+        ContentResolver cr = context.getContentResolver();
+        String whereClause = Images.ImageColumns._ID + "=" + Long.toString(id);
+        try {
+            Cursor cursor = cr.query(Images.Media.EXTERNAL_CONTENT_URI, CacheService.PROJECTION_IMAGES, whereClause, null, null);
+            if (cursor != null) {
+                if (cursor.moveToFirst()) {
+                    item = new MediaItem();
+                    CacheService.populateMediaItemFromCursor(item, cr, cursor, Images.Media.EXTERNAL_CONTENT_URI.toString() + "/");
+                }
+                cursor.close();
+                cursor = null;
+            }
+        } catch (Exception e) {
+            // If the database operation failed for any reason.
+            ;
+        }
+        return item;
+    }
+
+    public static MediaItem createMediaItemFromFileUri(Context context, String fileUri) {
+        MediaItem item = null;
+        String filepath = new File(URI.create(fileUri)).toString();
+        ContentResolver cr = context.getContentResolver();
+        long bucketId = SingleDataSource.parseBucketIdFromFileUri(fileUri);
+        String whereClause = Images.ImageColumns.BUCKET_ID + "=" + bucketId + " AND " + Images.ImageColumns.DATA + "='" + filepath
+                + "'";
+        try {
+            Cursor cursor = cr.query(Images.Media.EXTERNAL_CONTENT_URI, CacheService.PROJECTION_IMAGES, whereClause, null, null);
+            if (cursor != null) {
+                if (cursor.moveToFirst()) {
+                    item = new MediaItem();
+                    CacheService.populateMediaItemFromCursor(item, cr, cursor, Images.Media.EXTERNAL_CONTENT_URI.toString() + "/");
+                }
+                cursor.close();
+                cursor = null;
+            }
+        } catch (Exception e) {
+            // If the database operation failed for any reason.
+            ;
+        }
+        return item;
+    }
+}