diff --git a/app/src/main/java/org/oxycblt/auxio/music/Indexing.kt b/app/src/main/java/org/oxycblt/auxio/music/Indexing.kt
deleted file mode 100644
index 193b4a75a..000000000
--- a/app/src/main/java/org/oxycblt/auxio/music/Indexing.kt
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (c) 2023 Auxio Project
- * Indexing.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 .
- */
-
-package org.oxycblt.auxio.music
-
-import android.os.Build
-import org.oxycblt.musikr.IndexingProgress
-
-/** Version-aware permission identifier for reading audio files. */
-val PERMISSION_READ_AUDIO =
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
- android.Manifest.permission.READ_MEDIA_AUDIO
- } else {
- android.Manifest.permission.READ_EXTERNAL_STORAGE
- }
-
-/**
- * Represents the current state of the music loader.
- *
- * @author Alexander Capehart (OxygenCobalt)
- */
-sealed interface IndexingState {
- /**
- * Music loading is on-going.
- *
- * @param progress The current progress of the music loading.
- */
- data class Indexing(val progress: IndexingProgress) : IndexingState
-
- /**
- * Music loading has completed.
- *
- * @param error If music loading has failed, the error that occurred will be here. Otherwise, it
- * will be null.
- */
- data class Completed(val error: Exception?) : IndexingState
-}
diff --git a/app/src/main/java/org/oxycblt/auxio/music/MusicModule.kt b/app/src/main/java/org/oxycblt/auxio/music/MusicModule.kt
index 5d524b1fd..621bec0c4 100644
--- a/app/src/main/java/org/oxycblt/auxio/music/MusicModule.kt
+++ b/app/src/main/java/org/oxycblt/auxio/music/MusicModule.kt
@@ -26,7 +26,6 @@ import dagger.hilt.InstallIn
import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.components.SingletonComponent
import javax.inject.Singleton
-import org.oxycblt.musikr.cache.Cache
import org.oxycblt.musikr.cache.StoredCache
import org.oxycblt.musikr.playlist.db.StoredPlaylists
@@ -41,7 +40,9 @@ interface MusicModule {
@Module
@InstallIn(SingletonComponent::class)
class MusikrShimModule {
- @Singleton @Provides fun storedCache(@ApplicationContext context: Context) = StoredCache.from(context)
+ @Singleton
+ @Provides
+ fun storedCache(@ApplicationContext context: Context) = StoredCache.from(context)
@Singleton
@Provides
diff --git a/app/src/main/java/org/oxycblt/auxio/music/MusicRepository.kt b/app/src/main/java/org/oxycblt/auxio/music/MusicRepository.kt
index b07fccca6..0af145490 100644
--- a/app/src/main/java/org/oxycblt/auxio/music/MusicRepository.kt
+++ b/app/src/main/java/org/oxycblt/auxio/music/MusicRepository.kt
@@ -209,6 +209,28 @@ interface MusicRepository {
}
}
+/**
+ * Represents the current state of the music loader.
+ *
+ * @author Alexander Capehart (OxygenCobalt)
+ */
+sealed interface IndexingState {
+ /**
+ * Music loading is on-going.
+ *
+ * @param progress The current progress of the music loading.
+ */
+ data class Indexing(val progress: IndexingProgress) : IndexingState
+
+ /**
+ * Music loading has completed.
+ *
+ * @param error If music loading has failed, the error that occurred will be here. Otherwise, it
+ * will be null.
+ */
+ data class Completed(val error: Exception?) : IndexingState
+}
+
class MusicRepositoryImpl
@Inject
constructor(
diff --git a/app/src/main/java/org/oxycblt/auxio/music/RevisionedLibrary.kt b/app/src/main/java/org/oxycblt/auxio/music/RevisionedLibrary.kt
index d35e5f3e5..ad176e28a 100644
--- a/app/src/main/java/org/oxycblt/auxio/music/RevisionedLibrary.kt
+++ b/app/src/main/java/org/oxycblt/auxio/music/RevisionedLibrary.kt
@@ -75,7 +75,7 @@ class RevisionedCover(private val revision: UUID, val inner: Cover) : Cover by i
get() = "${inner.id}@${revision}"
}
-internal fun String.toUuidOrNull(): UUID? =
+private fun String.toUuidOrNull(): UUID? =
try {
UUID.fromString(this)
} catch (e: IllegalArgumentException) {
diff --git a/app/src/main/java/org/oxycblt/auxio/music/metadata/SeparatorsDialog.kt b/app/src/main/java/org/oxycblt/auxio/music/interpret/SeparatorsDialog.kt
similarity index 99%
rename from app/src/main/java/org/oxycblt/auxio/music/metadata/SeparatorsDialog.kt
rename to app/src/main/java/org/oxycblt/auxio/music/interpret/SeparatorsDialog.kt
index f2c5d0cec..4a37a7461 100644
--- a/app/src/main/java/org/oxycblt/auxio/music/metadata/SeparatorsDialog.kt
+++ b/app/src/main/java/org/oxycblt/auxio/music/interpret/SeparatorsDialog.kt
@@ -16,7 +16,7 @@
* along with this program. If not, see .
*/
-package org.oxycblt.auxio.music.metadata
+package org.oxycblt.auxio.music.interpret
import android.os.Bundle
import android.view.LayoutInflater
diff --git a/app/src/main/res/navigation/outer.xml b/app/src/main/res/navigation/outer.xml
index 503172f3b..0d15cbc8a 100644
--- a/app/src/main/res/navigation/outer.xml
+++ b/app/src/main/res/navigation/outer.xml
@@ -96,7 +96,7 @@
tools:layout="@layout/dialog_music_locations" />
diff --git a/musikr/src/main/java/org/oxycblt/musikr/cache/CacheDatabase.kt b/musikr/src/main/java/org/oxycblt/musikr/cache/CacheDatabase.kt
index a9f12af2a..dd4d8df63 100644
--- a/musikr/src/main/java/org/oxycblt/musikr/cache/CacheDatabase.kt
+++ b/musikr/src/main/java/org/oxycblt/musikr/cache/CacheDatabase.kt
@@ -21,7 +21,6 @@ package org.oxycblt.musikr.cache
import android.content.Context
import androidx.room.Dao
import androidx.room.Database
-import androidx.room.Delete
import androidx.room.Entity
import androidx.room.Insert
import androidx.room.OnConflictStrategy
@@ -32,7 +31,6 @@ import androidx.room.RoomDatabase
import androidx.room.Transaction
import androidx.room.TypeConverter
import androidx.room.TypeConverters
-import androidx.room.Update
import org.oxycblt.musikr.cover.StoredCovers
import org.oxycblt.musikr.fs.DeviceFile
import org.oxycblt.musikr.metadata.Properties
@@ -67,8 +65,7 @@ internal interface VisibleCacheDao {
@Query("SELECT addedMs FROM CachedSong WHERE uri = :uri")
suspend fun selectAddedMs(uri: String): Long?
- @Transaction
- suspend fun touch(uri: String) = updateTouchedNs(uri, System.nanoTime())
+ @Transaction suspend fun touch(uri: String) = updateTouchedNs(uri, System.nanoTime())
@Query("UPDATE cachedsong SET touchedNs = :nowNs WHERE uri = :uri")
suspend fun updateTouchedNs(uri: String, nowNs: Long)
@@ -84,8 +81,7 @@ internal interface InvisibleCacheDao {
internal interface CacheWriteDao {
@Insert(onConflict = OnConflictStrategy.REPLACE) suspend fun updateSong(cachedSong: CachedSong)
- @Query("DELETE FROM CachedSong WHERE touchedNs < :now")
- suspend fun pruneOlderThan(now: Long)
+ @Query("DELETE FROM CachedSong WHERE touchedNs < :now") suspend fun pruneOlderThan(now: Long)
}
@Entity
diff --git a/musikr/src/main/java/org/oxycblt/musikr/cache/StoredCache.kt b/musikr/src/main/java/org/oxycblt/musikr/cache/StoredCache.kt
index fca633e5d..5f4c95d70 100644
--- a/musikr/src/main/java/org/oxycblt/musikr/cache/StoredCache.kt
+++ b/musikr/src/main/java/org/oxycblt/musikr/cache/StoredCache.kt
@@ -1,3 +1,21 @@
+/*
+ * Copyright (c) 2024 Auxio Project
+ * StoredCache.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 .
+ */
+
package org.oxycblt.musikr.cache
import android.content.Context
@@ -24,8 +42,7 @@ private class StoredCacheImpl(private val cacheDatabase: CacheDatabase) : Stored
private abstract class BaseStoredCache(protected val writeDao: CacheWriteDao) : Cache() {
private val created = System.nanoTime()
- override suspend fun write(song: RawSong) =
- writeDao.updateSong(CachedSong.fromRawSong(song))
+ override suspend fun write(song: RawSong) = writeDao.updateSong(CachedSong.fromRawSong(song))
override suspend fun finalize() {
// Anything not create during this cache's use implies that it has not been
@@ -34,13 +51,10 @@ private abstract class BaseStoredCache(protected val writeDao: CacheWriteDao) :
}
}
-private class VisibleStoredCache(
- private val visibleDao: VisibleCacheDao,
- writeDao: CacheWriteDao
-) : BaseStoredCache(writeDao) {
+private class VisibleStoredCache(private val visibleDao: VisibleCacheDao, writeDao: CacheWriteDao) :
+ BaseStoredCache(writeDao) {
override suspend fun read(file: DeviceFile, storedCovers: StoredCovers): CacheResult {
- val song =
- visibleDao.selectSong(file.uri.toString()) ?: return CacheResult.Miss(file, null)
+ val song = visibleDao.selectSong(file.uri.toString()) ?: return CacheResult.Miss(file, null)
if (song.modifiedMs != file.lastModified) {
// We *found* this file earlier, but it's out of date.
// Send back it with the timestamp so it will be re-used.
@@ -53,7 +67,8 @@ private class VisibleStoredCache(
}
class Factory(private val cacheDatabase: CacheDatabase) : Cache.Factory() {
- override fun open() = VisibleStoredCache(cacheDatabase.visibleDao(), cacheDatabase.writeDao())
+ override fun open() =
+ VisibleStoredCache(cacheDatabase.visibleDao(), cacheDatabase.writeDao())
}
}
@@ -65,6 +80,7 @@ private class InvisibleStoredCache(
CacheResult.Miss(file, invisibleCacheDao.selectAddedMs(file.uri.toString()))
class Factory(private val cacheDatabase: CacheDatabase) : Cache.Factory() {
- override fun open() = InvisibleStoredCache(cacheDatabase.invisibleDao(), cacheDatabase.writeDao())
+ override fun open() =
+ InvisibleStoredCache(cacheDatabase.invisibleDao(), cacheDatabase.writeDao())
}
}
diff --git a/musikr/src/main/java/org/oxycblt/musikr/pipeline/ExtractStep.kt b/musikr/src/main/java/org/oxycblt/musikr/pipeline/ExtractStep.kt
index 7ef83627c..d42a17389 100644
--- a/musikr/src/main/java/org/oxycblt/musikr/pipeline/ExtractStep.kt
+++ b/musikr/src/main/java/org/oxycblt/musikr/pipeline/ExtractStep.kt
@@ -15,11 +15,12 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
-
+
package org.oxycblt.musikr.pipeline
import android.content.Context
import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.buffer
@@ -52,8 +53,7 @@ internal interface ExtractStep {
MetadataExtractor.new(),
TagParser.new(),
storage.cache,
- storage.storedCovers
- )
+ storage.storedCovers)
}
}
@@ -64,6 +64,7 @@ private class ExtractStepImpl(
private val cacheFactory: Cache.Factory,
private val storedCovers: MutableStoredCovers
) : ExtractStep {
+ @OptIn(ExperimentalCoroutinesApi::class)
override fun extract(nodes: Flow): Flow {
val cache = cacheFactory.open()
val addingMs = System.currentTimeMillis()
@@ -114,13 +115,13 @@ private class ExtractStepImpl(
val metadata =
fds.mapNotNull { fileWith ->
- wrap(fileWith.file) { _ ->
- metadataExtractor
- .extract(fileWith.with)
- ?.let { FileWith(fileWith.file, it) }
- .also { withContext(Dispatchers.IO) { fileWith.with.close() } }
+ wrap(fileWith.file) { _ ->
+ metadataExtractor
+ .extract(fileWith.with)
+ ?.let { FileWith(fileWith.file, it) }
+ .also { withContext(Dispatchers.IO) { fileWith.with.close() } }
+ }
}
- }
.flowOn(Dispatchers.IO)
// Covers are pretty big, so cap the amount of parsed metadata in-memory to at most
// 8 to minimize GCs.
@@ -150,19 +151,17 @@ private class ExtractStepImpl(
}
.flattenMerge()
- val merged = merge(
- filterFlow.manager,
- readDistributedFlow.manager,
- cacheFlow.manager,
- cachedSongs,
- writeDistributedFlow.manager,
- writtenSongs,
- playlistNodes
- )
+ val merged =
+ merge(
+ filterFlow.manager,
+ readDistributedFlow.manager,
+ cacheFlow.manager,
+ cachedSongs,
+ writeDistributedFlow.manager,
+ writtenSongs,
+ playlistNodes)
- return merged.onCompletion {
- cache.finalize()
- }
+ return merged.onCompletion { cache.finalize() }
}
private data class FileWith(val file: DeviceFile, val with: T)
diff --git a/musikr/src/main/java/org/oxycblt/musikr/tag/interpret/PreMusic.kt b/musikr/src/main/java/org/oxycblt/musikr/tag/interpret/PreMusic.kt
index ba6c28da4..413f351a9 100644
--- a/musikr/src/main/java/org/oxycblt/musikr/tag/interpret/PreMusic.kt
+++ b/musikr/src/main/java/org/oxycblt/musikr/tag/interpret/PreMusic.kt
@@ -15,7 +15,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
-
+
package org.oxycblt.musikr.tag.interpret
import android.net.Uri
@@ -53,21 +53,22 @@ internal data class PreSong(
val preArtists: List,
val preGenres: List
) {
- val uid = musicBrainzId?.let { Music.UID.musicBrainz(Music.UID.Item.SONG, it) }
- ?: Music.UID.auxio(Music.UID.Item.SONG) {
- // Song UIDs are based on the raw data without parsing so that they remain
- // consistent across music setting changes. Parents are not held up to the
- // same standard since grouping is already inherently linked to settings.
- update(rawName)
- update(preAlbum.rawName)
- update(date)
+ val uid =
+ musicBrainzId?.let { Music.UID.musicBrainz(Music.UID.Item.SONG, it) }
+ ?: Music.UID.auxio(Music.UID.Item.SONG) {
+ // Song UIDs are based on the raw data without parsing so that they remain
+ // consistent across music setting changes. Parents are not held up to the
+ // same standard since grouping is already inherently linked to settings.
+ update(rawName)
+ update(preAlbum.rawName)
+ update(date)
- update(track)
- update(disc?.number)
+ update(track)
+ update(disc?.number)
- update(preArtists.map { artist -> artist.rawName })
- update(preAlbum.preArtists.map { artist -> artist.rawName })
- }
+ update(preArtists.map { artist -> artist.rawName })
+ update(preAlbum.preArtists.map { artist -> artist.rawName })
+ }
}
internal data class PreAlbum(