PlayerAndroid/app/src/main/java/code/name/monkey/retromusic/repository/SongRepository.kt

214 lines
7.1 KiB
Kotlin
Raw Normal View History

2019-03-03 09:20:15 +00:00
/*
* Copyright (c) 2019 Hemanth Savarala.
*
* Licensed under the GNU General Public License v3
*
* This 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 (at your option) any later version.
*
* This software 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.
*/
package code.name.monkey.retromusic.repository
2018-11-28 07:48:19 +00:00
import android.content.Context
import android.database.Cursor
import android.os.Environment
2018-11-28 07:48:19 +00:00
import android.provider.MediaStore
2020-09-18 20:35:58 +00:00
import android.provider.MediaStore.Audio.AudioColumns
import android.provider.MediaStore.Audio.Media
2020-06-06 18:57:28 +00:00
import code.name.monkey.retromusic.Constants.IS_MUSIC
2019-10-09 12:31:31 +00:00
import code.name.monkey.retromusic.Constants.baseProjection
import code.name.monkey.retromusic.extensions.getInt
import code.name.monkey.retromusic.extensions.getLong
import code.name.monkey.retromusic.extensions.getString
import code.name.monkey.retromusic.extensions.getStringOrNull
2018-11-28 07:48:19 +00:00
import code.name.monkey.retromusic.model.Song
import code.name.monkey.retromusic.providers.BlacklistStore
2020-06-06 18:57:28 +00:00
import code.name.monkey.retromusic.util.PreferenceUtil
import java.util.*
2018-11-28 07:48:19 +00:00
/**
* Created by hemanths on 10/08/17.
*/
interface SongRepository {
2018-11-28 07:48:19 +00:00
fun songs(): List<Song>
2020-01-29 17:25:43 +00:00
fun songs(cursor: Cursor?): List<Song>
fun songs(query: String): List<Song>
fun songsByFilePath(filePath: String): List<Song>
fun song(cursor: Cursor?): Song
fun song(songId: Long): Song
}
class RealSongRepository(private val context: Context) : SongRepository {
override fun songs(): List<Song> {
return songs(makeSongCursor(null, null))
2018-11-30 01:06:16 +00:00
}
2018-11-28 07:48:19 +00:00
override fun songs(cursor: Cursor?): List<Song> {
val songs = arrayListOf<Song>()
if (cursor != null && cursor.moveToFirst()) {
do {
songs.add(getSongFromCursorImpl(cursor))
} while (cursor.moveToNext())
}
cursor?.close()
return songs
}
override fun song(cursor: Cursor?): Song {
val song: Song = if (cursor != null && cursor.moveToFirst()) {
getSongFromCursorImpl(cursor)
} else {
Song.emptySong
}
cursor?.close()
return song
}
override fun songs(query: String): List<Song> {
return songs(makeSongCursor(AudioColumns.TITLE + " LIKE ?", arrayOf("%$query%")))
}
override fun song(songId: Long): Song {
return song(makeSongCursor(AudioColumns._ID + "=?", arrayOf(songId.toString())))
}
override fun songsByFilePath(filePath: String): List<Song> {
return songs(
makeSongCursor(
AudioColumns.DATA + "=?",
arrayOf(filePath)
)
)
}
private fun getSongFromCursorImpl(
2020-01-29 17:25:43 +00:00
cursor: Cursor
): Song {
val id = cursor.getLong(AudioColumns._ID)
val title = cursor.getString(AudioColumns.TITLE)
val trackNumber = cursor.getInt(AudioColumns.TRACK)
val year = cursor.getInt(AudioColumns.YEAR)
val duration = cursor.getLong(AudioColumns.DURATION)
val data = cursor.getString(AudioColumns.DATA)
val dateModified = cursor.getLong(AudioColumns.DATE_MODIFIED)
val albumId = cursor.getLong(AudioColumns.ALBUM_ID)
val albumName = cursor.getStringOrNull(AudioColumns.ALBUM)
val artistId = cursor.getLong(AudioColumns.ARTIST_ID)
val artistName = cursor.getStringOrNull(AudioColumns.ARTIST)
val composer = cursor.getStringOrNull(AudioColumns.COMPOSER)
val albumArtist = cursor.getStringOrNull("album_artist")
2020-01-29 17:25:43 +00:00
return Song(
2020-08-11 18:29:44 +00:00
id,
title,
trackNumber,
year,
duration,
data,
dateModified,
albumId,
albumName ?: "",
artistId,
artistName ?: "",
composer ?: "",
albumArtist ?: ""
2020-01-29 17:25:43 +00:00
)
2018-11-30 01:06:16 +00:00
}
2018-11-28 07:48:19 +00:00
2018-11-30 01:06:16 +00:00
@JvmOverloads
fun makeSongCursor(
2020-09-12 19:39:46 +00:00
2020-01-29 17:25:43 +00:00
selection: String?,
selectionValues: Array<String>?,
2020-06-06 18:57:28 +00:00
sortOrder: String = PreferenceUtil.songSortOrder
): Cursor? {
2018-11-30 01:06:16 +00:00
var selectionFinal = selection
var selectionValuesFinal = selectionValues
selectionFinal = if (selection != null && selection.trim { it <= ' ' } != "") {
2020-06-06 18:57:28 +00:00
"$IS_MUSIC AND $selectionFinal"
2018-11-30 01:06:16 +00:00
} else {
2020-06-06 18:57:28 +00:00
IS_MUSIC
2018-11-30 01:06:16 +00:00
}
2018-11-28 07:48:19 +00:00
// Whitelist
if (PreferenceUtil.isWhiteList) {
selectionFinal =
selectionFinal + " AND " + AudioColumns.DATA + " LIKE ?"
selectionValuesFinal = addSelectionValues(
selectionValuesFinal, arrayListOf(
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC).canonicalPath
)
)
} else {
// Blacklist
val paths = BlacklistStore.getInstance(context).paths
if (paths.isNotEmpty()) {
selectionFinal = generateBlacklistSelection(selectionFinal, paths.size)
selectionValuesFinal = addSelectionValues(selectionValuesFinal, paths)
}
2018-11-30 01:06:16 +00:00
}
2020-08-11 18:29:44 +00:00
selectionFinal =
selectionFinal + " AND " + Media.DURATION + ">= " + (PreferenceUtil.filterLength * 1000)
2020-09-18 20:35:58 +00:00
val uri = if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.Q) {
Media.getContentUri(MediaStore.VOLUME_EXTERNAL)
} else {
Media.EXTERNAL_CONTENT_URI
}
return try {
context.contentResolver.query(
uri,
baseProjection,
selectionFinal,
selectionValuesFinal,
sortOrder
)
} catch (ex: SecurityException) {
return null
}
2018-11-30 01:06:16 +00:00
}
private fun generateBlacklistSelection(
2020-01-29 17:25:43 +00:00
selection: String?,
pathCount: Int
): String {
2018-11-30 01:06:16 +00:00
val newSelection = StringBuilder(
2020-01-29 17:25:43 +00:00
if (selection != null && selection.trim { it <= ' ' } != "") "$selection AND " else "")
2018-11-30 01:06:16 +00:00
newSelection.append(AudioColumns.DATA + " NOT LIKE ?")
for (i in 0 until pathCount - 1) {
newSelection.append(" AND " + AudioColumns.DATA + " NOT LIKE ?")
2018-11-28 07:48:19 +00:00
}
2018-11-30 01:06:16 +00:00
return newSelection.toString()
}
2018-11-28 07:48:19 +00:00
private fun addSelectionValues(
2020-01-29 17:25:43 +00:00
selectionValues: Array<String>?,
paths: ArrayList<String>
): Array<String> {
2018-11-30 01:06:16 +00:00
var selectionValuesFinal = selectionValues
if (selectionValuesFinal == null) {
selectionValuesFinal = emptyArray()
}
val newSelectionValues = Array(selectionValuesFinal.size + paths.size) {
"n = $it"
}
System.arraycopy(selectionValuesFinal, 0, newSelectionValues, 0, selectionValuesFinal.size)
for (i in selectionValuesFinal.size until newSelectionValues.size) {
newSelectionValues[i] = paths[i - selectionValuesFinal.size] + "%"
2018-11-28 07:48:19 +00:00
}
2018-11-30 01:06:16 +00:00
return newSelectionValues
}
2018-11-28 07:48:19 +00:00
}