diff --git a/musikr/src/main/java/org/oxycblt/musikr/Music.kt b/musikr/src/main/java/org/oxycblt/musikr/Music.kt index 5f5eea035..48d3c16e7 100644 --- a/musikr/src/main/java/org/oxycblt/musikr/Music.kt +++ b/musikr/src/main/java/org/oxycblt/musikr/Music.kt @@ -94,7 +94,7 @@ sealed interface Music { override fun toString() = "${format.namespace}:${item.intCode.toString(16)}-$uuid" - enum class Item(val intCode: Int) { + internal enum class Item(val intCode: Int) { // Item used to be MusicType back when the music module was // part of Auxio, so these old integer codes remain. // TODO: Introduce new UID format that removes these. @@ -126,7 +126,7 @@ sealed interface Music { @TypeConverter fun toMusicUid(string: String?) = string?.let(Companion::fromString) } - companion object { + internal companion object { /** * Creates an Auxio-style [UID] of random composition. Used if there is no * non-subjective, unlikely-to-change metadata of the music. diff --git a/musikr/src/main/java/org/oxycblt/musikr/Musikr.kt b/musikr/src/main/java/org/oxycblt/musikr/Musikr.kt index df3758d6a..4828b522e 100644 --- a/musikr/src/main/java/org/oxycblt/musikr/Musikr.kt +++ b/musikr/src/main/java/org/oxycblt/musikr/Musikr.kt @@ -55,7 +55,7 @@ sealed interface IndexingProgress { data object Indeterminate : IndexingProgress } -class MusikrImpl( +private class MusikrImpl( private val exploreStep: ExploreStep, private val extractStep: ExtractStep, private val evaluateStep: EvaluateStep diff --git a/musikr/src/main/java/org/oxycblt/musikr/cache/Cache.kt b/musikr/src/main/java/org/oxycblt/musikr/cache/Cache.kt index 0c286645b..89639a33c 100644 --- a/musikr/src/main/java/org/oxycblt/musikr/cache/Cache.kt +++ b/musikr/src/main/java/org/oxycblt/musikr/cache/Cache.kt @@ -18,7 +18,7 @@ package org.oxycblt.musikr.cache -import org.oxycblt.musikr.fs.query.DeviceFile +import org.oxycblt.musikr.fs.DeviceFile import org.oxycblt.musikr.pipeline.RawSong interface Cache { 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 07a3d069a..bdd804241 100644 --- a/musikr/src/main/java/org/oxycblt/musikr/cache/CacheDatabase.kt +++ b/musikr/src/main/java/org/oxycblt/musikr/cache/CacheDatabase.kt @@ -31,7 +31,7 @@ import androidx.room.RoomDatabase import androidx.room.TypeConverter import androidx.room.TypeConverters import org.oxycblt.musikr.cover.Cover -import org.oxycblt.musikr.fs.query.DeviceFile +import org.oxycblt.musikr.fs.DeviceFile import org.oxycblt.musikr.metadata.Properties import org.oxycblt.musikr.pipeline.RawSong import org.oxycblt.musikr.tag.Date diff --git a/musikr/src/main/java/org/oxycblt/musikr/cover/CoverIdentifier.kt b/musikr/src/main/java/org/oxycblt/musikr/cover/CoverIdentifier.kt index ef0917e05..7fa3b50fc 100644 --- a/musikr/src/main/java/org/oxycblt/musikr/cover/CoverIdentifier.kt +++ b/musikr/src/main/java/org/oxycblt/musikr/cover/CoverIdentifier.kt @@ -20,7 +20,7 @@ package org.oxycblt.musikr.cover import java.security.MessageDigest -interface CoverIdentifier { +internal interface CoverIdentifier { suspend fun identify(data: ByteArray): String companion object { diff --git a/musikr/src/main/java/org/oxycblt/musikr/fs/DeviceFile.kt b/musikr/src/main/java/org/oxycblt/musikr/fs/DeviceFile.kt new file mode 100644 index 000000000..32a58450f --- /dev/null +++ b/musikr/src/main/java/org/oxycblt/musikr/fs/DeviceFile.kt @@ -0,0 +1,11 @@ +package org.oxycblt.musikr.fs + +import android.net.Uri + +data class DeviceFile( + val uri: Uri, + val mimeType: String, + val path: Path, + val size: Long, + val lastModified: Long +) \ No newline at end of file diff --git a/musikr/src/main/java/org/oxycblt/musikr/fs/Format.kt b/musikr/src/main/java/org/oxycblt/musikr/fs/Format.kt index 3652a80df..113bd3583 100644 --- a/musikr/src/main/java/org/oxycblt/musikr/fs/Format.kt +++ b/musikr/src/main/java/org/oxycblt/musikr/fs/Format.kt @@ -84,7 +84,7 @@ sealed interface Format { "audio/wave" to Wav, ) - fun infer(containerMimeType: String, codecMimeType: String): Format { + internal fun infer(containerMimeType: String, codecMimeType: String): Format { val codecFormat = CODEC_MAP[codecMimeType] if (codecFormat != null) { // Codec found, possibly wrap in container. diff --git a/musikr/src/main/java/org/oxycblt/musikr/fs/MusicLocation.kt b/musikr/src/main/java/org/oxycblt/musikr/fs/MusicLocation.kt index d1e5e6235..87c6802af 100644 --- a/musikr/src/main/java/org/oxycblt/musikr/fs/MusicLocation.kt +++ b/musikr/src/main/java/org/oxycblt/musikr/fs/MusicLocation.kt @@ -26,7 +26,7 @@ import org.oxycblt.musikr.fs.path.DocumentPathFactory import org.oxycblt.musikr.fs.query.contentResolverSafe import org.oxycblt.musikr.util.splitEscaped -class MusicLocation internal constructor(val uri: Uri, val path: Path) { +class MusicLocation private constructor(internal val uri: Uri, internal val path: Path) { override fun equals(other: Any?) = other is MusicLocation && uri == other.uri override fun hashCode() = 31 * uri.hashCode() diff --git a/musikr/src/main/java/org/oxycblt/musikr/fs/Path.kt b/musikr/src/main/java/org/oxycblt/musikr/fs/Path.kt index 731ea5847..ef6252294 100644 --- a/musikr/src/main/java/org/oxycblt/musikr/fs/Path.kt +++ b/musikr/src/main/java/org/oxycblt/musikr/fs/Path.kt @@ -47,14 +47,14 @@ data class Path( * @param fileName The name of the file to append to the path. * @return The new [Path] instance. */ - fun file(fileName: String) = Path(volume, components.child(fileName)) + internal fun file(fileName: String) = Path(volume, components.child(fileName)) /** * Resolves the [Path] in a human-readable format. * * @param context [Context] required to obtain human-readable strings. */ - fun resolve(context: Context) = "${volume.resolveName(context)}/$components" + internal fun resolve(context: Context) = "${volume.resolveName(context)}/$components" } sealed interface Volume { @@ -154,9 +154,7 @@ value class Components private constructor(val components: List) { fun containing(other: Components) = Components(other.components.drop(components.size)) - companion object { - fun nil() = Components(listOf()) - + internal companion object { /** * Parses a path string into a [Components] instance by the unix path separator (/). * diff --git a/musikr/src/main/java/org/oxycblt/musikr/fs/path/DocumentPathFactory.kt b/musikr/src/main/java/org/oxycblt/musikr/fs/path/DocumentPathFactory.kt index 60582fb02..de1cb6a28 100644 --- a/musikr/src/main/java/org/oxycblt/musikr/fs/path/DocumentPathFactory.kt +++ b/musikr/src/main/java/org/oxycblt/musikr/fs/path/DocumentPathFactory.kt @@ -34,7 +34,7 @@ import org.oxycblt.musikr.fs.query.useQuery * * @author Alexander Capehart (OxygenCobalt) */ -interface DocumentPathFactory { +internal interface DocumentPathFactory { /** * Unpacks a document URI into a [Path] instance, using [fromDocumentId]. * diff --git a/musikr/src/main/java/org/oxycblt/musikr/fs/path/MediaStorePathInterpreter.kt b/musikr/src/main/java/org/oxycblt/musikr/fs/path/MediaStorePathInterpreter.kt index 59e14f111..d62d1cb45 100644 --- a/musikr/src/main/java/org/oxycblt/musikr/fs/path/MediaStorePathInterpreter.kt +++ b/musikr/src/main/java/org/oxycblt/musikr/fs/path/MediaStorePathInterpreter.kt @@ -29,7 +29,7 @@ import org.oxycblt.musikr.fs.Path * * @author Alexander Capehart (OxygenCobalt) */ -sealed interface MediaStorePathInterpreter { +internal sealed interface MediaStorePathInterpreter { /** * Extract a [Path] from the wrapped [Cursor]. This should be called after the cursor has been * moved to the row that should be interpreted. diff --git a/musikr/src/main/java/org/oxycblt/musikr/fs/path/VolumeCompat.kt b/musikr/src/main/java/org/oxycblt/musikr/fs/path/VolumeCompat.kt index ea3ed43db..2c0b87453 100644 --- a/musikr/src/main/java/org/oxycblt/musikr/fs/path/VolumeCompat.kt +++ b/musikr/src/main/java/org/oxycblt/musikr/fs/path/VolumeCompat.kt @@ -46,7 +46,7 @@ private val svApi21GetPathMethod: Method by lazyReflectedMethod(StorageVolume::c * * @see StorageManager.getStorageVolumes */ -val StorageManager.storageVolumesCompat: List +internal val StorageManager.storageVolumesCompat: List get() = storageVolumes.toList() /** @@ -55,7 +55,7 @@ val StorageManager.storageVolumesCompat: List * * @see StorageVolume.getDirectory */ -val StorageVolume.directoryCompat: String? +internal val StorageVolume.directoryCompat: String? @SuppressLint("NewApi") get() = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { @@ -76,7 +76,7 @@ val StorageVolume.directoryCompat: String? * @return A human-readable name for this volume. */ @SuppressLint("NewApi") -fun StorageVolume.getDescriptionCompat(context: Context): String = getDescription(context) +internal fun StorageVolume.getDescriptionCompat(context: Context): String = getDescription(context) /** * If this [StorageVolume] is considered the "Primary" volume where the Android System is kept. May @@ -84,7 +84,7 @@ fun StorageVolume.getDescriptionCompat(context: Context): String = getDescriptio * * @see StorageVolume.isPrimary */ -val StorageVolume.isPrimaryCompat: Boolean +internal val StorageVolume.isPrimaryCompat: Boolean @SuppressLint("NewApi") get() = isPrimary /** @@ -93,14 +93,14 @@ val StorageVolume.isPrimaryCompat: Boolean * * @see StorageVolume.isEmulated */ -val StorageVolume.isEmulatedCompat: Boolean +internal val StorageVolume.isEmulatedCompat: Boolean @SuppressLint("NewApi") get() = isEmulated /** * If this [StorageVolume] represents the "Internal Shared Storage" volume, also known as "primary" * to [MediaStore] and Document [Uri]s, obtained in a version compatible manner. */ -val StorageVolume.isInternalCompat: Boolean +internal val StorageVolume.isInternalCompat: Boolean // Must contain the android system AND be an emulated drive, as non-emulated system // volumes use their UUID instead of primary in MediaStore/Document URIs. get() = isPrimaryCompat && isEmulatedCompat @@ -111,7 +111,7 @@ val StorageVolume.isInternalCompat: Boolean * * @see StorageVolume.getUuid */ -val StorageVolume.uuidCompat: String? +internal val StorageVolume.uuidCompat: String? @SuppressLint("NewApi") get() = uuid /** @@ -120,7 +120,7 @@ val StorageVolume.uuidCompat: String? * * @see StorageVolume.getState */ -val StorageVolume.stateCompat: String +internal val StorageVolume.stateCompat: String @SuppressLint("NewApi") get() = state /** @@ -129,7 +129,7 @@ val StorageVolume.stateCompat: String * * @see StorageVolume.getMediaStoreVolumeName */ -val StorageVolume.mediaStoreVolumeNameCompat: String? +internal val StorageVolume.mediaStoreVolumeNameCompat: String? get() = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { mediaStoreVolumeName diff --git a/musikr/src/main/java/org/oxycblt/musikr/fs/path/VolumeManager.kt b/musikr/src/main/java/org/oxycblt/musikr/fs/path/VolumeManager.kt index bfc1325ef..3e67ef5f7 100644 --- a/musikr/src/main/java/org/oxycblt/musikr/fs/path/VolumeManager.kt +++ b/musikr/src/main/java/org/oxycblt/musikr/fs/path/VolumeManager.kt @@ -25,7 +25,7 @@ import org.oxycblt.musikr.fs.Components import org.oxycblt.musikr.fs.Volume /** A wrapper around [StorageManager] that provides instances of the [Volume] interface. */ -interface VolumeManager { +internal interface VolumeManager { /** * The internal storage volume of the device. * diff --git a/musikr/src/main/java/org/oxycblt/musikr/fs/query/DeviceFiles.kt b/musikr/src/main/java/org/oxycblt/musikr/fs/query/DeviceFiles.kt index 6edd4fe68..596801551 100644 --- a/musikr/src/main/java/org/oxycblt/musikr/fs/query/DeviceFiles.kt +++ b/musikr/src/main/java/org/oxycblt/musikr/fs/query/DeviceFiles.kt @@ -29,10 +29,11 @@ import kotlinx.coroutines.flow.emitAll import kotlinx.coroutines.flow.flatMapMerge import kotlinx.coroutines.flow.flattenMerge import kotlinx.coroutines.flow.flow +import org.oxycblt.musikr.fs.DeviceFile import org.oxycblt.musikr.fs.MusicLocation import org.oxycblt.musikr.fs.Path -interface DeviceFiles { +internal interface DeviceFiles { fun explore(locations: Flow): Flow companion object { @@ -40,14 +41,6 @@ interface DeviceFiles { } } -data class DeviceFile( - val uri: Uri, - val mimeType: String, - val path: Path, - val size: Long, - val lastModified: Long -) - @OptIn(ExperimentalCoroutinesApi::class) private class DeviceFilesImpl(private val contentResolver: ContentResolver) : DeviceFiles { override fun explore(locations: Flow): Flow = @@ -99,7 +92,8 @@ private class DeviceFilesImpl(private val contentResolver: ContentResolver) : De mimeType, newPath, size, - lastModified)) + lastModified) + ) } } emitAll(recursive.asFlow().flattenMerge()) diff --git a/musikr/src/main/java/org/oxycblt/musikr/fs/query/QueryUtil.kt b/musikr/src/main/java/org/oxycblt/musikr/fs/query/QueryUtil.kt index 15b139506..14a05edc4 100644 --- a/musikr/src/main/java/org/oxycblt/musikr/fs/query/QueryUtil.kt +++ b/musikr/src/main/java/org/oxycblt/musikr/fs/query/QueryUtil.kt @@ -27,7 +27,7 @@ import android.net.Uri * Get a content resolver that will not mangle MediaStore queries on certain devices. See * https://github.com/OxygenCobalt/Auxio/issues/50 for more info. */ -val Context.contentResolverSafe: ContentResolver +internal val Context.contentResolverSafe: ContentResolver get() = applicationContext.contentResolver /** @@ -42,7 +42,7 @@ val Context.contentResolverSafe: ContentResolver * @throws IllegalStateException If the [ContentResolver] did not return the queried [Cursor]. * @see ContentResolver.query */ -fun ContentResolver.safeQuery( +internal fun ContentResolver.safeQuery( uri: Uri, projection: Array, selector: String? = null, @@ -63,7 +63,7 @@ fun ContentResolver.safeQuery( * @throws IllegalStateException If the [ContentResolver] did not return the queried [Cursor]. * @see ContentResolver.query */ -inline fun ContentResolver.useQuery( +internal inline fun ContentResolver.useQuery( uri: Uri, projection: Array, selector: String? = null, diff --git a/musikr/src/main/java/org/oxycblt/musikr/graph/MusicGraph.kt b/musikr/src/main/java/org/oxycblt/musikr/graph/MusicGraph.kt index 3aaed1d23..6b93c3dff 100644 --- a/musikr/src/main/java/org/oxycblt/musikr/graph/MusicGraph.kt +++ b/musikr/src/main/java/org/oxycblt/musikr/graph/MusicGraph.kt @@ -25,7 +25,7 @@ import org.oxycblt.musikr.tag.interpret.PreGenre import org.oxycblt.musikr.tag.interpret.PreSong import org.oxycblt.musikr.util.unlikelyToBeNull -data class MusicGraph( +internal data class MusicGraph( val songVertex: List, val albumVertex: List, val artistVertex: List, @@ -274,7 +274,7 @@ private class MusicGraphBuilderImpl : MusicGraph.Builder { } } -class SongVertex( +internal class SongVertex( val preSong: PreSong, var albumVertex: AlbumVertex, var artistVertices: MutableList, @@ -283,12 +283,12 @@ class SongVertex( var tag: Any? = null } -class AlbumVertex(val preAlbum: PreAlbum, var artistVertices: MutableList) { +internal class AlbumVertex(val preAlbum: PreAlbum, var artistVertices: MutableList) { val songVertices = mutableSetOf() var tag: Any? = null } -class ArtistVertex( +internal class ArtistVertex( val preArtist: PreArtist, ) { val songVertices = mutableSetOf() @@ -297,7 +297,7 @@ class ArtistVertex( var tag: Any? = null } -class GenreVertex(val preGenre: PreGenre) { +internal class GenreVertex(val preGenre: PreGenre) { val songVertices = mutableSetOf() val artistVertices = mutableSetOf() var tag: Any? = null diff --git a/musikr/src/main/java/org/oxycblt/musikr/metadata/AndroidInputStream.kt b/musikr/src/main/java/org/oxycblt/musikr/metadata/AndroidInputStream.kt index 03c6d1c83..1de192024 100644 --- a/musikr/src/main/java/org/oxycblt/musikr/metadata/AndroidInputStream.kt +++ b/musikr/src/main/java/org/oxycblt/musikr/metadata/AndroidInputStream.kt @@ -22,7 +22,7 @@ import android.content.Context import java.io.FileInputStream import java.nio.ByteBuffer -class AndroidInputStream(context: Context, fileRef: FileRef) : NativeInputStream { +internal class AndroidInputStream(context: Context, fileRef: FileRef) : NativeInputStream { private val fileName = fileRef.fileName private val fd = requireNotNull(context.contentResolver.openFileDescriptor(fileRef.uri, "r")) { diff --git a/musikr/src/main/java/org/oxycblt/musikr/metadata/Metadata.kt b/musikr/src/main/java/org/oxycblt/musikr/metadata/Metadata.kt new file mode 100644 index 000000000..ab034844e --- /dev/null +++ b/musikr/src/main/java/org/oxycblt/musikr/metadata/Metadata.kt @@ -0,0 +1,43 @@ +package org.oxycblt.musikr.metadata + +internal data class Metadata( + val id3v2: Map>, + val xiph: Map>, + val mp4: Map>, + val cover: ByteArray?, + val properties: Properties +) { + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (javaClass != other?.javaClass) return false + + other as Metadata + + if (id3v2 != other.id3v2) return false + if (xiph != other.xiph) return false + if (mp4 != other.mp4) return false + if (cover != null) { + if (other.cover == null) return false + if (!cover.contentEquals(other.cover)) return false + } else if (other.cover != null) return false + if (properties != other.properties) return false + + return true + } + + override fun hashCode(): Int { + var result = id3v2.hashCode() + result = 31 * result + xiph.hashCode() + result = 31 * result + mp4.hashCode() + result = 31 * result + (cover?.contentHashCode() ?: 0) + result = 31 * result + properties.hashCode() + return result + } +} + +data class Properties( + val mimeType: String, + val durationMs: Long, + val bitrate: Int, + val sampleRate: Int, +) diff --git a/musikr/src/main/java/org/oxycblt/musikr/metadata/MetadataExtractor.kt b/musikr/src/main/java/org/oxycblt/musikr/metadata/MetadataExtractor.kt index 40d572fb8..59d1b0c7d 100644 --- a/musikr/src/main/java/org/oxycblt/musikr/metadata/MetadataExtractor.kt +++ b/musikr/src/main/java/org/oxycblt/musikr/metadata/MetadataExtractor.kt @@ -21,10 +21,10 @@ package org.oxycblt.musikr.metadata import android.content.Context import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext -import org.oxycblt.musikr.fs.query.DeviceFile +import org.oxycblt.musikr.fs.DeviceFile import org.oxycblt.musikr.util.unlikelyToBeNull -interface MetadataExtractor { +internal interface MetadataExtractor { suspend fun extract(file: DeviceFile): Metadata? companion object { diff --git a/musikr/src/main/java/org/oxycblt/musikr/metadata/NativeInputStream.kt b/musikr/src/main/java/org/oxycblt/musikr/metadata/NativeInputStream.kt index 66e63c454..1b2382647 100644 --- a/musikr/src/main/java/org/oxycblt/musikr/metadata/NativeInputStream.kt +++ b/musikr/src/main/java/org/oxycblt/musikr/metadata/NativeInputStream.kt @@ -23,7 +23,7 @@ package org.oxycblt.musikr.metadata * * The vast majority of IO shim between Taglib/KTaglib should occur here to minimize JNI calls. */ -interface NativeInputStream { +internal interface NativeInputStream { fun name(): String fun readBlock(length: Long): ByteArray diff --git a/musikr/src/main/java/org/oxycblt/musikr/metadata/TagLibJNI.kt b/musikr/src/main/java/org/oxycblt/musikr/metadata/TagLibJNI.kt index 45ac2be9b..12124a65d 100644 --- a/musikr/src/main/java/org/oxycblt/musikr/metadata/TagLibJNI.kt +++ b/musikr/src/main/java/org/oxycblt/musikr/metadata/TagLibJNI.kt @@ -21,7 +21,7 @@ package org.oxycblt.musikr.metadata import android.content.Context import android.net.Uri -object TagLibJNI { +internal object TagLibJNI { init { System.loadLibrary("taglib_jni") } @@ -41,46 +41,4 @@ object TagLibJNI { private external fun openNative(ioStream: AndroidInputStream): Metadata? } -data class FileRef(val fileName: String, val uri: Uri) - -data class Metadata( - val id3v2: Map>, - val xiph: Map>, - val mp4: Map>, - val cover: ByteArray?, - val properties: Properties -) { - override fun equals(other: Any?): Boolean { - if (this === other) return true - if (javaClass != other?.javaClass) return false - - other as Metadata - - if (id3v2 != other.id3v2) return false - if (xiph != other.xiph) return false - if (mp4 != other.mp4) return false - if (cover != null) { - if (other.cover == null) return false - if (!cover.contentEquals(other.cover)) return false - } else if (other.cover != null) return false - if (properties != other.properties) return false - - return true - } - - override fun hashCode(): Int { - var result = id3v2.hashCode() - result = 31 * result + xiph.hashCode() - result = 31 * result + mp4.hashCode() - result = 31 * result + (cover?.contentHashCode() ?: 0) - result = 31 * result + properties.hashCode() - return result - } -} - -data class Properties( - val mimeType: String, - val durationMs: Long, - val bitrate: Int, - val sampleRate: Int, -) +internal data class FileRef(val fileName: String, val uri: Uri) diff --git a/musikr/src/main/java/org/oxycblt/musikr/model/AlbumImpl.kt b/musikr/src/main/java/org/oxycblt/musikr/model/AlbumImpl.kt index 02148c876..19be4885c 100644 --- a/musikr/src/main/java/org/oxycblt/musikr/model/AlbumImpl.kt +++ b/musikr/src/main/java/org/oxycblt/musikr/model/AlbumImpl.kt @@ -27,7 +27,7 @@ import org.oxycblt.musikr.tag.Date import org.oxycblt.musikr.tag.interpret.PreAlbum import org.oxycblt.musikr.util.update -interface AlbumCore { +internal interface AlbumCore { val preAlbum: PreAlbum val songs: List @@ -39,7 +39,7 @@ interface AlbumCore { * * @author Alexander Capehart (OxygenCobalt) */ -class AlbumImpl(private val core: AlbumCore) : Album { +internal class AlbumImpl(private val core: AlbumCore) : Album { private val preAlbum = core.preAlbum override val uid = diff --git a/musikr/src/main/java/org/oxycblt/musikr/model/ArtistImpl.kt b/musikr/src/main/java/org/oxycblt/musikr/model/ArtistImpl.kt index f37f6c264..4a2ca3990 100644 --- a/musikr/src/main/java/org/oxycblt/musikr/model/ArtistImpl.kt +++ b/musikr/src/main/java/org/oxycblt/musikr/model/ArtistImpl.kt @@ -27,7 +27,7 @@ import org.oxycblt.musikr.cover.Cover import org.oxycblt.musikr.tag.interpret.PreArtist import org.oxycblt.musikr.util.update -interface ArtistCore { +internal interface ArtistCore { val preArtist: PreArtist val songs: Set val albums: Set @@ -40,7 +40,7 @@ interface ArtistCore { * * @author Alexander Capehart (OxygenCobalt) */ -class ArtistImpl(private val core: ArtistCore) : Artist { +internal class ArtistImpl(private val core: ArtistCore) : Artist { override val uid = // Attempt to use a MusicBrainz ID first before falling back to a hashed UID. core.preArtist.musicBrainzId?.let { Music.UID.musicBrainz(Music.UID.Item.ARTIST, it) } diff --git a/musikr/src/main/java/org/oxycblt/musikr/model/GenreImpl.kt b/musikr/src/main/java/org/oxycblt/musikr/model/GenreImpl.kt index 8fa91f4e0..cb696a696 100644 --- a/musikr/src/main/java/org/oxycblt/musikr/model/GenreImpl.kt +++ b/musikr/src/main/java/org/oxycblt/musikr/model/GenreImpl.kt @@ -26,7 +26,7 @@ import org.oxycblt.musikr.cover.Cover import org.oxycblt.musikr.tag.interpret.PreGenre import org.oxycblt.musikr.util.update -interface GenreCore { +internal interface GenreCore { val preGenre: PreGenre val songs: Set val artists: Set @@ -37,7 +37,7 @@ interface GenreCore { * * @author Alexander Capehart (OxygenCobalt) */ -class GenreImpl(private val core: GenreCore) : Genre { +internal class GenreImpl(private val core: GenreCore) : Genre { override val uid = Music.UID.auxio(Music.UID.Item.GENRE) { update(core.preGenre.rawName) } override val name = core.preGenre.name diff --git a/musikr/src/main/java/org/oxycblt/musikr/model/LibraryFactory.kt b/musikr/src/main/java/org/oxycblt/musikr/model/LibraryFactory.kt index 37d8ebc41..bdadcfc7d 100644 --- a/musikr/src/main/java/org/oxycblt/musikr/model/LibraryFactory.kt +++ b/musikr/src/main/java/org/oxycblt/musikr/model/LibraryFactory.kt @@ -29,7 +29,7 @@ import org.oxycblt.musikr.graph.GenreVertex import org.oxycblt.musikr.graph.MusicGraph import org.oxycblt.musikr.graph.SongVertex -interface LibraryFactory { +internal interface LibraryFactory { fun create(graph: MusicGraph): MutableLibrary companion object { diff --git a/musikr/src/main/java/org/oxycblt/musikr/model/LibraryImpl.kt b/musikr/src/main/java/org/oxycblt/musikr/model/LibraryImpl.kt index f3d5a08d9..3e067b57e 100644 --- a/musikr/src/main/java/org/oxycblt/musikr/model/LibraryImpl.kt +++ b/musikr/src/main/java/org/oxycblt/musikr/model/LibraryImpl.kt @@ -24,7 +24,7 @@ import org.oxycblt.musikr.Playlist import org.oxycblt.musikr.Song import org.oxycblt.musikr.fs.Path -class LibraryImpl( +internal class LibraryImpl( override val songs: Collection, override val albums: Collection, override val artists: Collection, diff --git a/musikr/src/main/java/org/oxycblt/musikr/model/PlaylistImpl.kt b/musikr/src/main/java/org/oxycblt/musikr/model/PlaylistImpl.kt index ac1e2cefe..16259b613 100644 --- a/musikr/src/main/java/org/oxycblt/musikr/model/PlaylistImpl.kt +++ b/musikr/src/main/java/org/oxycblt/musikr/model/PlaylistImpl.kt @@ -25,13 +25,13 @@ import org.oxycblt.musikr.playlist.PlaylistHandle import org.oxycblt.musikr.tag.Name import org.oxycblt.musikr.tag.interpret.PrePlaylist -interface PlaylistCore { +internal interface PlaylistCore { val prePlaylist: PrePlaylist val handle: PlaylistHandle val songs: List } -class PlaylistImpl(private val core: PlaylistCore) : Playlist { +internal class PlaylistImpl(private val core: PlaylistCore) : Playlist { override val uid = core.handle.uid override val name: Name.Known = core.prePlaylist.name override val durationMs = core.songs.sumOf { it.durationMs } diff --git a/musikr/src/main/java/org/oxycblt/musikr/model/SongImpl.kt b/musikr/src/main/java/org/oxycblt/musikr/model/SongImpl.kt index 8a49d3dda..cc9aac807 100644 --- a/musikr/src/main/java/org/oxycblt/musikr/model/SongImpl.kt +++ b/musikr/src/main/java/org/oxycblt/musikr/model/SongImpl.kt @@ -24,7 +24,7 @@ import org.oxycblt.musikr.Genre import org.oxycblt.musikr.Song import org.oxycblt.musikr.tag.interpret.PreSong -interface SongCore { +internal interface SongCore { val preSong: PreSong fun resolveAlbum(): Album @@ -39,7 +39,7 @@ interface SongCore { * * @author Alexander Capehart (OxygenCobalt) */ -class SongImpl(private val handle: SongCore) : Song { +internal class SongImpl(private val handle: SongCore) : Song { private val preSong = handle.preSong override val uid = preSong.computeUid() diff --git a/musikr/src/main/java/org/oxycblt/musikr/pipeline/EvaluateStep.kt b/musikr/src/main/java/org/oxycblt/musikr/pipeline/EvaluateStep.kt index 6dd6b5d83..fccee6ee9 100644 --- a/musikr/src/main/java/org/oxycblt/musikr/pipeline/EvaluateStep.kt +++ b/musikr/src/main/java/org/oxycblt/musikr/pipeline/EvaluateStep.kt @@ -31,7 +31,7 @@ import org.oxycblt.musikr.graph.MusicGraph import org.oxycblt.musikr.model.LibraryFactory import org.oxycblt.musikr.tag.interpret.TagInterpreter -interface EvaluateStep { +internal interface EvaluateStep { suspend fun evaluate( interpretation: Interpretation, extractedMusic: Flow diff --git a/musikr/src/main/java/org/oxycblt/musikr/pipeline/ExploreStep.kt b/musikr/src/main/java/org/oxycblt/musikr/pipeline/ExploreStep.kt index e73ca2cea..a011d3f98 100644 --- a/musikr/src/main/java/org/oxycblt/musikr/pipeline/ExploreStep.kt +++ b/musikr/src/main/java/org/oxycblt/musikr/pipeline/ExploreStep.kt @@ -25,11 +25,11 @@ import kotlinx.coroutines.flow.asFlow import kotlinx.coroutines.flow.flowOn import kotlinx.coroutines.flow.mapNotNull import org.oxycblt.musikr.fs.MusicLocation -import org.oxycblt.musikr.fs.query.DeviceFile +import org.oxycblt.musikr.fs.DeviceFile import org.oxycblt.musikr.fs.query.DeviceFiles import org.oxycblt.musikr.playlist.m3u.M3U -interface ExploreStep { +internal interface ExploreStep { fun explore(locations: List): Flow companion object { @@ -51,6 +51,6 @@ private class ExploreStepImpl(private val deviceFiles: DeviceFiles) : ExploreSte .flowOn(Dispatchers.IO) } -sealed interface ExploreNode { +internal sealed interface ExploreNode { data class Audio(val file: DeviceFile) : ExploreNode } 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 f7a1f03ac..520f07130 100644 --- a/musikr/src/main/java/org/oxycblt/musikr/pipeline/ExtractStep.kt +++ b/musikr/src/main/java/org/oxycblt/musikr/pipeline/ExtractStep.kt @@ -31,13 +31,13 @@ import kotlinx.coroutines.flow.merge import org.oxycblt.musikr.Storage import org.oxycblt.musikr.cache.CacheResult import org.oxycblt.musikr.cover.Cover -import org.oxycblt.musikr.fs.query.DeviceFile +import org.oxycblt.musikr.fs.DeviceFile import org.oxycblt.musikr.metadata.MetadataExtractor import org.oxycblt.musikr.metadata.Properties import org.oxycblt.musikr.tag.parse.ParsedTags import org.oxycblt.musikr.tag.parse.TagParser -interface ExtractStep { +internal interface ExtractStep { fun extract(storage: Storage, nodes: Flow): Flow companion object { @@ -99,6 +99,6 @@ data class RawSong( val cover: Cover.Single? ) -sealed interface ExtractedMusic { +internal sealed interface ExtractedMusic { data class Song(val song: RawSong) : ExtractedMusic } diff --git a/musikr/src/main/java/org/oxycblt/musikr/pipeline/FlowUtil.kt b/musikr/src/main/java/org/oxycblt/musikr/pipeline/FlowUtil.kt index a99c3f3c1..94d93c4c2 100644 --- a/musikr/src/main/java/org/oxycblt/musikr/pipeline/FlowUtil.kt +++ b/musikr/src/main/java/org/oxycblt/musikr/pipeline/FlowUtil.kt @@ -25,7 +25,7 @@ import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.receiveAsFlow import kotlinx.coroutines.flow.withIndex -sealed interface Divert { +internal sealed interface Divert { data class Left(val value: L) : Divert data class Right(val value: R) : Divert @@ -33,7 +33,7 @@ sealed interface Divert { class DivertedFlow(val manager: Flow, val left: Flow, val right: Flow) -inline fun Flow.divert( +internal inline fun Flow.divert( crossinline predicate: (T) -> Divert ): DivertedFlow { val leftChannel = Channel(Channel.UNLIMITED) @@ -52,7 +52,7 @@ inline fun Flow.divert( return DivertedFlow(managedFlow, leftChannel.receiveAsFlow(), rightChannel.receiveAsFlow()) } -class DistributedFlow(val manager: Flow, val flows: Array>) +internal class DistributedFlow(val manager: Flow, val flows: Array>) /** * Equally "distributes" the values of some flow across n new flows. @@ -60,7 +60,7 @@ class DistributedFlow(val manager: Flow, val flows: Array>) * Note that this function requires the "manager" flow to be consumed alongside the split flows in * order to function. Without this, all of the newly split flows will simply block. */ -fun Flow.distribute(n: Int): DistributedFlow { +internal fun Flow.distribute(n: Int): DistributedFlow { val posChannels = Array(n) { Channel(Channel.UNLIMITED) } val managerFlow = flow { diff --git a/musikr/src/main/java/org/oxycblt/musikr/playlist/ExternalPlaylistManager.kt b/musikr/src/main/java/org/oxycblt/musikr/playlist/ExternalPlaylistManager.kt index e4fe86dcc..0e6ecf179 100644 --- a/musikr/src/main/java/org/oxycblt/musikr/playlist/ExternalPlaylistManager.kt +++ b/musikr/src/main/java/org/oxycblt/musikr/playlist/ExternalPlaylistManager.kt @@ -84,7 +84,7 @@ data class ImportedPlaylist(val name: String?, val paths: List) typealias PossiblePaths = List -class ExternalPlaylistManagerImpl( +private class ExternalPlaylistManagerImpl( private val context: Context, private val documentPathFactory: DocumentPathFactory, private val m3u: M3U diff --git a/musikr/src/main/java/org/oxycblt/musikr/tag/format/ID3.kt b/musikr/src/main/java/org/oxycblt/musikr/tag/format/ID3.kt index 3712fc166..4e9390711 100644 --- a/musikr/src/main/java/org/oxycblt/musikr/tag/format/ID3.kt +++ b/musikr/src/main/java/org/oxycblt/musikr/tag/format/ID3.kt @@ -28,7 +28,7 @@ package org.oxycblt.musikr.tag.format * @return A list of one or more genre names, or null if this multi-value list has no valid * formatting. */ -fun List.parseId3GenreNames() = +internal fun List.parseId3GenreNames() = if (size == 1) { first().parseId3MultiValueGenre() } else { diff --git a/musikr/src/main/java/org/oxycblt/musikr/tag/format/Vorbis.kt b/musikr/src/main/java/org/oxycblt/musikr/tag/format/Vorbis.kt index 05c3e2793..51e58ce70 100644 --- a/musikr/src/main/java/org/oxycblt/musikr/tag/format/Vorbis.kt +++ b/musikr/src/main/java/org/oxycblt/musikr/tag/format/Vorbis.kt @@ -30,7 +30,7 @@ import org.oxycblt.musikr.util.positiveOrNull * * @see transformPositionField */ -fun String.parseId3v2PositionField() = +internal fun String.parseId3v2PositionField() = split('/', limit = 2).let { transformPositionField(it[0].toIntOrNull(), it.getOrNull(1)?.toIntOrNull()) } @@ -47,7 +47,7 @@ fun String.parseId3v2PositionField() = * * @see transformPositionField */ -fun parseXiphPositionField(pos: String?, total: String?) = +internal fun parseXiphPositionField(pos: String?, total: String?) = transformPositionField(pos?.toIntOrNull(), total?.toIntOrNull()) /** @@ -59,7 +59,7 @@ fun parseXiphPositionField(pos: String?, total: String?) = * - The position could not be parsed * - The position was zeroed AND the total value was not present/zeroed */ -fun transformPositionField(pos: Int?, total: Int?) = +internal fun transformPositionField(pos: Int?, total: Int?) = if (pos != null && (pos > 0 || (total?.positiveOrNull() != null))) { pos } else { 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 8da604f6a..b977fa562 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 @@ -32,7 +32,7 @@ import org.oxycblt.musikr.tag.ReleaseType import org.oxycblt.musikr.tag.ReplayGainAdjustment import org.oxycblt.musikr.util.update -data class PreSong( +internal data class PreSong( val musicBrainzId: UUID?, val name: Name.Known, val rawName: String, @@ -70,7 +70,7 @@ data class PreSong( } } -data class PreAlbum( +internal data class PreAlbum( val musicBrainzId: UUID?, val name: Name, val rawName: String?, @@ -78,11 +78,11 @@ data class PreAlbum( val preArtists: List ) -data class PreArtist(val musicBrainzId: UUID?, val name: Name, val rawName: String?) +internal data class PreArtist(val musicBrainzId: UUID?, val name: Name, val rawName: String?) -data class PreGenre( +internal data class PreGenre( val name: Name, val rawName: String?, ) -data class PrePlaylist(val name: Name.Known, val rawName: String?, val handle: PlaylistHandle) +internal data class PrePlaylist(val name: Name.Known, val rawName: String?, val handle: PlaylistHandle) diff --git a/musikr/src/main/java/org/oxycblt/musikr/tag/interpret/TagInterpreter.kt b/musikr/src/main/java/org/oxycblt/musikr/tag/interpret/TagInterpreter.kt index 89de7fd62..44d1448b3 100644 --- a/musikr/src/main/java/org/oxycblt/musikr/tag/interpret/TagInterpreter.kt +++ b/musikr/src/main/java/org/oxycblt/musikr/tag/interpret/TagInterpreter.kt @@ -30,7 +30,7 @@ import org.oxycblt.musikr.tag.parse.ParsedTags import org.oxycblt.musikr.tag.format.parseId3GenreNames import org.oxycblt.musikr.util.toUuidOrNull -interface TagInterpreter { +internal interface TagInterpreter { fun interpret(song: RawSong, interpretation: Interpretation): PreSong companion object { diff --git a/musikr/src/main/java/org/oxycblt/musikr/tag/interpret/Token.kt b/musikr/src/main/java/org/oxycblt/musikr/tag/interpret/Token.kt index 749b6c5e5..c09ba3521 100644 --- a/musikr/src/main/java/org/oxycblt/musikr/tag/interpret/Token.kt +++ b/musikr/src/main/java/org/oxycblt/musikr/tag/interpret/Token.kt @@ -21,7 +21,9 @@ package org.oxycblt.musikr.tag.interpret import java.text.CollationKey /** An individual part of a name string that can be compared intelligently. */ -data class Token(val collationKey: CollationKey, val type: Type) : Comparable { +data class Token(internal val collationKey: CollationKey, internal val type: Type) : Comparable { + val value: String get() = collationKey.sourceString + override fun compareTo(other: Token): Int { // Numeric tokens should always be lower than lexicographic tokens. val modeComp = type.compareTo(other.type) diff --git a/musikr/src/main/java/org/oxycblt/musikr/tag/parse/ExoPlayerTagFields.kt b/musikr/src/main/java/org/oxycblt/musikr/tag/parse/TagFields.kt similarity index 87% rename from musikr/src/main/java/org/oxycblt/musikr/tag/parse/ExoPlayerTagFields.kt rename to musikr/src/main/java/org/oxycblt/musikr/tag/parse/TagFields.kt index 23ea14a18..a35ed1205 100644 --- a/musikr/src/main/java/org/oxycblt/musikr/tag/parse/ExoPlayerTagFields.kt +++ b/musikr/src/main/java/org/oxycblt/musikr/tag/parse/TagFields.kt @@ -1,6 +1,6 @@ /* * Copyright (c) 2024 Auxio Project - * ExoPlayerTagFields.kt is part of Auxio. + * TagFields.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 @@ -26,32 +26,32 @@ import org.oxycblt.musikr.tag.format.parseXiphPositionField import org.oxycblt.musikr.util.nonZeroOrNull // Song -fun Metadata.musicBrainzId() = +internal fun Metadata.musicBrainzId() = (xiph["MUSICBRAINZ_RELEASETRACKID"] ?: xiph["MUSICBRAINZ RELEASE TRACK ID"] ?: id3v2["TXXX:MUSICBRAINZ RELEASE TRACK ID"] ?: id3v2["TXXX:MUSICBRAINZ_RELEASETRACKID"]) ?.first() -fun Metadata.name() = (xiph["TITLE"] ?: id3v2["TIT2"])?.first() +internal fun Metadata.name() = (xiph["TITLE"] ?: id3v2["TIT2"])?.first() -fun Metadata.sortName() = (xiph["TITLESORT"] ?: id3v2["TSOT"])?.first() +internal fun Metadata.sortName() = (xiph["TITLESORT"] ?: id3v2["TSOT"])?.first() // Track. -fun Metadata.track() = +internal fun Metadata.track() = (parseXiphPositionField( xiph["TRACKNUMBER"]?.first(), (xiph["TOTALTRACKS"] ?: xiph["TRACKTOTAL"] ?: xiph["TRACKC"])?.first()) ?: id3v2["TRCK"]?.run { first().parseId3v2PositionField() }) // Disc and it's subtitle name. -fun Metadata.disc() = +internal fun Metadata.disc() = (parseXiphPositionField( xiph["DISCNUMBER"]?.first(), (xiph["TOTALDISCS"] ?: xiph["DISCTOTAL"] ?: xiph["DISCC"])?.run { first() }) ?: id3v2["TPOS"]?.run { first().parseId3v2PositionField() }) -fun Metadata.subtitle() = (xiph["DISCSUBTITLE"] ?: id3v2["TSST"])?.first() +internal fun Metadata.subtitle() = (xiph["DISCSUBTITLE"] ?: id3v2["TSST"])?.first() // Dates are somewhat complicated, as not only did their semantics change from a flat year // value in ID3v2.3 to a full ISO-8601 date in ID3v2.4, but there are also a variety of @@ -65,7 +65,7 @@ fun Metadata.subtitle() = (xiph["DISCSUBTITLE"] ?: id3v2["TSST"])?.first() // TODO: Show original and normal dates side-by-side // TODO: Handle dates that are in "January" because the actual specific release date // isn't known? -fun Metadata.date() = +internal fun Metadata.date() = (xiph["ORIGINALDATE"]?.run { Date.from(first()) } ?: xiph["DATE"]?.run { Date.from(first()) } ?: xiph["YEAR"]?.run { Date.from(first()) } @@ -83,18 +83,18 @@ fun Metadata.date() = ?: parseId3v23Date()) // Album -fun Metadata.albumMusicBrainzId() = +internal fun Metadata.albumMusicBrainzId() = (xiph["MUSICBRAINZ_ALBUMID"] ?: xiph["MUSICBRAINZ ALBUM ID"] ?: id3v2["TXXX:MUSICBRAINZ ALBUM ID"] ?: id3v2["TXXX:MUSICBRAINZ_ALBUMID"]) ?.first() -fun Metadata.albumName() = (xiph["ALBUM"] ?: id3v2["TALB"])?.first() +internal fun Metadata.albumName() = (xiph["ALBUM"] ?: id3v2["TALB"])?.first() -fun Metadata.albumSortName() = (xiph["ALBUMSORT"] ?: id3v2["TSOA"])?.first() +internal fun Metadata.albumSortName() = (xiph["ALBUMSORT"] ?: id3v2["TSOA"])?.first() -fun Metadata.releaseTypes() = +internal fun Metadata.releaseTypes() = (xiph["RELEASETYPE"] ?: xiph["MUSICBRAINZ ALBUM TYPE"] ?: id3v2["TXXX:MUSICBRAINZ ALBUM TYPE"] @@ -104,20 +104,20 @@ fun Metadata.releaseTypes() = id3v2["GRP1"]) // Artist -fun Metadata.artistMusicBrainzIds() = +internal fun Metadata.artistMusicBrainzIds() = (xiph["MUSICBRAINZ_ARTISTID"] ?: xiph["MUSICBRAINZ ARTIST ID"] ?: id3v2["TXXX:MUSICBRAINZ ARTIST ID"] ?: id3v2["TXXX:MUSICBRAINZ_ARTISTID"]) -fun Metadata.artistNames() = +internal fun Metadata.artistNames() = (xiph["ARTISTS"] ?: xiph["ARTIST"] ?: id3v2["TXXX:ARTISTS"] ?: id3v2["TPE1"] ?: id3v2["TXXX:ARTIST"]) -fun Metadata.artistSortNames() = +internal fun Metadata.artistSortNames() = (xiph["ARTISTSSORT"] ?: xiph["ARTISTS_SORT"] ?: xiph["ARTISTS SORT"] @@ -130,13 +130,13 @@ fun Metadata.artistSortNames() = ?: id3v2["TXXX:ARTISTSORT"] ?: id3v2["TXXX:ARTIST SORT"]) -fun Metadata.albumArtistMusicBrainzIds() = +internal fun Metadata.albumArtistMusicBrainzIds() = (xiph["MUSICBRAINZ_ALBUMARTISTID"] ?: xiph["MUSICBRAINZ ALBUM ARTIST ID"] ?: id3v2["TXXX:MUSICBRAINZ ALBUM ARTIST ID"] ?: id3v2["TXXX:MUSICBRAINZ_ALBUMARTISTID"]) -fun Metadata.albumArtistNames() = +internal fun Metadata.albumArtistNames() = (xiph["ALBUMARTISTS"] ?: xiph["ALBUM_ARTISTS"] ?: xiph["ALBUM ARTISTS"] @@ -149,7 +149,7 @@ fun Metadata.albumArtistNames() = ?: id3v2["TXXX:ALBUMARTIST"] ?: id3v2["TXXX:ALBUM ARTIST"]) -fun Metadata.albumArtistSortNames() = +internal fun Metadata.albumArtistSortNames() = (xiph["ALBUMARTISTSSORT"] ?: xiph["ALBUMARTISTS_SORT"] ?: xiph["ALBUMARTISTS SORT"] @@ -164,10 +164,10 @@ fun Metadata.albumArtistSortNames() = ?: id3v2["TXXX:ALBUM ARTIST SORT"]) // Genre -fun Metadata.genreNames() = xiph["GENRE"] ?: id3v2["TCON"] +internal fun Metadata.genreNames() = xiph["GENRE"] ?: id3v2["TCON"] // Compilation Flag -fun Metadata.isCompilation() = +internal fun Metadata.isCompilation() = (xiph["COMPILATION"] ?: xiph["ITUNESCOMPILATION"] ?: id3v2["TCMP"] // This is a non-standard itunes extension @@ -179,16 +179,36 @@ fun Metadata.isCompilation() = } // ReplayGain information -fun Metadata.replayGainTrackAdjustment() = +internal fun Metadata.replayGainTrackAdjustment() = (xiph["R128_TRACK_GAIN"]?.parseR128Adjustment() ?: xiph["REPLAYGAIN_TRACK_GAIN"]?.parseReplayGainAdjustment() ?: id3v2["TXXX:REPLAYGAIN_TRACK_GAIN"]?.parseReplayGainAdjustment()) -fun Metadata.replayGainAlbumAdjustment() = +internal fun Metadata.replayGainAlbumAdjustment() = (xiph["R128_ALBUM_GAIN"]?.parseR128Adjustment() ?: xiph["REPLAYGAIN_ALBUM_GAIN"]?.parseReplayGainAdjustment() ?: id3v2["TXXX:REPLAYGAIN_ALBUM_GAIN"]?.parseReplayGainAdjustment()) +private fun List.parseR128Adjustment() = + first().replace(REPLAYGAIN_ADJUSTMENT_FILTER_REGEX, "").toFloatOrNull()?.nonZeroOrNull()?.run { + // Convert to fixed-point and adjust to LUFS 18 to match the ReplayGain scale + this / 256f + 5 + } + +/** + * Parse a ReplayGain adjustment into a float value. + * + * @return A parsed adjustment float, or null if the adjustment had invalid formatting. + */ +private fun List.parseReplayGainAdjustment() = + first().replace(REPLAYGAIN_ADJUSTMENT_FILTER_REGEX, "").toFloatOrNull()?.nonZeroOrNull() + +/** + * Matches non-float information from ReplayGain adjustments. Derived from vanilla music: + * https://github.com/vanilla-music/vanilla + */ +private val REPLAYGAIN_ADJUSTMENT_FILTER_REGEX by lazy { Regex("[^\\d.-]") } + private fun Metadata.parseId3v23Date(): Date? { // Assume that TDAT/TIME can refer to TYER or TORY depending on if TORY // is present. @@ -222,23 +242,3 @@ private fun Metadata.parseId3v23Date(): Date? { return Date.from(year) } } - -private fun List.parseR128Adjustment() = - first().replace(REPLAYGAIN_ADJUSTMENT_FILTER_REGEX, "").toFloatOrNull()?.nonZeroOrNull()?.run { - // Convert to fixed-point and adjust to LUFS 18 to match the ReplayGain scale - this / 256f + 5 - } - -/** - * Parse a ReplayGain adjustment into a float value. - * - * @return A parsed adjustment float, or null if the adjustment had invalid formatting. - */ -private fun List.parseReplayGainAdjustment() = - first().replace(REPLAYGAIN_ADJUSTMENT_FILTER_REGEX, "").toFloatOrNull()?.nonZeroOrNull() - -/** - * Matches non-float information from ReplayGain adjustments. Derived from vanilla music: - * https://github.com/vanilla-music/vanilla - */ -val REPLAYGAIN_ADJUSTMENT_FILTER_REGEX by lazy { Regex("[^\\d.-]") } diff --git a/musikr/src/main/java/org/oxycblt/musikr/tag/parse/TagParser.kt b/musikr/src/main/java/org/oxycblt/musikr/tag/parse/TagParser.kt index 14ecaf570..9bfce156d 100644 --- a/musikr/src/main/java/org/oxycblt/musikr/tag/parse/TagParser.kt +++ b/musikr/src/main/java/org/oxycblt/musikr/tag/parse/TagParser.kt @@ -18,10 +18,10 @@ package org.oxycblt.musikr.tag.parse -import org.oxycblt.musikr.fs.query.DeviceFile +import org.oxycblt.musikr.fs.DeviceFile import org.oxycblt.musikr.metadata.Metadata -interface TagParser { +internal interface TagParser { fun parse(file: DeviceFile, metadata: Metadata): ParsedTags companion object { diff --git a/musikr/src/main/java/org/oxycblt/musikr/util/LangUtil.kt b/musikr/src/main/java/org/oxycblt/musikr/util/LangUtil.kt index bae4960b9..d71e6b576 100644 --- a/musikr/src/main/java/org/oxycblt/musikr/util/LangUtil.kt +++ b/musikr/src/main/java/org/oxycblt/musikr/util/LangUtil.kt @@ -29,7 +29,7 @@ import org.oxycblt.musikr.tag.Date * otherwise, it aliases to the unchecked dereference operator (!!). This can be used as a minor * optimization in certain cases. */ -fun unlikelyToBeNull(value: T?) = +internal fun unlikelyToBeNull(value: T?) = if (BuildConfig.DEBUG) { requireNotNull(value) } else { @@ -41,14 +41,14 @@ fun unlikelyToBeNull(value: T?) = * * @return The given number if it's non-zero, null otherwise. */ -fun Int.positiveOrNull() = if (this > 0) this else null +internal fun Int.positiveOrNull() = if (this > 0) this else null /** * Aliases a check to ensure that the given number is non-zero. * * @return The same number if it's non-zero, null otherwise. */ -fun Float.nonZeroOrNull() = if (this != 0f) this else null +internal fun Float.nonZeroOrNull() = if (this != 0f) this else null /** * Aliases a check to ensure a given value is in a specified range. @@ -56,7 +56,7 @@ fun Float.nonZeroOrNull() = if (this != 0f) this else null * @param range The valid range of values for this number. * @return The same number if it is in the range, null otherwise. */ -fun Int.inRangeOrNull(range: IntRange) = if (range.contains(this)) this else null +internal fun Int.inRangeOrNull(range: IntRange) = if (range.contains(this)) this else null /** * Convert a [String] to a [UUID]. @@ -64,7 +64,7 @@ fun Int.inRangeOrNull(range: IntRange) = if (range.contains(this)) this else nul * @return A [UUID] converted from the [String] value, or null if the value was not valid. * @see UUID.fromString */ -fun String.toUuidOrNull(): UUID? = +internal fun String.toUuidOrNull(): UUID? = try { UUID.fromString(this) } catch (e: IllegalArgumentException) { @@ -76,7 +76,7 @@ fun String.toUuidOrNull(): UUID? = * * @param string The [String] to hash. If null, it will not be hashed. */ -fun MessageDigest.update(string: String?) { +internal fun MessageDigest.update(string: String?) { if (string != null) { update(string.lowercase().toByteArray()) } else { @@ -89,7 +89,7 @@ fun MessageDigest.update(string: String?) { * * @param date The [Date] to hash. If null, nothing will be done. */ -fun MessageDigest.update(date: Date?) { +internal fun MessageDigest.update(date: Date?) { if (date != null) { update(date.toString().toByteArray()) } else { @@ -102,7 +102,7 @@ fun MessageDigest.update(date: Date?) { * * @param strings The [String]s to hash. If a [String] is null, it will not be hashed. */ -fun MessageDigest.update(strings: List) { +internal fun MessageDigest.update(strings: List) { strings.forEach(::update) } @@ -111,7 +111,7 @@ fun MessageDigest.update(strings: List) { * * @param n The [Int] to write. If null, nothing will be done. */ -fun MessageDigest.update(n: Int?) { +internal fun MessageDigest.update(n: Int?) { if (n != null) { update(byteArrayOf(n.toByte(), n.shr(8).toByte(), n.shr(16).toByte(), n.shr(24).toByte())) } else { @@ -126,7 +126,7 @@ fun MessageDigest.update(n: Int?) { * @param clazz The [KClass] to reflect into. * @param method The name of the method to obtain. */ -fun lazyReflectedMethod(clazz: KClass<*>, method: String, vararg params: KClass<*>) = lazy { +internal fun lazyReflectedMethod(clazz: KClass<*>, method: String, vararg params: KClass<*>) = lazy { clazz.java.getDeclaredMethod(method, *params.map { it.java }.toTypedArray()).also { it.isAccessible = true } diff --git a/musikr/src/main/java/org/oxycblt/musikr/util/ParseUtil.kt b/musikr/src/main/java/org/oxycblt/musikr/util/ParseUtil.kt index 3a474a0c7..4110c387b 100644 --- a/musikr/src/main/java/org/oxycblt/musikr/util/ParseUtil.kt +++ b/musikr/src/main/java/org/oxycblt/musikr/util/ParseUtil.kt @@ -7,7 +7,7 @@ package org.oxycblt.musikr.util * @param selector A block that determines if the string should be split at a given character. * @return One or more [String]s split by the selector. */ -inline fun String.splitEscaped(selector: (Char) -> Boolean): List { +internal inline fun String.splitEscaped(selector: (Char) -> Boolean): List { val split = mutableListOf() var currentString = "" var i = 0 @@ -53,11 +53,11 @@ inline fun String.splitEscaped(selector: (Char) -> Boolean): List { * @return A string with trailing whitespace remove,d or null if the [String] was all whitespace or * empty. */ -fun String.correctWhitespace() = trim().ifBlank { null } +internal fun String.correctWhitespace() = trim().ifBlank { null } /** * Fix trailing whitespace or blank contents within a list of [String]s. * * @return A list of non-blank strings with trailing whitespace removed. */ -fun List.correctWhitespace() = mapNotNull { it.correctWhitespace() } +internal fun List.correctWhitespace() = mapNotNull { it.correctWhitespace() }