package com.simplecity.amp_library.utils;
import android.content.ContentUris;
import android.database.Cursor;
import android.net.Uri;
import android.provider.MediaStore;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.WorkerThread;
import android.util.Log;
import com.annimon.stream.Stream;
import com.simplecity.amp_library.ShuttleApplication;
import com.simplecity.amp_library.model.Album;
import com.simplecity.amp_library.model.Song;
import org.jaudiotagger.audio.AudioFile;
import org.jaudiotagger.audio.AudioFileIO;
import org.jaudiotagger.audio.exceptions.CannotReadException;
import org.jaudiotagger.audio.exceptions.InvalidAudioFrameException;
import org.jaudiotagger.audio.exceptions.ReadOnlyFileException;
import org.jaudiotagger.tag.Tag;
import org.jaudiotagger.tag.TagException;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.regex.Pattern;
public class ArtworkUtils {
private static final String TAG = "ArtworkUtils";
//This class is never instantiated
private ArtworkUtils() {
}
/**
* Searches the parent directory of the passed in path for [cover/album/artwork].[png/jpg/jpeg]
* using regex and returns a {@link InputStream} representing the artwork
*/
@WorkerThread
public static InputStream getFolderArtwork(@Nullable final String path) {
InputStream fileInputStream = null;
if (path != null) {
File[] files;
File file = new File(path);
File parent = file.getParentFile();
if (parent.exists() && parent.isDirectory()) {
final Pattern pattern = Pattern.compile("(folder|cover|album).*\\.(jpg|jpeg|png)", Pattern.CASE_INSENSITIVE);
files = parent.listFiles(file1 -> {
return pattern.matcher(file1.getName()).matches();
}
);
if (files.length > 0) {
try {
File artworkFile = Stream.of(files)
.filter(aFile -> aFile.exists() && aFile.length() > 1024)
.max((a, b) -> (int) (a.length() / 1024 - b.length() / 1024))
.get();
fileInputStream = getFileArtwork(artworkFile);
} catch (NoSuchElementException e) {
Log.e(TAG, "getFolderArtwork failed: " + e.toString());
}
}
}
}
return fileInputStream;
}
/**
* Returns a FileInputStream for the given file, or null if the file is invalid
*/
@WorkerThread
public static InputStream getFileArtwork(@Nullable File file) {
if (file == null || !file.exists() || file.length() < 10 * 1024) {
return null;
}
FileInputStream fileInputStream = null;
try {
fileInputStream = new FileInputStream(file);
} catch (FileNotFoundException | NoSuchElementException e) {
Log.e(TAG, "getFileArtwork failed: " + e.toString());
}
return fileInputStream;
}
/**
* Retrieves the Artwork for the given album id from the MediaStore as an {@link InputStream}
*/
@WorkerThread
public static InputStream getMediaStoreArtwork(long albumId) {
Uri contentUri = ContentUris.withAppendedId(MediaStore.Audio.Albums.EXTERNAL_CONTENT_URI, albumId);
FileInputStream fileInputStream = null;
Cursor cursor = ShuttleApplication.getInstance()
.getContentResolver()
.query(contentUri, new String[]{MediaStore.Audio.Albums.ALBUM_ART}, null, null, null);
if (cursor != null) {
try {
if (cursor.moveToFirst()) {
File file = new File(cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Albums.ALBUM_ART)));
if (file.exists()) {
try {
fileInputStream = new FileInputStream(file);
} catch (FileNotFoundException ignored) {
}
}
}
} catch (NullPointerException ignored) {
} finally {
cursor.close();
}
}
return fileInputStream;
}
/**
* Retrieves the Artwork for the given {@link Song} from the MediaStore as an {@link InputStream}
*/
@WorkerThread
public static InputStream getMediaStoreArtwork(@NonNull Song song) {
return getMediaStoreArtwork(song.albumId);
}
/**
* Retrieves the Artwork for the given {@link Album} from the MediaStore as an {@link InputStream}
*/
@WorkerThread
public static InputStream getMediaStoreArtwork(@NonNull Album album) {
return getMediaStoreArtwork(album.id);
}
/**
* Retrieves the Artwork from the id3 tags of the file at the given path.
*/
@WorkerThread
public static InputStream getTagArtwork(@Nullable String filePath) {
InputStream inputStream = null;
if (filePath != null) {
try {
AudioFile audioFIle = AudioFileIO.read(new File(filePath));
if (audioFIle != null) {
Tag tag = audioFIle.getTag();
if (tag != null) {
org.jaudiotagger.tag.datatype.Artwork artwork = tag.getFirstArtwork();
if (artwork != null) {
inputStream = new ByteArrayInputStream(artwork.getBinaryData());
}
}
}
} catch (CannotReadException | IOException | TagException | ReadOnlyFileException | InvalidAudioFrameException ignored) {
}
}
return inputStream;
}
/**
* Searches the parent directory of the passed in path for [cover/album/artwork].[png/jpg/jpeg]
* using regex and returns a {@link List<File>} representing the artwork
*/
@WorkerThread
public static List<File> getAllFolderArtwork(@Nullable final String path) {
List<File> fileArray = new ArrayList<>();
if (path != null) {
File[] files;
File parent = new File(path).getParentFile();
if (parent.exists() && parent.isDirectory()) {
final Pattern pattern = Pattern.compile("(folder|cover|album).*\\.(jpg|jpeg|png)", Pattern.CASE_INSENSITIVE);
files = parent.listFiles(file1 -> {
return pattern.matcher(file1.getName()).matches();
}
);
if (files.length != 0) {
for (File file : files) {
if (file.exists()) {
fileArray.add(file);
}
}
}
}
}
return fileArray;
}
}