Add AlbumDao, rename getArtist to getAlbumsOfArtist
This commit is contained in:
parent
3445576dc9
commit
3a3bd10fdb
|
@ -1,8 +1,10 @@
|
|||
package org.moire.ultrasonic.domain
|
||||
|
||||
import androidx.room.Entity
|
||||
import androidx.room.PrimaryKey
|
||||
import java.util.Date
|
||||
|
||||
@Entity(tableName = "albums")
|
||||
data class Album(
|
||||
@PrimaryKey override var id: String,
|
||||
override var parent: String? = null,
|
||||
|
|
|
@ -0,0 +1,474 @@
|
|||
{
|
||||
"formatVersion": 1,
|
||||
"database": {
|
||||
"version": 2,
|
||||
"identityHash": "b6ac795e7857eac4fed2dbbd01f80fb8",
|
||||
"entities": [
|
||||
{
|
||||
"tableName": "artists",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `name` TEXT, `index` TEXT, `coverArt` TEXT, `albumCount` INTEGER, `closeness` INTEGER NOT NULL, PRIMARY KEY(`id`))",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "id",
|
||||
"columnName": "id",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "name",
|
||||
"columnName": "name",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "index",
|
||||
"columnName": "index",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "coverArt",
|
||||
"columnName": "coverArt",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "albumCount",
|
||||
"columnName": "albumCount",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "closeness",
|
||||
"columnName": "closeness",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"columnNames": [
|
||||
"id"
|
||||
],
|
||||
"autoGenerate": false
|
||||
},
|
||||
"indices": [],
|
||||
"foreignKeys": []
|
||||
},
|
||||
{
|
||||
"tableName": "albums",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `parent` TEXT, `album` TEXT, `title` TEXT, `name` TEXT, `discNumber` INTEGER, `coverArt` TEXT, `songCount` INTEGER, `created` INTEGER, `artist` TEXT, `artistId` TEXT, `duration` INTEGER, `year` INTEGER, `genre` TEXT, `starred` INTEGER NOT NULL, `path` TEXT, `closeness` INTEGER NOT NULL, `isDirectory` INTEGER NOT NULL, `isVideo` INTEGER NOT NULL, PRIMARY KEY(`id`))",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "id",
|
||||
"columnName": "id",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "parent",
|
||||
"columnName": "parent",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "album",
|
||||
"columnName": "album",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "title",
|
||||
"columnName": "title",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "name",
|
||||
"columnName": "name",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "discNumber",
|
||||
"columnName": "discNumber",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "coverArt",
|
||||
"columnName": "coverArt",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "songCount",
|
||||
"columnName": "songCount",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "created",
|
||||
"columnName": "created",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "artist",
|
||||
"columnName": "artist",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "artistId",
|
||||
"columnName": "artistId",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "duration",
|
||||
"columnName": "duration",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "year",
|
||||
"columnName": "year",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "genre",
|
||||
"columnName": "genre",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "starred",
|
||||
"columnName": "starred",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "path",
|
||||
"columnName": "path",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "closeness",
|
||||
"columnName": "closeness",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "isDirectory",
|
||||
"columnName": "isDirectory",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "isVideo",
|
||||
"columnName": "isVideo",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"columnNames": [
|
||||
"id"
|
||||
],
|
||||
"autoGenerate": false
|
||||
},
|
||||
"indices": [],
|
||||
"foreignKeys": []
|
||||
},
|
||||
{
|
||||
"tableName": "tracks",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `parent` TEXT, `isDirectory` INTEGER NOT NULL, `title` TEXT, `album` TEXT, `albumId` TEXT, `artist` TEXT, `artistId` TEXT, `track` INTEGER, `year` INTEGER, `genre` TEXT, `contentType` TEXT, `suffix` TEXT, `transcodedContentType` TEXT, `transcodedSuffix` TEXT, `coverArt` TEXT, `size` INTEGER, `songCount` INTEGER, `duration` INTEGER, `bitRate` INTEGER, `path` TEXT, `isVideo` INTEGER NOT NULL, `starred` INTEGER NOT NULL, `discNumber` INTEGER, `type` TEXT, `created` INTEGER, `closeness` INTEGER NOT NULL, `bookmarkPosition` INTEGER NOT NULL, `userRating` INTEGER, `averageRating` REAL, `name` TEXT, PRIMARY KEY(`id`))",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "id",
|
||||
"columnName": "id",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "parent",
|
||||
"columnName": "parent",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "isDirectory",
|
||||
"columnName": "isDirectory",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "title",
|
||||
"columnName": "title",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "album",
|
||||
"columnName": "album",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "albumId",
|
||||
"columnName": "albumId",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "artist",
|
||||
"columnName": "artist",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "artistId",
|
||||
"columnName": "artistId",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "track",
|
||||
"columnName": "track",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "year",
|
||||
"columnName": "year",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "genre",
|
||||
"columnName": "genre",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "contentType",
|
||||
"columnName": "contentType",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "suffix",
|
||||
"columnName": "suffix",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "transcodedContentType",
|
||||
"columnName": "transcodedContentType",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "transcodedSuffix",
|
||||
"columnName": "transcodedSuffix",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "coverArt",
|
||||
"columnName": "coverArt",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "size",
|
||||
"columnName": "size",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "songCount",
|
||||
"columnName": "songCount",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "duration",
|
||||
"columnName": "duration",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "bitRate",
|
||||
"columnName": "bitRate",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "path",
|
||||
"columnName": "path",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "isVideo",
|
||||
"columnName": "isVideo",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "starred",
|
||||
"columnName": "starred",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "discNumber",
|
||||
"columnName": "discNumber",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "type",
|
||||
"columnName": "type",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "created",
|
||||
"columnName": "created",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "closeness",
|
||||
"columnName": "closeness",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "bookmarkPosition",
|
||||
"columnName": "bookmarkPosition",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "userRating",
|
||||
"columnName": "userRating",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "averageRating",
|
||||
"columnName": "averageRating",
|
||||
"affinity": "REAL",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "name",
|
||||
"columnName": "name",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"columnNames": [
|
||||
"id"
|
||||
],
|
||||
"autoGenerate": false
|
||||
},
|
||||
"indices": [],
|
||||
"foreignKeys": []
|
||||
},
|
||||
{
|
||||
"tableName": "indexes",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `name` TEXT, `index` TEXT, `coverArt` TEXT, `albumCount` INTEGER, `closeness` INTEGER NOT NULL, `musicFolderId` TEXT, PRIMARY KEY(`id`))",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "id",
|
||||
"columnName": "id",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "name",
|
||||
"columnName": "name",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "index",
|
||||
"columnName": "index",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "coverArt",
|
||||
"columnName": "coverArt",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "albumCount",
|
||||
"columnName": "albumCount",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "closeness",
|
||||
"columnName": "closeness",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "musicFolderId",
|
||||
"columnName": "musicFolderId",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"columnNames": [
|
||||
"id"
|
||||
],
|
||||
"autoGenerate": false
|
||||
},
|
||||
"indices": [],
|
||||
"foreignKeys": []
|
||||
},
|
||||
{
|
||||
"tableName": "music_folders",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `name` TEXT NOT NULL, PRIMARY KEY(`id`))",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "id",
|
||||
"columnName": "id",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "name",
|
||||
"columnName": "name",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"columnNames": [
|
||||
"id"
|
||||
],
|
||||
"autoGenerate": false
|
||||
},
|
||||
"indices": [],
|
||||
"foreignKeys": []
|
||||
}
|
||||
],
|
||||
"views": [],
|
||||
"setupQueries": [
|
||||
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
|
||||
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'b6ac795e7857eac4fed2dbbd01f80fb8')"
|
||||
]
|
||||
}
|
||||
}
|
|
@ -19,6 +19,7 @@ import androidx.recyclerview.widget.RecyclerView
|
|||
import com.drakeet.multitype.ItemViewBinder
|
||||
import org.koin.core.component.KoinComponent
|
||||
import org.moire.ultrasonic.R
|
||||
import org.moire.ultrasonic.data.ActiveServerProvider
|
||||
import org.moire.ultrasonic.domain.ArtistOrIndex
|
||||
import org.moire.ultrasonic.domain.Identifiable
|
||||
import org.moire.ultrasonic.imageloader.ImageLoader
|
||||
|
@ -57,7 +58,7 @@ class ArtistRowBinder(
|
|||
|
||||
holder.coverArtId = item.coverArt
|
||||
|
||||
if (Settings.shouldShowArtistPicture) {
|
||||
if (showArtistPicture()) {
|
||||
holder.coverArt.visibility = View.VISIBLE
|
||||
val key = FileUtil.getArtistArtKey(item.name, false)
|
||||
imageLoader.loadImage(
|
||||
|
@ -108,6 +109,12 @@ class ArtistRowBinder(
|
|||
return section.toString()
|
||||
}
|
||||
|
||||
private fun showArtistPicture(): Boolean {
|
||||
val isOffline = ActiveServerProvider.isOffline()
|
||||
val shouldShowArtistPicture = Settings.shouldShowArtistPicture
|
||||
return (!isOffline && shouldShowArtistPicture) || Settings.useId3TagsOffline
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an instance of our ViewHolder class
|
||||
*/
|
||||
|
|
|
@ -110,7 +110,14 @@ class ActiveServerProvider(
|
|||
|
||||
Timber.i("Switching to new database, id:$activeServer")
|
||||
cachedServerId = activeServer
|
||||
return buildDatabase(cachedServerId)
|
||||
return Room.databaseBuilder(
|
||||
UApp.applicationContext(),
|
||||
MetaDatabase::class.java,
|
||||
METADATA_DB + cachedServerId
|
||||
)
|
||||
.addMigrations(META_MIGRATION_2_1)
|
||||
.fallbackToDestructiveMigrationOnDowngrade()
|
||||
.build()
|
||||
}
|
||||
|
||||
val offlineMetaDatabase: MetaDatabase by lazy {
|
||||
|
|
|
@ -0,0 +1,68 @@
|
|||
package org.moire.ultrasonic.data
|
||||
|
||||
import androidx.room.Dao
|
||||
import androidx.room.Query
|
||||
import androidx.room.Transaction
|
||||
import org.moire.ultrasonic.domain.Album
|
||||
|
||||
@Dao
|
||||
interface AlbumDao : GenericDao<Album> {
|
||||
/**
|
||||
* Clear the whole database
|
||||
*/
|
||||
@Query("DELETE FROM albums")
|
||||
fun clear()
|
||||
|
||||
/**
|
||||
* Get all albums
|
||||
*/
|
||||
@Query("SELECT * FROM albums")
|
||||
fun get(): List<Album>
|
||||
|
||||
/**
|
||||
* Get albums by artist
|
||||
*/
|
||||
@Query("SELECT * FROM albums WHERE artistId LIKE :id")
|
||||
fun byArtist(id: String): List<Album>
|
||||
|
||||
/**
|
||||
* Clear albums by artist
|
||||
*/
|
||||
@Query("DELETE FROM albums WHERE artistId LIKE :id")
|
||||
fun clearByArtist(id: String)
|
||||
|
||||
/**
|
||||
* FIXME: Make generic
|
||||
* Upserts (insert or update) an object to the database
|
||||
*
|
||||
* @param obj the object to upsert
|
||||
*/
|
||||
@Transaction
|
||||
@JvmSuppressWildcards
|
||||
fun upsert(obj: Album) {
|
||||
val id = insertIgnoring(obj)
|
||||
if (id == -1L) {
|
||||
update(obj)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Upserts (insert or update) a list of objects
|
||||
*
|
||||
* @param objList the object to be upserted
|
||||
*/
|
||||
@Transaction
|
||||
@JvmSuppressWildcards
|
||||
fun upsert(objList: List<Album>) {
|
||||
val insertResult = insertIgnoring(objList)
|
||||
val updateList: MutableList<Album> = ArrayList()
|
||||
for (i in insertResult.indices) {
|
||||
if (insertResult[i] == -1L) {
|
||||
updateList.add(objList[i])
|
||||
}
|
||||
}
|
||||
if (updateList.isNotEmpty()) {
|
||||
update(updateList)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -43,5 +43,5 @@ interface ArtistsDao {
|
|||
* Get artist by id
|
||||
*/
|
||||
@Query("SELECT * FROM artists WHERE id LIKE :id")
|
||||
fun get(id: String): Artist
|
||||
fun get(id: String): Artist?
|
||||
}
|
||||
|
|
|
@ -1,7 +1,14 @@
|
|||
package org.moire.ultrasonic.data
|
||||
|
||||
import androidx.room.AutoMigration
|
||||
import androidx.room.Database
|
||||
import androidx.room.RoomDatabase
|
||||
import androidx.room.TypeConverter
|
||||
import androidx.room.TypeConverters
|
||||
import androidx.room.migration.Migration
|
||||
import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
import org.moire.ultrasonic.domain.Album
|
||||
import java.util.Date
|
||||
import org.moire.ultrasonic.domain.Artist
|
||||
import org.moire.ultrasonic.domain.Index
|
||||
import org.moire.ultrasonic.domain.MusicFolder
|
||||
|
@ -11,14 +18,41 @@ import org.moire.ultrasonic.domain.MusicFolder
|
|||
*/
|
||||
|
||||
@Database(
|
||||
entities = [Artist::class, Index::class, MusicFolder::class],
|
||||
version = 1,
|
||||
entities = [Artist::class, Album::class, Index::class, MusicFolder::class],
|
||||
version = 2,
|
||||
autoMigrations = [
|
||||
AutoMigration(from = 1, to = 2)
|
||||
],
|
||||
exportSchema = true
|
||||
)
|
||||
@TypeConverters(Converters::class)
|
||||
abstract class MetaDatabase : RoomDatabase() {
|
||||
abstract fun artistsDao(): ArtistsDao
|
||||
|
||||
abstract fun albumDao(): AlbumDao
|
||||
|
||||
abstract fun musicFoldersDao(): MusicFoldersDao
|
||||
|
||||
abstract fun indexDao(): IndexDao
|
||||
}
|
||||
|
||||
class Converters {
|
||||
@TypeConverter
|
||||
fun fromTimestamp(value: Long?): Date? {
|
||||
return value?.let { Date(it) }
|
||||
}
|
||||
|
||||
@TypeConverter
|
||||
fun dateToTimestamp(date: Date?): Long? {
|
||||
return date?.time
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: Check if correct
|
||||
val META_MIGRATION_2_1: Migration = object : Migration(2, 1) {
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
database.execSQL(
|
||||
"DROP TABLE ServerSetting"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,7 +39,7 @@ class AlbumListModel(application: Application) : GenericListModel(application) {
|
|||
id: String,
|
||||
name: String?
|
||||
) {
|
||||
list.postValue(musicService.getArtist(id, name, refresh))
|
||||
list.postValue(musicService.getAlbumsOfArtist(id, name, refresh))
|
||||
}
|
||||
|
||||
override fun load(
|
||||
|
|
|
@ -26,6 +26,7 @@ import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
|||
import java.text.Collator
|
||||
import org.moire.ultrasonic.domain.ArtistOrIndex
|
||||
import org.moire.ultrasonic.service.MusicService
|
||||
import org.moire.ultrasonic.util.Settings
|
||||
|
||||
/**
|
||||
* Provides ViewModel which contains the list of available Artists
|
||||
|
@ -58,7 +59,7 @@ class ArtistListModel(application: Application) : GenericListModel(application)
|
|||
|
||||
val result: List<ArtistOrIndex>
|
||||
|
||||
if (!isOffline && useId3Tags) {
|
||||
if (!isOffline && useId3Tags || Settings.useId3TagsOffline) {
|
||||
result = musicService.getArtists(refresh)
|
||||
} else {
|
||||
result = musicService.getIndexes(musicFolderId, refresh)
|
||||
|
|
|
@ -635,7 +635,7 @@ class AutoMediaBrowserCallback(var player: Player, val libraryService: MediaLibr
|
|||
|
||||
return serviceScope.future {
|
||||
val albums = if (!isOffline && useId3Tags) {
|
||||
callWithErrorHandling { musicService.getArtist(id, name, false) }
|
||||
callWithErrorHandling { musicService.getAlbumsOfArtist(id, name, false) }
|
||||
} else {
|
||||
callWithErrorHandling {
|
||||
musicService.getMusicDirectory(id, name, false).getAlbums()
|
||||
|
|
|
@ -43,7 +43,6 @@ class CachedMusicService(private val musicService: MusicService) : MusicService,
|
|||
|
||||
// Old style TimeLimitedCache
|
||||
private val cachedMusicDirectories: LRUCache<String, TimeLimitedCache<MusicDirectory?>>
|
||||
private val cachedArtist: LRUCache<String, TimeLimitedCache<List<Album>>>
|
||||
private val cachedAlbum: LRUCache<String, TimeLimitedCache<MusicDirectory?>>
|
||||
private val cachedUserInfo: LRUCache<String, TimeLimitedCache<UserInfo?>>
|
||||
private val cachedLicenseValid = TimeLimitedCache<Boolean>(120, TimeUnit.SECONDS)
|
||||
|
@ -54,6 +53,7 @@ class CachedMusicService(private val musicService: MusicService) : MusicService,
|
|||
|
||||
// New Room Database
|
||||
private var cachedArtists = metaDatabase.artistsDao()
|
||||
private var cachedAlbums = metaDatabase.albumDao()
|
||||
private var cachedIndexes = metaDatabase.indexDao()
|
||||
private val cachedMusicFolders = metaDatabase.musicFoldersDao()
|
||||
|
||||
|
@ -103,10 +103,10 @@ class CachedMusicService(private val musicService: MusicService) : MusicService,
|
|||
|
||||
var indexes: List<Index>
|
||||
|
||||
if (musicFolderId == null) {
|
||||
indexes = cachedIndexes.get()
|
||||
indexes = if (musicFolderId == null) {
|
||||
cachedIndexes.get()
|
||||
} else {
|
||||
indexes = cachedIndexes.get(musicFolderId)
|
||||
cachedIndexes.get(musicFolderId)
|
||||
}
|
||||
|
||||
if (indexes.isEmpty()) {
|
||||
|
@ -117,17 +117,40 @@ class CachedMusicService(private val musicService: MusicService) : MusicService,
|
|||
return indexes
|
||||
}
|
||||
|
||||
// FIXME why commented?
|
||||
// @Throws(Exception::class)
|
||||
// override fun getArtist(id: String, refresh: Boolean): Artist? {
|
||||
//
|
||||
// // Check if we have a cache hit
|
||||
// var result = cachedArtists.get(id)
|
||||
//
|
||||
// if (result == null || refresh) {
|
||||
// musicService.getArtists(refresh = true)
|
||||
// }
|
||||
// //var result = cachedArtists.get()
|
||||
//
|
||||
// if (result.isEmpty()) {
|
||||
// result = getArtists(refresh)
|
||||
// // FIXME
|
||||
// // cachedAlbums.clear()
|
||||
// cachedArtists.set(result)
|
||||
// }
|
||||
// return result
|
||||
// }
|
||||
//
|
||||
@Throws(Exception::class)
|
||||
override fun getArtists(refresh: Boolean): List<Artist> {
|
||||
checkSettingsChanged()
|
||||
if (refresh) {
|
||||
cachedArtists.clear()
|
||||
}
|
||||
// FIXME unnecessary check
|
||||
var result = cachedArtists.get()
|
||||
|
||||
if (result.isEmpty()) {
|
||||
result = musicService.getArtists(refresh)
|
||||
cachedArtist.clear()
|
||||
// FIXME
|
||||
// cachedAlbums.clear()
|
||||
cachedArtists.set(result)
|
||||
}
|
||||
return result
|
||||
|
@ -150,20 +173,24 @@ class CachedMusicService(private val musicService: MusicService) : MusicService,
|
|||
}
|
||||
|
||||
@Throws(Exception::class)
|
||||
override fun getArtist(id: String, name: String?, refresh: Boolean):
|
||||
override fun getAlbumsOfArtist(id: String, name: String?, refresh: Boolean):
|
||||
List<Album> {
|
||||
checkSettingsChanged()
|
||||
var cache = if (refresh) null else cachedArtist[id]
|
||||
var dir = cache?.get()
|
||||
if (dir == null) {
|
||||
dir = musicService.getArtist(id, name, refresh)
|
||||
cache = TimeLimitedCache(
|
||||
Settings.directoryCacheTime.toLong(), TimeUnit.SECONDS
|
||||
)
|
||||
cache.set(dir)
|
||||
cachedArtist.put(id, cache)
|
||||
|
||||
var result: List<Album>
|
||||
|
||||
result = if (refresh) {
|
||||
cachedAlbums.clearByArtist(id)
|
||||
listOf()
|
||||
} else {
|
||||
cachedAlbums.byArtist(id)
|
||||
}
|
||||
return dir
|
||||
|
||||
if (result.isEmpty()) {
|
||||
result = musicService.getAlbumsOfArtist(id, name, refresh)
|
||||
cachedAlbums.upsert(result)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
@Throws(Exception::class)
|
||||
|
@ -327,6 +354,7 @@ class CachedMusicService(private val musicService: MusicService) : MusicService,
|
|||
// Switch database
|
||||
metaDatabase = activeServerProvider.getActiveMetaDatabase()
|
||||
cachedArtists = metaDatabase.artistsDao()
|
||||
cachedAlbums = metaDatabase.albumDao()
|
||||
cachedIndexes = metaDatabase.indexDao()
|
||||
|
||||
// Clear in memory caches
|
||||
|
@ -335,7 +363,6 @@ class CachedMusicService(private val musicService: MusicService) : MusicService,
|
|||
cachedPlaylists.clear()
|
||||
cachedGenres.clear()
|
||||
cachedAlbum.clear()
|
||||
cachedArtist.clear()
|
||||
cachedUserInfo.clear()
|
||||
|
||||
// Set the cache keys
|
||||
|
@ -472,7 +499,6 @@ class CachedMusicService(private val musicService: MusicService) : MusicService,
|
|||
|
||||
init {
|
||||
cachedMusicDirectories = LRUCache(MUSIC_DIR_CACHE_SIZE)
|
||||
cachedArtist = LRUCache(MUSIC_DIR_CACHE_SIZE)
|
||||
cachedAlbum = LRUCache(MUSIC_DIR_CACHE_SIZE)
|
||||
cachedUserInfo = LRUCache(MUSIC_DIR_CACHE_SIZE)
|
||||
}
|
||||
|
|
|
@ -59,7 +59,7 @@ interface MusicService {
|
|||
fun getMusicDirectory(id: String, name: String?, refresh: Boolean): MusicDirectory
|
||||
|
||||
@Throws(Exception::class)
|
||||
fun getArtist(id: String, name: String?, refresh: Boolean): List<Album>
|
||||
fun getAlbumsOfArtist(id: String, name: String?, refresh: Boolean): List<Album>
|
||||
|
||||
@Throws(Exception::class)
|
||||
fun getAlbum(id: String, name: String?, refresh: Boolean): MusicDirectory
|
||||
|
|
|
@ -23,6 +23,7 @@ import java.util.regex.Pattern
|
|||
import org.koin.core.component.KoinComponent
|
||||
import org.koin.core.component.inject
|
||||
import org.moire.ultrasonic.data.ActiveServerProvider
|
||||
import org.moire.ultrasonic.data.MetaDatabase
|
||||
import org.moire.ultrasonic.domain.Album
|
||||
import org.moire.ultrasonic.domain.Artist
|
||||
import org.moire.ultrasonic.domain.ArtistOrIndex
|
||||
|
@ -52,6 +53,14 @@ import timber.log.Timber
|
|||
class OfflineMusicService : MusicService, KoinComponent {
|
||||
private val activeServerProvider: ActiveServerProvider by inject()
|
||||
|
||||
private var metaDatabase: MetaDatabase = activeServerProvider.getActiveMetaDatabase()
|
||||
|
||||
// New Room Database
|
||||
private var cachedArtists = metaDatabase.artistsDao()
|
||||
private var cachedAlbums = metaDatabase.albumDao()
|
||||
private var cachedIndexes = metaDatabase.indexDao()
|
||||
private val cachedMusicFolders = metaDatabase.musicFoldersDao()
|
||||
|
||||
override fun getIndexes(musicFolderId: String?, refresh: Boolean): List<Index> {
|
||||
val indexes: MutableList<Index> = ArrayList()
|
||||
val root = FileUtil.musicDirectory
|
||||
|
@ -97,6 +106,16 @@ class OfflineMusicService : MusicService, KoinComponent {
|
|||
return indexes
|
||||
}
|
||||
|
||||
@Throws(OfflineException::class)
|
||||
override fun getArtists(refresh: Boolean): List<Artist> {
|
||||
var result = cachedArtists.get()
|
||||
|
||||
if (result.isEmpty()) {
|
||||
// use indexes?
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
/*
|
||||
* Especially when dealing with indexes, this method can return Albums, Entries or a mix of both!
|
||||
*/
|
||||
|
@ -450,15 +469,11 @@ class OfflineMusicService : MusicService, KoinComponent {
|
|||
|
||||
override fun isLicenseValid(): Boolean = true
|
||||
|
||||
@Throws(OfflineException::class)
|
||||
override fun getArtists(refresh: Boolean): List<Artist> {
|
||||
throw OfflineException("getArtists isn't available in offline mode")
|
||||
}
|
||||
|
||||
@Throws(OfflineException::class)
|
||||
override fun getArtist(id: String, name: String?, refresh: Boolean):
|
||||
@Throws(Exception::class)
|
||||
override fun getAlbumsOfArtist(id: String, name: String?, refresh: Boolean):
|
||||
List<Album> {
|
||||
throw OfflineException("getArtist isn't available in offline mode")
|
||||
// FIXME: Add fallback?
|
||||
return cachedAlbums.byArtist(id)
|
||||
}
|
||||
|
||||
@Throws(OfflineException::class)
|
||||
|
|
|
@ -141,7 +141,7 @@ open class RESTMusicService(
|
|||
}
|
||||
|
||||
@Throws(Exception::class)
|
||||
override fun getArtist(
|
||||
override fun getAlbumsOfArtist(
|
||||
id: String,
|
||||
name: String?,
|
||||
refresh: Boolean
|
||||
|
|
|
@ -269,7 +269,7 @@ class DownloadHandler(
|
|||
return
|
||||
}
|
||||
val musicService = getMusicService()
|
||||
val artist = musicService.getArtist(id, "", false)
|
||||
val artist = musicService.getAlbumsOfArtist(id, "", false)
|
||||
for ((id1) in artist) {
|
||||
val albumDirectory = musicService.getAlbum(
|
||||
id1,
|
||||
|
|
|
@ -13,7 +13,6 @@ import androidx.preference.PreferenceManager
|
|||
import java.util.regex.Pattern
|
||||
import org.moire.ultrasonic.R
|
||||
import org.moire.ultrasonic.app.UApp
|
||||
import org.moire.ultrasonic.data.ActiveServerProvider
|
||||
|
||||
/**
|
||||
* Contains convenience functions for reading and writing preferences
|
||||
|
@ -161,8 +160,7 @@ object Settings {
|
|||
by BooleanSetting(Constants.PREFERENCES_KEY_SHOW_NOW_PLAYING_DETAILS, false)
|
||||
|
||||
@JvmStatic
|
||||
var shouldUseId3Tags
|
||||
by BooleanSetting(Constants.PREFERENCES_KEY_ID3_TAGS, false)
|
||||
var shouldUseId3Tags by BooleanSetting(Constants.PREFERENCES_KEY_ID3_TAGS, false)
|
||||
|
||||
var activeServer by IntSetting(Constants.PREFERENCES_KEY_SERVER_INSTANCE, -1)
|
||||
|
||||
|
@ -170,15 +168,8 @@ object Settings {
|
|||
|
||||
var firstRunExecuted by BooleanSetting(Constants.PREFERENCES_KEY_FIRST_RUN_EXECUTED, false)
|
||||
|
||||
val shouldShowArtistPicture: Boolean
|
||||
get() {
|
||||
val preferences = preferences
|
||||
val isOffline = ActiveServerProvider.isOffline()
|
||||
val isId3Enabled = preferences.getBoolean(Constants.PREFERENCES_KEY_ID3_TAGS, false)
|
||||
val shouldShowArtistPicture =
|
||||
preferences.getBoolean(Constants.PREFERENCES_KEY_SHOW_ARTIST_PICTURE, false)
|
||||
return !isOffline && isId3Enabled && shouldShowArtistPicture
|
||||
}
|
||||
val shouldShowArtistPicture
|
||||
by BooleanSetting(Constants.PREFERENCES_KEY_SHOW_ARTIST_PICTURE, false)
|
||||
|
||||
@JvmStatic
|
||||
var chatRefreshInterval by StringIntSetting(
|
||||
|
@ -253,6 +244,8 @@ object Settings {
|
|||
|
||||
var useHwOffload by BooleanSetting(Constants.PREFERENCES_KEY_HARDWARE_OFFLOAD, false)
|
||||
|
||||
var useId3TagsOffline = true
|
||||
|
||||
// TODO: Remove in December 2022
|
||||
fun migrateFeatureStorage() {
|
||||
val sp = appContext.getSharedPreferences("feature_flags", Context.MODE_PRIVATE)
|
||||
|
|
Loading…
Reference in New Issue