App shortcut fixed

This commit is contained in:
h4h13 2018-12-25 20:28:47 +05:30
parent 1425bfe612
commit 0b6f043995
181 changed files with 1616 additions and 2052 deletions

View file

@ -85,8 +85,8 @@ class BlurTransformation : BitmapTransformation {
return StackBlur.blur(out, blurRadius)
}
override fun equals(o: Any?): Boolean {
return o is BlurTransformation
override fun equals(other: Any?): Boolean {
return other is BlurTransformation
}
override fun hashCode(): Int {
@ -138,7 +138,7 @@ class BlurTransformation : BitmapTransformation {
companion object {
val DEFAULT_BLUR_RADIUS = 5f
private val ID = "com.poupa.vinylmusicplayer.glide.BlurTransformation"
const val DEFAULT_BLUR_RADIUS = 5f
private const val ID = "code.name.monkey.retromusic.glide.BlurTransformation"
}
}

View file

@ -1,5 +1,7 @@
package code.name.monkey.retromusic.glide;
import androidx.annotation.NonNull;
import com.bumptech.glide.GenericTransitionOptions;
import com.bumptech.glide.Priority;
import com.bumptech.glide.RequestBuilder;
@ -8,11 +10,11 @@ import com.bumptech.glide.annotation.GlideOption;
import com.bumptech.glide.annotation.GlideType;
import com.bumptech.glide.load.Key;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions;
import com.bumptech.glide.request.RequestOptions;
import com.bumptech.glide.request.target.Target;
import com.bumptech.glide.signature.MediaStoreSignature;
import androidx.annotation.NonNull;
import code.name.monkey.retromusic.App;
import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.glide.artistimage.ArtistImage;
@ -34,6 +36,7 @@ public final class RetroGlideExtension {
public static void asBitmapPalette(RequestBuilder<BitmapPaletteWrapper> requestBuilder) {
}
@NonNull
@GlideOption
public static RequestOptions artistOptions(@NonNull RequestOptions requestOptions, Artist artist) {
return requestOptions
@ -46,11 +49,12 @@ public final class RetroGlideExtension {
}
@GlideOption
@NonNull
public static RequestOptions songOptions(@NonNull RequestOptions requestOptions, Song song) {
return requestOptions
.diskCacheStrategy(DiskCacheStrategy.NONE)
.error(R.drawable.default_album_art)
.placeholder(R.drawable.default_album_art)
//.placeholder(R.drawable.default_album_art)
.signature(createSignature(song));
}
@ -93,4 +97,5 @@ public final class RetroGlideExtension {
public static <TranscodeType> GenericTransitionOptions<TranscodeType> getDefaultTransition() {
return new GenericTransitionOptions<TranscodeType>().transition(android.R.anim.fade_in);
}
}

View file

@ -1,4 +0,0 @@
package code.name.monkey.retromusic.glide.artistimage
class ArtistImage(val artistName: String, val skipOkHttpCache: Boolean)

View file

@ -1,98 +0,0 @@
package code.name.monkey.retromusic.glide.artistimage
import android.content.Context
import android.text.TextUtils
import code.name.monkey.retromusic.rest.LastFMRestClient
import code.name.monkey.retromusic.rest.model.LastFmArtist
import code.name.monkey.retromusic.util.LastFMUtil
import code.name.monkey.retromusic.util.MusicUtil
import code.name.monkey.retromusic.util.RetroUtil
import com.bumptech.glide.Priority
import com.bumptech.glide.integration.okhttp3.OkHttpStreamFetcher
import com.bumptech.glide.load.DataSource
import com.bumptech.glide.load.data.DataFetcher
import com.bumptech.glide.load.model.GlideUrl
import okhttp3.OkHttpClient
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import java.io.InputStream
class ArtistImageFetcher(private val context: Context, private val lastFMRestClient: LastFMRestClient, private val okHttp: OkHttpClient, private val model: ArtistImage, width: Int, height: Int) : DataFetcher<InputStream> {
@Volatile
private var isCancelled: Boolean = false
private var call: Call<LastFmArtist>? = null
private var streamFetcher: OkHttpStreamFetcher? = null
override fun getDataClass(): Class<InputStream> {
return InputStream::class.java
}
override fun getDataSource(): DataSource {
return DataSource.REMOTE
}
override fun loadData(priority: Priority, callback: DataFetcher.DataCallback<in InputStream>) {
try {
if (!MusicUtil.isArtistNameUnknown(model.artistName) && RetroUtil.isAllowedToDownloadMetadata(context)) {
call = lastFMRestClient.apiService.getArtistInfo(model.artistName, null, if (model.skipOkHttpCache) "no-cache" else null)
call!!.enqueue(object : Callback<LastFmArtist> {
override fun onResponse(call: Call<LastFmArtist>, response: Response<LastFmArtist>) {
if (isCancelled) {
callback.onDataReady(null)
return
}
val lastFmArtist = response.body()
if (lastFmArtist == null || lastFmArtist.artist == null || lastFmArtist.artist.image == null) {
callback.onLoadFailed(Exception("No artist image url found"))
return
}
val url = LastFMUtil.getLargestArtistImageUrl(lastFmArtist.artist.image)
if (TextUtils.isEmpty(url) || TextUtils.isEmpty(url.trim { it <= ' ' })) {
callback.onLoadFailed(Exception("No artist image url found"))
return
}
streamFetcher = OkHttpStreamFetcher(okHttp, GlideUrl(url))
streamFetcher!!.loadData(priority, callback)
}
override fun onFailure(call: Call<LastFmArtist>, throwable: Throwable) {
callback.onLoadFailed(Exception(throwable))
}
})
}
} catch (e: Exception) {
callback.onLoadFailed(e)
}
}
override fun cleanup() {
if (streamFetcher != null) {
streamFetcher!!.cleanup()
}
}
override fun cancel() {
isCancelled = true
if (call != null) {
call!!.cancel()
}
if (streamFetcher != null) {
streamFetcher!!.cancel()
}
}
companion object {
val TAG: String = ArtistImageFetcher::class.java.simpleName
}
}

View file

@ -1,17 +1,109 @@
package code.name.monkey.retromusic.glide.artistimage
import android.content.Context
import android.text.TextUtils
import code.name.monkey.retromusic.rest.LastFMRestClient
import code.name.monkey.retromusic.rest.model.LastFmArtist
import code.name.monkey.retromusic.util.LastFMUtil
import code.name.monkey.retromusic.util.MusicUtil
import code.name.monkey.retromusic.util.RetroUtil
import com.bumptech.glide.Priority
import com.bumptech.glide.integration.okhttp3.OkHttpStreamFetcher
import com.bumptech.glide.load.DataSource
import com.bumptech.glide.load.Options
import com.bumptech.glide.load.data.DataFetcher
import com.bumptech.glide.load.model.GlideUrl
import com.bumptech.glide.load.model.ModelLoader
import com.bumptech.glide.load.model.ModelLoaderFactory
import com.bumptech.glide.load.model.MultiModelLoaderFactory
import com.bumptech.glide.signature.ObjectKey
import okhttp3.OkHttpClient
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
import java.io.InputStream
import java.util.concurrent.TimeUnit
class ArtistImage(val artistName: String, val skipOkHttpCache: Boolean)
class ArtistImageFetcher(private val context: Context, private val lastFMRestClient: LastFMRestClient, private val okHttp: OkHttpClient, private val model: ArtistImage, width: Int, height: Int) : DataFetcher<InputStream> {
@Volatile
private var isCancelled: Boolean = false
private var call: Call<LastFmArtist>? = null
private var streamFetcher: OkHttpStreamFetcher? = null
override fun getDataClass(): Class<InputStream> {
return InputStream::class.java
}
override fun getDataSource(): DataSource {
return DataSource.REMOTE
}
override fun loadData(priority: Priority, callback: DataFetcher.DataCallback<in InputStream>) {
try {
if (!MusicUtil.isArtistNameUnknown(model.artistName) && RetroUtil.isAllowedToDownloadMetadata(context)) {
call = lastFMRestClient.apiService.getArtistInfo(model.artistName, null, if (model.skipOkHttpCache) "no-cache" else null)
call!!.enqueue(object : Callback<LastFmArtist> {
override fun onResponse(call: Call<LastFmArtist>, response: Response<LastFmArtist>) {
if (isCancelled) {
callback.onDataReady(null)
return
}
val lastFmArtist = response.body()
if (lastFmArtist == null || lastFmArtist.artist == null || lastFmArtist.artist.image == null) {
callback.onLoadFailed(Exception("No artist image url found"))
return
}
val url = LastFMUtil.getLargestArtistImageUrl(lastFmArtist.artist.image)
if (TextUtils.isEmpty(url) || TextUtils.isEmpty(url.trim { it <= ' ' })) {
callback.onLoadFailed(Exception("No artist image url found"))
return
}
streamFetcher = OkHttpStreamFetcher(okHttp, GlideUrl(url))
streamFetcher!!.loadData(priority, callback)
}
override fun onFailure(call: Call<LastFmArtist>, throwable: Throwable) {
callback.onLoadFailed(Exception(throwable))
}
})
}
} catch (e: Exception) {
callback.onLoadFailed(e)
}
}
override fun cleanup() {
if (streamFetcher != null) {
streamFetcher!!.cleanup()
}
}
override fun cancel() {
isCancelled = true
if (call != null) {
call!!.cancel()
}
if (streamFetcher != null) {
streamFetcher!!.cancel()
}
}
companion object {
val TAG: String = ArtistImageFetcher::class.java.simpleName
}
}
class ArtistImageLoader(private val context: Context, private val lastFMClient: LastFMRestClient, private val okhttp: OkHttpClient) : ModelLoader<ArtistImage, InputStream> {
override fun buildLoadData(model: ArtistImage, width: Int, height: Int, options: Options): ModelLoader.LoadData<InputStream>? {

View file

@ -1,4 +0,0 @@
package code.name.monkey.retromusic.glide.audiocover
class AudioFileCover(val filePath: String)

View file

@ -1,92 +0,0 @@
package code.name.monkey.retromusic.glide.audiocover
import android.media.MediaMetadataRetriever
import com.bumptech.glide.Priority
import com.bumptech.glide.load.DataSource
import com.bumptech.glide.load.data.DataFetcher
import org.jaudiotagger.audio.mp3.MP3File
import java.io.*
/**
* @author Karim Abou Zeid (kabouzeid)
*/
class AudioFileCoverFetcher(private val model: AudioFileCover) : DataFetcher<InputStream> {
private var stream: FileInputStream? = null
override fun loadData(priority: Priority, callback: DataFetcher.DataCallback<in InputStream>) {
val retriever = MediaMetadataRetriever()
val data: InputStream?
try {
retriever.setDataSource(model.filePath)
val picture = retriever.embeddedPicture
if (picture != null) {
data = ByteArrayInputStream(picture)
} else {
data = fallback(model.filePath)
}
callback.onDataReady(data)
} catch (e: FileNotFoundException) {
callback.onLoadFailed(e)
} finally {
retriever.release()
}
}
override fun getDataClass(): Class<InputStream> {
return InputStream::class.java
}
override fun getDataSource(): DataSource {
return DataSource.LOCAL
}
@Throws(FileNotFoundException::class)
private fun fallback(path: String): InputStream? {
try {
val mp3File = MP3File(path)
if (mp3File.hasID3v2Tag()) {
val art = mp3File.tag.firstArtwork
if (art != null) {
val imageData = art.binaryData
return ByteArrayInputStream(imageData)
}
}
// If there are any exceptions, we ignore them and continue to the other fallback method
} catch (ignored: Exception) {
}
// Method 2: look for album art in external files
val parent = File(path).parentFile
for (fallback in FALLBACKS) {
val cover = File(parent, fallback)
if (cover.exists()) {
stream = FileInputStream(cover)
return stream
}
}
return null
}
override fun cleanup() {
// already cleaned up in loadData and ByteArrayInputStream will be GC'd
if (stream != null) {
try {
stream!!.close()
} catch (ignore: IOException) {
// can't do much about it
}
}
}
override fun cancel() {
// cannot cancel
}
companion object {
private val FALLBACKS = arrayOf("cover.jpg", "album.jpg", "folder.jpg", "cover.png", "album.png", "folder.png")
}
}

View file

@ -1,14 +1,102 @@
package code.name.monkey.retromusic.glide.audiocover
import android.media.MediaMetadataRetriever
import com.bumptech.glide.Priority
import com.bumptech.glide.load.DataSource
import com.bumptech.glide.load.Options
import com.bumptech.glide.load.data.DataFetcher
import com.bumptech.glide.load.model.ModelLoader
import com.bumptech.glide.load.model.ModelLoader.LoadData
import com.bumptech.glide.load.model.ModelLoaderFactory
import com.bumptech.glide.load.model.MultiModelLoaderFactory
import com.bumptech.glide.signature.ObjectKey
import java.io.InputStream
import org.jaudiotagger.audio.mp3.MP3File
import java.io.*
class AudioFileCover(val filePath: String)
class AudioFileCoverFetcher(private val model: AudioFileCover) : DataFetcher<InputStream> {
private var stream: FileInputStream? = null
override fun loadData(priority: Priority, callback: DataFetcher.DataCallback<in InputStream>) {
val retriever = MediaMetadataRetriever()
val data: InputStream?
try {
retriever.setDataSource(model.filePath)
val picture = retriever.embeddedPicture
if (picture != null) {
data = ByteArrayInputStream(picture)
} else {
data = fallback(model.filePath)
}
callback.onDataReady(data)
} catch (e: FileNotFoundException) {
callback.onLoadFailed(e)
} finally {
retriever.release()
}
}
override fun getDataClass(): Class<InputStream> {
return InputStream::class.java
}
override fun getDataSource(): DataSource {
return DataSource.LOCAL
}
@Throws(FileNotFoundException::class)
private fun fallback(path: String): InputStream? {
try {
val mp3File = MP3File(path)
if (mp3File.hasID3v2Tag()) {
val art = mp3File.tag.firstArtwork
if (art != null) {
val imageData = art.binaryData
return ByteArrayInputStream(imageData)
}
}
// If there are any exceptions, we ignore them and continue to the other fallback method
} catch (ignored: Exception) {
}
// Method 2: look for album art in external files
val parent = File(path).parentFile
for (fallback in FALLBACKS) {
val cover = File(parent, fallback)
if (cover.exists()) {
stream = FileInputStream(cover)
return stream
}
}
return null
}
override fun cleanup() {
// already cleaned up in loadData and ByteArrayInputStream will be GC'd
if (stream != null) {
try {
stream!!.close()
} catch (ignore: IOException) {
// can't do much about it
}
}
}
override fun cancel() {
// cannot cancel
}
companion object {
private val FALLBACKS = arrayOf("cover.jpg", "album.jpg", "folder.jpg", "cover.png", "album.png", "folder.png")
}
}
class AudioFileCoverLoader : ModelLoader<AudioFileCover, InputStream> {
override fun buildLoadData(model: AudioFileCover, width: Int, height: Int,
options: Options): LoadData<InputStream>? {

View file

@ -1,8 +1,33 @@
package code.name.monkey.retromusic.glide.palette
import android.graphics.Bitmap
import android.widget.ImageView
import androidx.palette.graphics.Palette
import code.name.monkey.retromusic.util.RetroColorUtil
import com.bumptech.glide.load.Options
import com.bumptech.glide.load.engine.Resource
import com.bumptech.glide.load.resource.transcode.ResourceTranscoder
import com.bumptech.glide.request.target.ImageViewTarget
import com.bumptech.glide.util.Util
class BitmapPaletteTranscoder : ResourceTranscoder<Bitmap, BitmapPaletteWrapper> {
override fun transcode(bitmapResource: Resource<Bitmap>, options: Options): Resource<BitmapPaletteWrapper>? {
val bitmap = bitmapResource.get()
val bitmapPaletteWrapper = BitmapPaletteWrapper(bitmap, RetroColorUtil.generatePalette(bitmap)!!)
return BitmapPaletteResource(bitmapPaletteWrapper)
}
}
class BitmapPaletteWrapper(val bitmap: Bitmap, val palette: Palette)
open class BitmapPaletteTarget(view: ImageView) : ImageViewTarget<BitmapPaletteWrapper>(view) {
override fun setResource(bitmapPaletteWrapper: BitmapPaletteWrapper?) {
if (bitmapPaletteWrapper != null) {
view.setImageBitmap(bitmapPaletteWrapper.bitmap)
}
}
}
class BitmapPaletteResource(private val bitmapPaletteWrapper: BitmapPaletteWrapper) : Resource<BitmapPaletteWrapper> {

View file

@ -1,14 +0,0 @@
package code.name.monkey.retromusic.glide.palette
import android.widget.ImageView
import com.bumptech.glide.request.target.ImageViewTarget
open class BitmapPaletteTarget(view: ImageView) : ImageViewTarget<BitmapPaletteWrapper>(view) {
override fun setResource(bitmapPaletteWrapper: BitmapPaletteWrapper?) {
if (bitmapPaletteWrapper != null) {
view.setImageBitmap(bitmapPaletteWrapper.bitmap)
}
}
}

View file

@ -1,16 +0,0 @@
package code.name.monkey.retromusic.glide.palette
import android.graphics.Bitmap
import code.name.monkey.retromusic.util.RetroColorUtil
import com.bumptech.glide.load.Options
import com.bumptech.glide.load.engine.Resource
import com.bumptech.glide.load.resource.transcode.ResourceTranscoder
class BitmapPaletteTranscoder : ResourceTranscoder<Bitmap, BitmapPaletteWrapper> {
override fun transcode(bitmapResource: Resource<Bitmap>, options: Options): Resource<BitmapPaletteWrapper>? {
val bitmap = bitmapResource.get()
val bitmapPaletteWrapper = BitmapPaletteWrapper(bitmap, RetroColorUtil.generatePalette(bitmap)!!)
return BitmapPaletteResource(bitmapPaletteWrapper)
}
}

View file

@ -1,6 +0,0 @@
package code.name.monkey.retromusic.glide.palette
import android.graphics.Bitmap
import androidx.palette.graphics.Palette
class BitmapPaletteWrapper(val bitmap: Bitmap, val palette: Palette)