musikr: remove di requirement from tagcache

This commit is contained in:
Alexander Capehart 2024-12-11 06:58:16 -07:00
parent 45ead8253a
commit 530d8cc2b5
No known key found for this signature in database
GPG key ID: 37DBE3621FE9AD47
11 changed files with 109 additions and 77 deletions

View file

@ -18,11 +18,15 @@
package org.oxycblt.auxio.music
import android.content.Context
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
import org.oxycblt.musikr.tag.cache.TagDatabase
@Module
@InstallIn(SingletonComponent::class)
@ -31,3 +35,11 @@ interface MusicModule {
@Binds fun settings(musicSettingsImpl: MusicSettingsImpl): MusicSettings
}
@Module
@InstallIn(SingletonComponent::class)
class MusikrShimModule {
@Singleton
@Provides
fun tagDatabase(@ApplicationContext context: Context) = TagDatabase.from(context)
}

View file

@ -26,19 +26,18 @@ import kotlinx.coroutines.withContext
import kotlinx.coroutines.yield
import org.oxycblt.auxio.music.MusicRepository.IndexingWorker
import org.oxycblt.musikr.IndexingProgress
import org.oxycblt.musikr.Interpretation
import org.oxycblt.musikr.Library
import org.oxycblt.musikr.Music
import org.oxycblt.musikr.Musikr
import org.oxycblt.musikr.MutableLibrary
import org.oxycblt.musikr.Playlist
import org.oxycblt.musikr.Song
import org.oxycblt.musikr.Interpretation
import org.oxycblt.musikr.Storage
import org.oxycblt.musikr.cover.Cover
import org.oxycblt.musikr.cover.StoredCovers
import org.oxycblt.musikr.tag.Name
import org.oxycblt.musikr.tag.cache.FullTagCache
import org.oxycblt.musikr.tag.cache.WriteOnlyTagCache
import org.oxycblt.musikr.tag.cache.TagCache
import org.oxycblt.musikr.tag.cache.TagDatabase
import org.oxycblt.musikr.tag.interpret.Separators
import timber.log.Timber as L
@ -208,8 +207,11 @@ interface MusicRepository {
class MusicRepositoryImpl
@Inject
constructor(private val musikr: Musikr, private val fullTagCache: FullTagCache, private val writeOnlyTagCache: WriteOnlyTagCache, private val musicSettings: MusicSettings) :
MusicRepository {
constructor(
private val musikr: Musikr,
private val tagDatabase: TagDatabase,
private val musicSettings: MusicSettings
) : MusicRepository {
private val updateListeners = mutableListOf<MusicRepository.UpdateListener>()
private val indexingListeners = mutableListOf<MusicRepository.IndexingListener>()
@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 storage = if (withCache) {
Storage(fullTagCache, StoredCovers.buildOn())
} else {
Storage(writeOnlyTagCache, StoredCovers.new())
}
val storage =
if (withCache) {
Storage(TagCache.full(tagDatabase), StoredCovers.buildOn())
} else {
Storage(TagCache.writeOnly(tagDatabase), StoredCovers.new())
}
val newLibrary =
musikr.run(locations, storage, Interpretation(nameFactory, separators), ::emitIndexingProgress)
musikr.run(
locations, storage, Interpretation(nameFactory, separators), ::emitIndexingProgress)
emitIndexingCompletion(null)

View file

@ -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
import org.oxycblt.musikr.cover.StoredCovers

View file

@ -18,13 +18,9 @@
package org.oxycblt.musikr.cover
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

View file

@ -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
import androidx.media3.common.MediaMetadata
import androidx.media3.common.Metadata
import androidx.media3.extractor.metadata.flac.PictureFrame
import androidx.media3.extractor.metadata.id3.ApicFrame
import org.oxycblt.musikr.metadata.AudioMetadata
import javax.inject.Inject
import org.oxycblt.musikr.metadata.AudioMetadata
interface CoverParser {
suspend fun extract(metadata: AudioMetadata): ByteArray?
@ -32,12 +50,10 @@ class CoverParserImpl @Inject constructor() : CoverParser {
pic = entry.pictureData
type = entry.pictureType
}
is PictureFrame -> {
pic = entry.pictureData
type = entry.pictureType
}
else -> continue
}
@ -50,4 +66,4 @@ class CoverParserImpl @Inject constructor() : CoverParser {
return fallbackPic
}
}
}

View file

@ -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
import java.io.InputStream
@ -11,6 +29,7 @@ interface StoredCovers {
companion object {
suspend fun buildOn(): Editor = TODO()
fun new(): Editor = TODO()
}
}

View file

@ -26,10 +26,10 @@ import kotlinx.coroutines.flow.buffer
import kotlinx.coroutines.flow.filterIsInstance
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.map
import org.oxycblt.musikr.Interpretation
import org.oxycblt.musikr.MutableLibrary
import org.oxycblt.musikr.graph.MusicGraph
import org.oxycblt.musikr.model.LibraryFactory
import org.oxycblt.musikr.Interpretation
import org.oxycblt.musikr.tag.interpret.TagInterpreter
interface EvaluateStep {

View file

@ -18,7 +18,6 @@
package org.oxycblt.musikr.tag.cache
import javax.inject.Inject
import org.oxycblt.musikr.fs.query.DeviceFile
import org.oxycblt.musikr.tag.parse.ParsedTags
@ -26,9 +25,15 @@ interface TagCache {
suspend fun read(file: DeviceFile): 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) =
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))
}
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 write(file: DeviceFile, tags: ParsedTags) =
tagDao.updateTags(CachedTags.fromParsedTags(file, tags))
}
}

View file

@ -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()
}

View file

@ -18,6 +18,7 @@
package org.oxycblt.musikr.tag.cache
import android.content.Context
import androidx.room.Dao
import androidx.room.Database
import androidx.room.Entity
@ -25,6 +26,7 @@ import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.PrimaryKey
import androidx.room.Query
import androidx.room.Room
import androidx.room.RoomDatabase
import androidx.room.TypeConverter
import androidx.room.TypeConverters
@ -36,11 +38,19 @@ import org.oxycblt.musikr.tag.util.splitEscaped
@Database(entities = [CachedTags::class], version = 50, exportSchema = false)
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
interface TagDao {
internal interface TagDao {
@Query("SELECT * FROM CachedTags WHERE uri = :uri AND dateModified = :dateModified")
suspend fun selectTags(uri: String, dateModified: Long): CachedTags?
@ -49,7 +59,7 @@ interface TagDao {
@Entity
@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
* box only used for comparison.

View file

@ -22,10 +22,10 @@ import javax.inject.Inject
import org.oxycblt.auxio.R
import org.oxycblt.auxio.playback.replaygain.ReplayGainAdjustment
import org.oxycblt.auxio.util.toUuidOrNull
import org.oxycblt.musikr.Interpretation
import org.oxycblt.musikr.fs.MimeType
import org.oxycblt.musikr.fs.query.DeviceFile
import org.oxycblt.musikr.tag.Disc
import org.oxycblt.musikr.Interpretation
import org.oxycblt.musikr.tag.Name
import org.oxycblt.musikr.tag.ReleaseType
import org.oxycblt.musikr.tag.parse.ParsedTags