musikr: remove di requirement from tagcache
This commit is contained in:
parent
45ead8253a
commit
530d8cc2b5
11 changed files with 109 additions and 77 deletions
|
@ -18,11 +18,15 @@
|
||||||
|
|
||||||
package org.oxycblt.auxio.music
|
package org.oxycblt.auxio.music
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
import dagger.Binds
|
import dagger.Binds
|
||||||
import dagger.Module
|
import dagger.Module
|
||||||
|
import dagger.Provides
|
||||||
import dagger.hilt.InstallIn
|
import dagger.hilt.InstallIn
|
||||||
|
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||||
import dagger.hilt.components.SingletonComponent
|
import dagger.hilt.components.SingletonComponent
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
import org.oxycblt.musikr.tag.cache.TagDatabase
|
||||||
|
|
||||||
@Module
|
@Module
|
||||||
@InstallIn(SingletonComponent::class)
|
@InstallIn(SingletonComponent::class)
|
||||||
|
@ -31,3 +35,11 @@ interface MusicModule {
|
||||||
|
|
||||||
@Binds fun settings(musicSettingsImpl: MusicSettingsImpl): MusicSettings
|
@Binds fun settings(musicSettingsImpl: MusicSettingsImpl): MusicSettings
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Module
|
||||||
|
@InstallIn(SingletonComponent::class)
|
||||||
|
class MusikrShimModule {
|
||||||
|
@Singleton
|
||||||
|
@Provides
|
||||||
|
fun tagDatabase(@ApplicationContext context: Context) = TagDatabase.from(context)
|
||||||
|
}
|
||||||
|
|
|
@ -26,19 +26,18 @@ import kotlinx.coroutines.withContext
|
||||||
import kotlinx.coroutines.yield
|
import kotlinx.coroutines.yield
|
||||||
import org.oxycblt.auxio.music.MusicRepository.IndexingWorker
|
import org.oxycblt.auxio.music.MusicRepository.IndexingWorker
|
||||||
import org.oxycblt.musikr.IndexingProgress
|
import org.oxycblt.musikr.IndexingProgress
|
||||||
|
import org.oxycblt.musikr.Interpretation
|
||||||
import org.oxycblt.musikr.Library
|
import org.oxycblt.musikr.Library
|
||||||
import org.oxycblt.musikr.Music
|
import org.oxycblt.musikr.Music
|
||||||
import org.oxycblt.musikr.Musikr
|
import org.oxycblt.musikr.Musikr
|
||||||
import org.oxycblt.musikr.MutableLibrary
|
import org.oxycblt.musikr.MutableLibrary
|
||||||
import org.oxycblt.musikr.Playlist
|
import org.oxycblt.musikr.Playlist
|
||||||
import org.oxycblt.musikr.Song
|
import org.oxycblt.musikr.Song
|
||||||
import org.oxycblt.musikr.Interpretation
|
|
||||||
import org.oxycblt.musikr.Storage
|
import org.oxycblt.musikr.Storage
|
||||||
import org.oxycblt.musikr.cover.Cover
|
|
||||||
import org.oxycblt.musikr.cover.StoredCovers
|
import org.oxycblt.musikr.cover.StoredCovers
|
||||||
import org.oxycblt.musikr.tag.Name
|
import org.oxycblt.musikr.tag.Name
|
||||||
import org.oxycblt.musikr.tag.cache.FullTagCache
|
import org.oxycblt.musikr.tag.cache.TagCache
|
||||||
import org.oxycblt.musikr.tag.cache.WriteOnlyTagCache
|
import org.oxycblt.musikr.tag.cache.TagDatabase
|
||||||
import org.oxycblt.musikr.tag.interpret.Separators
|
import org.oxycblt.musikr.tag.interpret.Separators
|
||||||
import timber.log.Timber as L
|
import timber.log.Timber as L
|
||||||
|
|
||||||
|
@ -208,8 +207,11 @@ interface MusicRepository {
|
||||||
|
|
||||||
class MusicRepositoryImpl
|
class MusicRepositoryImpl
|
||||||
@Inject
|
@Inject
|
||||||
constructor(private val musikr: Musikr, private val fullTagCache: FullTagCache, private val writeOnlyTagCache: WriteOnlyTagCache, private val musicSettings: MusicSettings) :
|
constructor(
|
||||||
MusicRepository {
|
private val musikr: Musikr,
|
||||||
|
private val tagDatabase: TagDatabase,
|
||||||
|
private val musicSettings: MusicSettings
|
||||||
|
) : MusicRepository {
|
||||||
private val updateListeners = mutableListOf<MusicRepository.UpdateListener>()
|
private val updateListeners = mutableListOf<MusicRepository.UpdateListener>()
|
||||||
private val indexingListeners = mutableListOf<MusicRepository.IndexingListener>()
|
private val indexingListeners = mutableListOf<MusicRepository.IndexingListener>()
|
||||||
@Volatile private var indexingWorker: MusicRepository.IndexingWorker? = null
|
@Volatile private var indexingWorker: MusicRepository.IndexingWorker? = null
|
||||||
|
@ -354,13 +356,15 @@ constructor(private val musikr: Musikr, private val fullTagCache: FullTagCache,
|
||||||
}
|
}
|
||||||
val locations = musicSettings.musicLocations
|
val locations = musicSettings.musicLocations
|
||||||
|
|
||||||
val storage = if (withCache) {
|
val storage =
|
||||||
Storage(fullTagCache, StoredCovers.buildOn())
|
if (withCache) {
|
||||||
} else {
|
Storage(TagCache.full(tagDatabase), StoredCovers.buildOn())
|
||||||
Storage(writeOnlyTagCache, StoredCovers.new())
|
} else {
|
||||||
}
|
Storage(TagCache.writeOnly(tagDatabase), StoredCovers.new())
|
||||||
|
}
|
||||||
val newLibrary =
|
val newLibrary =
|
||||||
musikr.run(locations, storage, Interpretation(nameFactory, separators), ::emitIndexingProgress)
|
musikr.run(
|
||||||
|
locations, storage, Interpretation(nameFactory, separators), ::emitIndexingProgress)
|
||||||
|
|
||||||
emitIndexingCompletion(null)
|
emitIndexingCompletion(null)
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,21 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2024 Auxio Project
|
||||||
|
* Config.kt is part of Auxio.
|
||||||
|
*
|
||||||
|
* This program 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 program 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 this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
package org.oxycblt.musikr
|
package org.oxycblt.musikr
|
||||||
|
|
||||||
import org.oxycblt.musikr.cover.StoredCovers
|
import org.oxycblt.musikr.cover.StoredCovers
|
||||||
|
|
|
@ -18,13 +18,9 @@
|
||||||
|
|
||||||
package org.oxycblt.musikr.cover
|
package org.oxycblt.musikr.cover
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import androidx.room.Room
|
|
||||||
import dagger.Binds
|
import dagger.Binds
|
||||||
import dagger.Module
|
import dagger.Module
|
||||||
import dagger.Provides
|
|
||||||
import dagger.hilt.InstallIn
|
import dagger.hilt.InstallIn
|
||||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
|
||||||
import dagger.hilt.components.SingletonComponent
|
import dagger.hilt.components.SingletonComponent
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,29 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2024 Auxio Project
|
||||||
|
* CoverParser.kt is part of Auxio.
|
||||||
|
*
|
||||||
|
* This program 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 program 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 this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
package org.oxycblt.musikr.cover
|
package org.oxycblt.musikr.cover
|
||||||
|
|
||||||
import androidx.media3.common.MediaMetadata
|
import androidx.media3.common.MediaMetadata
|
||||||
import androidx.media3.common.Metadata
|
import androidx.media3.common.Metadata
|
||||||
import androidx.media3.extractor.metadata.flac.PictureFrame
|
import androidx.media3.extractor.metadata.flac.PictureFrame
|
||||||
import androidx.media3.extractor.metadata.id3.ApicFrame
|
import androidx.media3.extractor.metadata.id3.ApicFrame
|
||||||
import org.oxycblt.musikr.metadata.AudioMetadata
|
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
import org.oxycblt.musikr.metadata.AudioMetadata
|
||||||
|
|
||||||
interface CoverParser {
|
interface CoverParser {
|
||||||
suspend fun extract(metadata: AudioMetadata): ByteArray?
|
suspend fun extract(metadata: AudioMetadata): ByteArray?
|
||||||
|
@ -32,12 +50,10 @@ class CoverParserImpl @Inject constructor() : CoverParser {
|
||||||
pic = entry.pictureData
|
pic = entry.pictureData
|
||||||
type = entry.pictureType
|
type = entry.pictureType
|
||||||
}
|
}
|
||||||
|
|
||||||
is PictureFrame -> {
|
is PictureFrame -> {
|
||||||
pic = entry.pictureData
|
pic = entry.pictureData
|
||||||
type = entry.pictureType
|
type = entry.pictureType
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> continue
|
else -> continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,4 +66,4 @@ class CoverParserImpl @Inject constructor() : CoverParser {
|
||||||
|
|
||||||
return fallbackPic
|
return fallbackPic
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,21 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2024 Auxio Project
|
||||||
|
* StoredCovers.kt is part of Auxio.
|
||||||
|
*
|
||||||
|
* This program 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 program 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 this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
package org.oxycblt.musikr.cover
|
package org.oxycblt.musikr.cover
|
||||||
|
|
||||||
import java.io.InputStream
|
import java.io.InputStream
|
||||||
|
@ -11,6 +29,7 @@ interface StoredCovers {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
suspend fun buildOn(): Editor = TODO()
|
suspend fun buildOn(): Editor = TODO()
|
||||||
|
|
||||||
fun new(): Editor = TODO()
|
fun new(): Editor = TODO()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,10 +26,10 @@ import kotlinx.coroutines.flow.buffer
|
||||||
import kotlinx.coroutines.flow.filterIsInstance
|
import kotlinx.coroutines.flow.filterIsInstance
|
||||||
import kotlinx.coroutines.flow.flowOn
|
import kotlinx.coroutines.flow.flowOn
|
||||||
import kotlinx.coroutines.flow.map
|
import kotlinx.coroutines.flow.map
|
||||||
|
import org.oxycblt.musikr.Interpretation
|
||||||
import org.oxycblt.musikr.MutableLibrary
|
import org.oxycblt.musikr.MutableLibrary
|
||||||
import org.oxycblt.musikr.graph.MusicGraph
|
import org.oxycblt.musikr.graph.MusicGraph
|
||||||
import org.oxycblt.musikr.model.LibraryFactory
|
import org.oxycblt.musikr.model.LibraryFactory
|
||||||
import org.oxycblt.musikr.Interpretation
|
|
||||||
import org.oxycblt.musikr.tag.interpret.TagInterpreter
|
import org.oxycblt.musikr.tag.interpret.TagInterpreter
|
||||||
|
|
||||||
interface EvaluateStep {
|
interface EvaluateStep {
|
||||||
|
|
|
@ -18,7 +18,6 @@
|
||||||
|
|
||||||
package org.oxycblt.musikr.tag.cache
|
package org.oxycblt.musikr.tag.cache
|
||||||
|
|
||||||
import javax.inject.Inject
|
|
||||||
import org.oxycblt.musikr.fs.query.DeviceFile
|
import org.oxycblt.musikr.fs.query.DeviceFile
|
||||||
import org.oxycblt.musikr.tag.parse.ParsedTags
|
import org.oxycblt.musikr.tag.parse.ParsedTags
|
||||||
|
|
||||||
|
@ -26,9 +25,15 @@ interface TagCache {
|
||||||
suspend fun read(file: DeviceFile): ParsedTags?
|
suspend fun read(file: DeviceFile): ParsedTags?
|
||||||
|
|
||||||
suspend fun write(file: DeviceFile, tags: ParsedTags)
|
suspend fun write(file: DeviceFile, tags: ParsedTags)
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun full(db: TagDatabase): TagCache = FullTagCache(db.cachedSongsDao())
|
||||||
|
|
||||||
|
fun writeOnly(db: TagDatabase): TagCache = WriteOnlyTagCache(db.cachedSongsDao())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class FullTagCache @Inject constructor(private val tagDao: TagDao) : TagCache {
|
private class FullTagCache(private val tagDao: TagDao) : TagCache {
|
||||||
override suspend fun read(file: DeviceFile) =
|
override suspend fun read(file: DeviceFile) =
|
||||||
tagDao.selectTags(file.uri.toString(), file.lastModified)?.intoParsedTags()
|
tagDao.selectTags(file.uri.toString(), file.lastModified)?.intoParsedTags()
|
||||||
|
|
||||||
|
@ -36,9 +41,9 @@ class FullTagCache @Inject constructor(private val tagDao: TagDao) : TagCache {
|
||||||
tagDao.updateTags(CachedTags.fromParsedTags(file, tags))
|
tagDao.updateTags(CachedTags.fromParsedTags(file, tags))
|
||||||
}
|
}
|
||||||
|
|
||||||
class WriteOnlyTagCache @Inject constructor(private val tagDao: TagDao) : TagCache {
|
private class WriteOnlyTagCache(private val tagDao: TagDao) : TagCache {
|
||||||
override suspend fun read(file: DeviceFile) = null
|
override suspend fun read(file: DeviceFile) = null
|
||||||
|
|
||||||
override suspend fun write(file: DeviceFile, tags: ParsedTags) =
|
override suspend fun write(file: DeviceFile, tags: ParsedTags) =
|
||||||
tagDao.updateTags(CachedTags.fromParsedTags(file, tags))
|
tagDao.updateTags(CachedTags.fromParsedTags(file, tags))
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,48 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2023 Auxio Project
|
|
||||||
* TagCacheModule.kt is part of Auxio.
|
|
||||||
*
|
|
||||||
* This program 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 program 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 this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.oxycblt.musikr.tag.cache
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import androidx.room.Room
|
|
||||||
import dagger.Binds
|
|
||||||
import dagger.Module
|
|
||||||
import dagger.Provides
|
|
||||||
import dagger.hilt.InstallIn
|
|
||||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
|
||||||
import dagger.hilt.components.SingletonComponent
|
|
||||||
import javax.inject.Singleton
|
|
||||||
|
|
||||||
@Module
|
|
||||||
@InstallIn(SingletonComponent::class)
|
|
||||||
interface TagCacheModule {
|
|
||||||
@Binds fun tagCache(cacheRepository: TagCacheImpl): TagCache
|
|
||||||
}
|
|
||||||
|
|
||||||
@Module
|
|
||||||
@InstallIn(SingletonComponent::class)
|
|
||||||
class TagDatabaseModule {
|
|
||||||
@Singleton
|
|
||||||
@Provides
|
|
||||||
fun database(@ApplicationContext context: Context) =
|
|
||||||
Room.databaseBuilder(context.applicationContext, TagDatabase::class.java, "music_cache.db")
|
|
||||||
.fallbackToDestructiveMigration()
|
|
||||||
.build()
|
|
||||||
|
|
||||||
@Provides fun tagsDao(database: TagDatabase) = database.cachedSongsDao()
|
|
||||||
}
|
|
|
@ -18,6 +18,7 @@
|
||||||
|
|
||||||
package org.oxycblt.musikr.tag.cache
|
package org.oxycblt.musikr.tag.cache
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
import androidx.room.Dao
|
import androidx.room.Dao
|
||||||
import androidx.room.Database
|
import androidx.room.Database
|
||||||
import androidx.room.Entity
|
import androidx.room.Entity
|
||||||
|
@ -25,6 +26,7 @@ import androidx.room.Insert
|
||||||
import androidx.room.OnConflictStrategy
|
import androidx.room.OnConflictStrategy
|
||||||
import androidx.room.PrimaryKey
|
import androidx.room.PrimaryKey
|
||||||
import androidx.room.Query
|
import androidx.room.Query
|
||||||
|
import androidx.room.Room
|
||||||
import androidx.room.RoomDatabase
|
import androidx.room.RoomDatabase
|
||||||
import androidx.room.TypeConverter
|
import androidx.room.TypeConverter
|
||||||
import androidx.room.TypeConverters
|
import androidx.room.TypeConverters
|
||||||
|
@ -36,11 +38,19 @@ import org.oxycblt.musikr.tag.util.splitEscaped
|
||||||
|
|
||||||
@Database(entities = [CachedTags::class], version = 50, exportSchema = false)
|
@Database(entities = [CachedTags::class], version = 50, exportSchema = false)
|
||||||
abstract class TagDatabase : RoomDatabase() {
|
abstract class TagDatabase : RoomDatabase() {
|
||||||
abstract fun cachedSongsDao(): TagDao
|
internal abstract fun cachedSongsDao(): TagDao
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun from(context: Context) =
|
||||||
|
Room.databaseBuilder(
|
||||||
|
context.applicationContext, TagDatabase::class.java, "music_cache.db")
|
||||||
|
.fallbackToDestructiveMigration()
|
||||||
|
.build()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Dao
|
@Dao
|
||||||
interface TagDao {
|
internal interface TagDao {
|
||||||
@Query("SELECT * FROM CachedTags WHERE uri = :uri AND dateModified = :dateModified")
|
@Query("SELECT * FROM CachedTags WHERE uri = :uri AND dateModified = :dateModified")
|
||||||
suspend fun selectTags(uri: String, dateModified: Long): CachedTags?
|
suspend fun selectTags(uri: String, dateModified: Long): CachedTags?
|
||||||
|
|
||||||
|
@ -49,7 +59,7 @@ interface TagDao {
|
||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
@TypeConverters(CachedTags.Converters::class)
|
@TypeConverters(CachedTags.Converters::class)
|
||||||
data class CachedTags(
|
internal data class CachedTags(
|
||||||
/**
|
/**
|
||||||
* The Uri of the [AudioFile]'s audio file, obtained from SAF. This should ideally be a black
|
* The Uri of the [AudioFile]'s audio file, obtained from SAF. This should ideally be a black
|
||||||
* box only used for comparison.
|
* box only used for comparison.
|
||||||
|
|
|
@ -22,10 +22,10 @@ import javax.inject.Inject
|
||||||
import org.oxycblt.auxio.R
|
import org.oxycblt.auxio.R
|
||||||
import org.oxycblt.auxio.playback.replaygain.ReplayGainAdjustment
|
import org.oxycblt.auxio.playback.replaygain.ReplayGainAdjustment
|
||||||
import org.oxycblt.auxio.util.toUuidOrNull
|
import org.oxycblt.auxio.util.toUuidOrNull
|
||||||
|
import org.oxycblt.musikr.Interpretation
|
||||||
import org.oxycblt.musikr.fs.MimeType
|
import org.oxycblt.musikr.fs.MimeType
|
||||||
import org.oxycblt.musikr.fs.query.DeviceFile
|
import org.oxycblt.musikr.fs.query.DeviceFile
|
||||||
import org.oxycblt.musikr.tag.Disc
|
import org.oxycblt.musikr.tag.Disc
|
||||||
import org.oxycblt.musikr.Interpretation
|
|
||||||
import org.oxycblt.musikr.tag.Name
|
import org.oxycblt.musikr.tag.Name
|
||||||
import org.oxycblt.musikr.tag.ReleaseType
|
import org.oxycblt.musikr.tag.ReleaseType
|
||||||
import org.oxycblt.musikr.tag.parse.ParsedTags
|
import org.oxycblt.musikr.tag.parse.ParsedTags
|
||||||
|
|
Loading…
Reference in a new issue