/*
* Copyright 2008-2013, ETH Zürich, Samuel Welten, Michael Kuhn, Tobias Langner,
* Sandro Affentranger, Lukas Bossard, Michael Grob, Rahul Jain,
* Dominic Langenegger, Sonia Mayor Alonso, Roger Odermatt, Tobias Schlueter,
* Yannick Stucki, Sebastian Wendland, Samuel Zehnder, Samuel Zihlmann,
* Samuel Zweifel
*
* This file is part of Jukefox.
*
* Jukefox is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or any later version. Jukefox is
* distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* Jukefox. If not, see <http://www.gnu.org/licenses/>.
*/
package ch.ethz.dcg.jukefox.manager.model.albumart;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.LinkedHashMap;
import java.util.Map;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import ch.ethz.dcg.jukefox.commons.AndroidConstants;
import ch.ethz.dcg.jukefox.commons.DataUnavailableException;
import ch.ethz.dcg.jukefox.commons.utils.AndroidUtils;
import ch.ethz.dcg.jukefox.commons.utils.Log;
import ch.ethz.dcg.jukefox.data.db.IDbDataPortal;
import ch.ethz.dcg.jukefox.model.collection.BaseAlbum;
import ch.ethz.dcg.jukefox.model.collection.ListAlbum;
import ch.ethz.dcg.jukefox.model.commons.NoAlbumArtException;
public class AlbumArtProvider {
private IDbDataPortal dbWrapper;
private LinkedHashMap<Integer, String> lowResPathCache;
private LinkedHashMap<Integer, byte[]> lowResByteCache;
private LinkedHashMap<Integer, Bitmap> lowResBitmapCache;
private LinkedHashMap<Integer, String> highResPathCache;
private LinkedHashMap<Integer, byte[]> highResByteCache;
private LinkedHashMap<Integer, Bitmap> highResBitmapCache;
public static final int MAX_LOW_RES_PATH_ITEMS = 2;
public static final int MAX_LOW_RES_BYTE_ARRAY_ITEMS = 2;
public static final int MAX_LOW_RES_BITMAP_ITEMS = 2;
public static final int MAX_HIGH_RES_PATH_ITEMS = 2;
public static final int MAX_HIGH_RES_BYTE_ARRAY_ITEMS = 2;
public static final int MAX_LOW_HIGH_BITMAP_ITEMS = 2;
private static final String TAG = AlbumArtProvider.class.getCanonicalName();
public AlbumArtProvider(IDbDataPortal dbWrapper) {
this.dbWrapper = dbWrapper;
initializeLowResCaches();
initializeHighResCaches();
}
private void initializeLowResCaches() {
lowResPathCache = new LinkedHashMap<Integer, String>(16, 0.75f, true) {
private static final long serialVersionUID = 1L;
@Override
public boolean removeEldestEntry(Map.Entry<Integer, String> eldest) {
if (this.size() > MAX_LOW_RES_PATH_ITEMS) {
return true;
} else {
return false;
}
}
};
lowResByteCache = new LinkedHashMap<Integer, byte[]>(16, 0.75f, true) {
private static final long serialVersionUID = 1L;
@Override
public boolean removeEldestEntry(Map.Entry<Integer, byte[]> eldest) {
if (this.size() > MAX_LOW_RES_BYTE_ARRAY_ITEMS) {
return true;
} else {
return false;
}
}
};
lowResBitmapCache = new LinkedHashMap<Integer, Bitmap>(16, 0.75f, true) {
private static final long serialVersionUID = 1L;
@Override
public boolean removeEldestEntry(Map.Entry<Integer, Bitmap> eldest) {
if (this.size() > MAX_LOW_RES_BITMAP_ITEMS) {
return true;
} else {
return false;
}
}
};
}
private void initializeHighResCaches() {
highResPathCache = new LinkedHashMap<Integer, String>(16, 0.75f, true) {
private static final long serialVersionUID = 1L;
@Override
public boolean removeEldestEntry(Map.Entry<Integer, String> eldest) {
if (this.size() > MAX_LOW_RES_PATH_ITEMS) {
return true;
} else {
return false;
}
}
};
highResByteCache = new LinkedHashMap<Integer, byte[]>(16, 0.75f, true) {
private static final long serialVersionUID = 1L;
@Override
public boolean removeEldestEntry(Map.Entry<Integer, byte[]> eldest) {
if (this.size() > MAX_LOW_RES_BYTE_ARRAY_ITEMS) {
return true;
} else {
return false;
}
}
};
highResBitmapCache = new LinkedHashMap<Integer, Bitmap>(16, 0.75f, true) {
private static final long serialVersionUID = 1L;
@Override
public boolean removeEldestEntry(Map.Entry<Integer, Bitmap> eldest) {
if (this.size() > MAX_LOW_RES_BITMAP_ITEMS) {
return true;
} else {
return false;
}
}
};
}
public Bitmap getAlbumArt(BaseAlbum album, boolean forceLowResolution) throws NoAlbumArtException {
if (forceLowResolution) {
return getLowResAlbumArt(album);
} else {
return getHighResAlbumArtIfPossible(album);
}
}
private Bitmap getHighResAlbumArtIfPossible(BaseAlbum album) throws NoAlbumArtException {
Bitmap albumArt = getHighResAlbumArt(album);
if (albumArt == null) {
albumArt = getLowResAlbumArt(album);
}
return albumArt;
}
private Bitmap getHighResAlbumArt(BaseAlbum album) throws NoAlbumArtException {
int albumId = album.getId();
if (highResBitmapCache.containsKey(albumId)) {
return highResBitmapCache.get(albumId);
} else if (highResByteCache.containsKey(albumId)) {
return AndroidUtils.getBitmapFromByteArray(highResByteCache.get(albumId),
AndroidConstants.COVER_SIZE_HIGH_RES);
} else if (highResPathCache.containsKey(albumId)) {
return decodeAlbumArtPath(albumId, highResPathCache.get(albumId), AndroidConstants.COVER_SIZE_HIGH_RES);
} else {
String path;
try {
path = dbWrapper.getAlbumArtPath(album, false);
if (path == null) {
throw new NoAlbumArtException();
}
} catch (DataUnavailableException e) {
throw new NoAlbumArtException();
}
try {
highResPathCache.put(albumId, path);
} catch (Exception e) {
// TODO: wtf
}
return decodeAlbumArtPath(albumId, path, AndroidConstants.COVER_SIZE_HIGH_RES);
}
}
private Bitmap getLowResAlbumArt(BaseAlbum album) throws NoAlbumArtException {
int albumId = album.getId();
if (lowResBitmapCache.containsKey(albumId)) {
return lowResBitmapCache.get(albumId);
} else if (lowResByteCache.containsKey(albumId)) {
return AndroidUtils.getBitmapFromByteArray(lowResByteCache.get(albumId),
AndroidConstants.COVER_SIZE_LOW_RES);
} else if (lowResPathCache.containsKey(albumId)) {
return decodeAlbumArtPath(albumId, lowResPathCache.get(albumId), AndroidConstants.COVER_SIZE_LOW_RES);
} else {
String path;
try {
path = dbWrapper.getAlbumArtPath(album, true);
if (path == null) {
throw new NoAlbumArtException();
}
} catch (DataUnavailableException e) {
throw new NoAlbumArtException();
}
lowResPathCache.put(albumId, path);
return decodeAlbumArtPath(albumId, path, AndroidConstants.COVER_SIZE_LOW_RES);
}
}
private Bitmap decodeAlbumArtPath(int albumId, String path, int maxRes) throws NoAlbumArtException {
InputStream inputStream;
Bitmap bitmap = null;
try {
if (path == null || !AndroidUtils.fileExists(path)) {
throw new NoAlbumArtException();
}
inputStream = new FileInputStream(path);
bitmap = AndroidUtils.getBitmapFromInputStream(inputStream, maxRes);
} catch (Throwable e) {
Log.w(TAG, e);
throw new NoAlbumArtException();
}
// byte[] byteArray = null;
//
// try {
//
// byteArray = new byte[inputStream.available()];
// inputStream.read(byteArray);
//
// if (lowRes) {
// lowResByteCache.put(albumId, byteArray);
// } else {
// highResByteCache.put(albumId, byteArray);
// }
//
// } catch (Exception e) {
// Log.w(TAG, e);
// } finally {
// try {
// inputStream.close();
// } catch (IOException e) {
// Log.w("Bitmap", e.toString());
// }
// }
if (bitmap == null) {
throw new NoAlbumArtException();
} else {
try {
if (maxRes == AndroidConstants.COVER_SIZE_LOW_RES) {
lowResBitmapCache.put(albumId, bitmap);
} else if (maxRes == AndroidConstants.COVER_SIZE_HIGH_RES) {
highResBitmapCache.put(albumId, bitmap);
}
} catch (Exception e) {
Log.w(TAG, e);
}
}
// Log.v(TAG, "Returning bitmap with width: " + bitmap.getWidth() +
// " and height: " + bitmap.getHeight() + " from path: " + path);
return bitmap;
}
public BitmapDrawable getListAlbumArt(ListAlbum album) throws NoAlbumArtException {
Bitmap bitmap;
try {
bitmap = getVeryLowResAlbumArt(album);
} catch (NullPointerException e) {
Log.w(TAG, e);
throw new NoAlbumArtException();
}
BitmapDrawable drawable = new BitmapDrawable(bitmap);
return drawable;
}
private Bitmap getVeryLowResAlbumArt(BaseAlbum album) throws NoAlbumArtException {
int albumId = album.getId();
if (lowResByteCache.containsKey(albumId)) {
return AndroidUtils.getBitmapFromByteArray(lowResByteCache.get(albumId),
AndroidConstants.COVER_SIZE_LOW_RES / 2);
} else if (lowResPathCache.containsKey(albumId)) {
return decodeAlbumArtPath(albumId, lowResPathCache.get(albumId), AndroidConstants.COVER_SIZE_LOW_RES / 2);
} else {
String path;
try {
path = dbWrapper.getAlbumArtPath(album, true);
if (path == null) {
throw new NoAlbumArtException();
}
} catch (DataUnavailableException e) {
throw new NoAlbumArtException();
}
lowResPathCache.put(albumId, path);
return decodeAlbumArtPath(albumId, path, AndroidConstants.COVER_SIZE_LOW_RES / 2);
}
}
}