1 /* 2 * Copyright (C) 2013 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.camera.data; 18 19 import java.util.ArrayList; 20 21 import android.content.Context; 22 import android.net.Uri; 23 24 import com.android.camera.util.PhotoSphereHelper; 25 import com.android.camera.util.PhotoSphereHelper.PanoramaMetadata; 26 27 /** 28 * This class breaks out the off-thread panorama support. 29 */ 30 public class PanoramaMetadataLoader { 31 /** 32 * Classes implementing this interface can get information about loaded 33 * photo sphere metadata. 34 */ 35 public static interface PanoramaMetadataCallback { 36 /** 37 * Called with the loaded metadata or <code>null</code>. 38 */ 39 public void onPanoramaMetadataLoaded(PanoramaMetadata metadata); 40 } 41 42 private PanoramaMetadata mPanoramaMetadata; 43 private ArrayList<PanoramaMetadataCallback> mCallbacksWaiting; 44 private Uri mMediaUri; 45 46 /** 47 * Instantiated the meta data loader for the image resource with the given 48 * URI. 49 */ 50 public PanoramaMetadataLoader(Uri uri) { 51 mMediaUri = uri; 52 } 53 54 /** 55 * Asynchronously extract and return panorama metadata from the item with 56 * the given URI. 57 * <p> 58 * NOTE: This call is backed by a cache to speed up successive calls, which 59 * will return immediately. Use {@link #clearCachedValues()} is called. 60 */ 61 public synchronized void getPanoramaMetadata(final Context context, 62 PanoramaMetadataCallback callback) { 63 if (mPanoramaMetadata != null) { 64 // Return the cached data right away, no need to fetch it again. 65 callback.onPanoramaMetadataLoaded(mPanoramaMetadata); 66 } else { 67 if (mCallbacksWaiting == null) { 68 mCallbacksWaiting = new ArrayList<PanoramaMetadataCallback>(); 69 70 // TODO: Don't create a new thread each time, use a pool or 71 // single instance. 72 (new Thread() { 73 @Override 74 public void run() { 75 onLoadingDone(PhotoSphereHelper.getPanoramaMetadata(context, 76 mMediaUri)); 77 } 78 }).start(); 79 } 80 mCallbacksWaiting.add(callback); 81 } 82 } 83 84 /** 85 * Clear cached value and stop all running loading threads. 86 */ 87 public synchronized void clearCachedValues() { 88 if (mPanoramaMetadata != null) { 89 mPanoramaMetadata = null; 90 } 91 92 // TODO: Cancel running loading thread if active. 93 } 94 95 private synchronized void onLoadingDone(PanoramaMetadata metadata) { 96 mPanoramaMetadata = metadata; 97 if (mPanoramaMetadata == null) { 98 // Error getting panorama data from file. Treat as not panorama. 99 mPanoramaMetadata = PhotoSphereHelper.NOT_PANORAMA; 100 } 101 for (PanoramaMetadataCallback cb : mCallbacksWaiting) { 102 cb.onPanoramaMetadataLoaded(mPanoramaMetadata); 103 } 104 mCallbacksWaiting = null; 105 } 106 } 107