diff --git a/app/src/main/java/org/oxycblt/auxio/detail/AlbumDetailFragment.kt b/app/src/main/java/org/oxycblt/auxio/detail/AlbumDetailFragment.kt index db4dde242..2c378e158 100644 --- a/app/src/main/java/org/oxycblt/auxio/detail/AlbumDetailFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/detail/AlbumDetailFragment.kt @@ -31,6 +31,7 @@ import org.oxycblt.auxio.list.ListFragment import org.oxycblt.auxio.list.menu.Menu import org.oxycblt.auxio.music.PlaylistDecision import org.oxycblt.auxio.music.PlaylistMessage +import org.oxycblt.auxio.music.resolveNames import org.oxycblt.auxio.playback.PlaybackDecision import org.oxycblt.auxio.playback.formatDurationMs import org.oxycblt.auxio.util.collect @@ -43,7 +44,6 @@ import org.oxycblt.musikr.Album import org.oxycblt.musikr.Music import org.oxycblt.musikr.MusicParent import org.oxycblt.musikr.Song -import org.oxycblt.musikr.resolveNames import timber.log.Timber as L /** diff --git a/app/src/main/java/org/oxycblt/auxio/detail/ArtistDetailFragment.kt b/app/src/main/java/org/oxycblt/auxio/detail/ArtistDetailFragment.kt index b96452422..ba66f34ee 100644 --- a/app/src/main/java/org/oxycblt/auxio/detail/ArtistDetailFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/detail/ArtistDetailFragment.kt @@ -31,6 +31,7 @@ import org.oxycblt.auxio.list.ListFragment import org.oxycblt.auxio.list.menu.Menu import org.oxycblt.auxio.music.PlaylistDecision import org.oxycblt.auxio.music.PlaylistMessage +import org.oxycblt.auxio.music.resolveNames import org.oxycblt.auxio.playback.PlaybackDecision import org.oxycblt.auxio.util.collect import org.oxycblt.auxio.util.collectImmediately @@ -43,7 +44,6 @@ import org.oxycblt.musikr.Artist import org.oxycblt.musikr.Music import org.oxycblt.musikr.MusicParent import org.oxycblt.musikr.Song -import org.oxycblt.musikr.resolveNames import timber.log.Timber as L /** diff --git a/app/src/main/java/org/oxycblt/auxio/detail/SongDetailDialog.kt b/app/src/main/java/org/oxycblt/auxio/detail/SongDetailDialog.kt index fa263f054..cf6c1af92 100644 --- a/app/src/main/java/org/oxycblt/auxio/detail/SongDetailDialog.kt +++ b/app/src/main/java/org/oxycblt/auxio/detail/SongDetailDialog.kt @@ -32,6 +32,7 @@ import org.oxycblt.auxio.databinding.DialogSongDetailBinding import org.oxycblt.auxio.detail.list.SongProperty import org.oxycblt.auxio.detail.list.SongPropertyAdapter import org.oxycblt.auxio.list.adapter.UpdateInstructions +import org.oxycblt.auxio.music.resolveNames import org.oxycblt.auxio.playback.formatDurationMs import org.oxycblt.auxio.playback.replaygain.formatDb import org.oxycblt.auxio.ui.ViewBindingMaterialDialogFragment @@ -40,7 +41,6 @@ import org.oxycblt.auxio.util.concatLocalized import org.oxycblt.musikr.Music import org.oxycblt.musikr.Song import org.oxycblt.musikr.metadata.AudioProperties -import org.oxycblt.musikr.resolveNames import org.oxycblt.musikr.tag.Name import timber.log.Timber as L diff --git a/app/src/main/java/org/oxycblt/auxio/detail/list/PlaylistDetailListAdapter.kt b/app/src/main/java/org/oxycblt/auxio/detail/list/PlaylistDetailListAdapter.kt index 3cb8e60c2..cb939a587 100644 --- a/app/src/main/java/org/oxycblt/auxio/detail/list/PlaylistDetailListAdapter.kt +++ b/app/src/main/java/org/oxycblt/auxio/detail/list/PlaylistDetailListAdapter.kt @@ -40,12 +40,12 @@ import org.oxycblt.auxio.list.adapter.SelectionIndicatorAdapter import org.oxycblt.auxio.list.adapter.SimpleDiffCallback import org.oxycblt.auxio.list.recycler.MaterialDragCallback import org.oxycblt.auxio.list.recycler.SongViewHolder +import org.oxycblt.auxio.music.resolveNames import org.oxycblt.auxio.util.context import org.oxycblt.auxio.util.getAttrColorCompat import org.oxycblt.auxio.util.inflater import org.oxycblt.musikr.Playlist import org.oxycblt.musikr.Song -import org.oxycblt.musikr.resolveNames import timber.log.Timber as L /** diff --git a/app/src/main/java/org/oxycblt/auxio/detail/list/SongPropertyAdapter.kt b/app/src/main/java/org/oxycblt/auxio/detail/list/SongPropertyAdapter.kt index 29f4bf2d2..fdb5da79a 100644 --- a/app/src/main/java/org/oxycblt/auxio/detail/list/SongPropertyAdapter.kt +++ b/app/src/main/java/org/oxycblt/auxio/detail/list/SongPropertyAdapter.kt @@ -23,7 +23,6 @@ import android.view.ViewGroup import androidx.annotation.StringRes import androidx.recyclerview.widget.RecyclerView import org.oxycblt.auxio.databinding.ItemSongPropertyBinding -import org.oxycblt.auxio.list.Item import org.oxycblt.auxio.list.adapter.FlexibleListAdapter import org.oxycblt.auxio.list.adapter.SimpleDiffCallback import org.oxycblt.auxio.list.recycler.DialogRecyclerView @@ -53,7 +52,7 @@ class SongPropertyAdapter : * @param value The value of the property. * @author Alexander Capehart (OxygenCobalt) */ -data class SongProperty(@StringRes val name: Int, val value: String) : Item +data class SongProperty(@StringRes val name: Int, val value: String) /** * A [RecyclerView.ViewHolder] that displays a [SongProperty]. Use [from] to create an instance. diff --git a/app/src/main/java/org/oxycblt/auxio/list/Data.kt b/app/src/main/java/org/oxycblt/auxio/list/Data.kt index 5507bb9fc..b5c8059cb 100644 --- a/app/src/main/java/org/oxycblt/auxio/list/Data.kt +++ b/app/src/main/java/org/oxycblt/auxio/list/Data.kt @@ -22,9 +22,9 @@ import androidx.annotation.StringRes // TODO: Consider breaking this up into sealed classes for individual adapters /** A marker for something that is a RecyclerView item. Has no functionality on it's own. */ -interface Item +typealias Item = Any -interface Header : Item +interface Header /** * A "header" used for delimiting groups of data. @@ -44,7 +44,7 @@ interface PlainHeader : Header { */ data class BasicHeader(@StringRes override val titleRes: Int) : PlainHeader -interface Divider : Item { +interface Divider { val anchor: T? } diff --git a/app/src/main/java/org/oxycblt/auxio/list/menu/MenuDialogFragmentImpl.kt b/app/src/main/java/org/oxycblt/auxio/list/menu/MenuDialogFragmentImpl.kt index 114b8f9f4..e3ee9b213 100644 --- a/app/src/main/java/org/oxycblt/auxio/list/menu/MenuDialogFragmentImpl.kt +++ b/app/src/main/java/org/oxycblt/auxio/list/menu/MenuDialogFragmentImpl.kt @@ -28,6 +28,7 @@ import org.oxycblt.auxio.databinding.DialogMenuBinding import org.oxycblt.auxio.detail.DetailViewModel import org.oxycblt.auxio.list.ListViewModel import org.oxycblt.auxio.music.MusicViewModel +import org.oxycblt.auxio.music.resolveNames import org.oxycblt.auxio.playback.PlaybackViewModel import org.oxycblt.auxio.playback.formatDurationMs import org.oxycblt.auxio.util.getPlural @@ -37,7 +38,6 @@ import org.oxycblt.musikr.Artist import org.oxycblt.musikr.Genre import org.oxycblt.musikr.Playlist import org.oxycblt.musikr.Song -import org.oxycblt.musikr.resolveNames /** * [MenuDialogFragment] implementation for a [Song]. diff --git a/app/src/main/java/org/oxycblt/auxio/list/recycler/ViewHolders.kt b/app/src/main/java/org/oxycblt/auxio/list/recycler/ViewHolders.kt index 4d7c0fb22..29e5ef101 100644 --- a/app/src/main/java/org/oxycblt/auxio/list/recycler/ViewHolders.kt +++ b/app/src/main/java/org/oxycblt/auxio/list/recycler/ViewHolders.kt @@ -32,6 +32,8 @@ import org.oxycblt.auxio.list.PlainDivider import org.oxycblt.auxio.list.SelectableListListener import org.oxycblt.auxio.list.adapter.SelectionIndicatorAdapter import org.oxycblt.auxio.list.adapter.SimpleDiffCallback +import org.oxycblt.auxio.music.areNamesTheSame +import org.oxycblt.auxio.music.resolveNames import org.oxycblt.auxio.util.context import org.oxycblt.auxio.util.getPlural import org.oxycblt.auxio.util.inflater @@ -40,8 +42,6 @@ import org.oxycblt.musikr.Artist import org.oxycblt.musikr.Genre import org.oxycblt.musikr.Playlist import org.oxycblt.musikr.Song -import org.oxycblt.musikr.areNamesTheSame -import org.oxycblt.musikr.resolveNames /** * A [RecyclerView.ViewHolder] that displays a [Song]. Use [from] to create an instance. diff --git a/app/src/main/java/org/oxycblt/auxio/music/MusicUtil.kt b/app/src/main/java/org/oxycblt/auxio/music/MusicUtil.kt new file mode 100644 index 000000000..9b316161c --- /dev/null +++ b/app/src/main/java/org/oxycblt/auxio/music/MusicUtil.kt @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2024 Auxio Project + * MusicUtil.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.content.Context +import kotlin.math.max +import org.oxycblt.auxio.util.concatLocalized +import org.oxycblt.musikr.Music + +/** + * Run [Name.resolve] on each instance in the given list and concatenate them into a [String] in a + * localized manner. + * + * @param context [Context] required + * @return A concatenated string. + */ +fun List.resolveNames(context: Context) = + concatLocalized(context) { it.name.resolve(context) } + +/** + * Returns if [Music.name] matches for each item in a list. Useful for scenarios where the display + * information of an item must be compared without a context. + * + * @param other The list of items to compare to. + * @return True if they are the same (by [Music.name]), false otherwise. + */ +fun List.areNamesTheSame(other: List): Boolean { + for (i in 0 until max(size, other.size)) { + val a = getOrNull(i) ?: return false + val b = other.getOrNull(i) ?: return false + if (a.name != b.name) { + return false + } + } + + return true +} diff --git a/app/src/main/java/org/oxycblt/auxio/music/ReplayGainPreAmp.kt b/app/src/main/java/org/oxycblt/auxio/music/ReplayGainPreAmp.kt new file mode 100644 index 000000000..93735b9ec --- /dev/null +++ b/app/src/main/java/org/oxycblt/auxio/music/ReplayGainPreAmp.kt @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2024 Auxio Project + * ReplayGainPreAmp.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 + +/** + * The current ReplayGain pre-amp configuration. + * + * @param with The pre-amp (in dB) to use when ReplayGain tags are present. + * @param without The pre-amp (in dB) to use when ReplayGain tags are not present. + * @author Alexander Capehart (OxygenCobalt) + */ +data class ReplayGainPreAmp(val with: Float, val without: Float) diff --git a/app/src/main/java/org/oxycblt/auxio/music/decision/PlaylistPickerViewModel.kt b/app/src/main/java/org/oxycblt/auxio/music/decision/PlaylistPickerViewModel.kt index 753900d0b..df2c13ee8 100644 --- a/app/src/main/java/org/oxycblt/auxio/music/decision/PlaylistPickerViewModel.kt +++ b/app/src/main/java/org/oxycblt/auxio/music/decision/PlaylistPickerViewModel.kt @@ -25,7 +25,6 @@ import javax.inject.Inject import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import org.oxycblt.auxio.R -import org.oxycblt.auxio.list.Item import org.oxycblt.auxio.list.sort.Sort import org.oxycblt.auxio.music.MusicRepository import org.oxycblt.auxio.music.PlaylistDecision @@ -354,4 +353,4 @@ sealed interface ChosenName { * [Playlist]. * @author Alexander Capehart (OxygenCobalt) */ -data class PlaylistChoice(val playlist: Playlist, val alreadyAdded: Boolean) : Item +data class PlaylistChoice(val playlist: Playlist, val alreadyAdded: Boolean) diff --git a/app/src/main/java/org/oxycblt/auxio/music/service/MediaItemTranslation.kt b/app/src/main/java/org/oxycblt/auxio/music/service/MediaItemTranslation.kt index b33836132..a4bf9d5d6 100644 --- a/app/src/main/java/org/oxycblt/auxio/music/service/MediaItemTranslation.kt +++ b/app/src/main/java/org/oxycblt/auxio/music/service/MediaItemTranslation.kt @@ -27,6 +27,7 @@ import androidx.annotation.StringRes import androidx.media.utils.MediaConstants import org.oxycblt.auxio.BuildConfig import org.oxycblt.auxio.R +import org.oxycblt.auxio.music.resolveNames import org.oxycblt.auxio.playback.formatDurationDs import org.oxycblt.auxio.util.getPlural import org.oxycblt.musikr.Album @@ -36,7 +37,6 @@ import org.oxycblt.musikr.Music import org.oxycblt.musikr.MusicParent import org.oxycblt.musikr.Playlist import org.oxycblt.musikr.Song -import org.oxycblt.musikr.resolveNames sealed interface MediaSessionUID { data class Tab(val node: TabNode) : MediaSessionUID { diff --git a/app/src/main/java/org/oxycblt/auxio/playback/PlaybackBarFragment.kt b/app/src/main/java/org/oxycblt/auxio/playback/PlaybackBarFragment.kt index c4bda9307..36cb21d3f 100644 --- a/app/src/main/java/org/oxycblt/auxio/playback/PlaybackBarFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/playback/PlaybackBarFragment.kt @@ -26,13 +26,13 @@ import dagger.hilt.android.AndroidEntryPoint import org.oxycblt.auxio.R import org.oxycblt.auxio.databinding.FragmentPlaybackBarBinding import org.oxycblt.auxio.detail.DetailViewModel +import org.oxycblt.auxio.music.resolveNames import org.oxycblt.auxio.playback.state.RepeatMode import org.oxycblt.auxio.ui.ViewBindingFragment import org.oxycblt.auxio.util.collectImmediately import org.oxycblt.auxio.util.getAttrColorCompat import org.oxycblt.auxio.util.getColorCompat import org.oxycblt.musikr.Song -import org.oxycblt.musikr.resolveNames import timber.log.Timber as L /** diff --git a/app/src/main/java/org/oxycblt/auxio/playback/PlaybackPanelFragment.kt b/app/src/main/java/org/oxycblt/auxio/playback/PlaybackPanelFragment.kt index 028ef5e85..ad918ff63 100644 --- a/app/src/main/java/org/oxycblt/auxio/playback/PlaybackPanelFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/playback/PlaybackPanelFragment.kt @@ -35,6 +35,7 @@ import org.oxycblt.auxio.R import org.oxycblt.auxio.databinding.FragmentPlaybackPanelBinding import org.oxycblt.auxio.detail.DetailViewModel import org.oxycblt.auxio.list.ListViewModel +import org.oxycblt.auxio.music.resolveNames import org.oxycblt.auxio.playback.state.RepeatMode import org.oxycblt.auxio.playback.ui.StyledSeekBar import org.oxycblt.auxio.playback.ui.SwipeCoverView @@ -44,7 +45,6 @@ import org.oxycblt.auxio.util.showToast import org.oxycblt.auxio.util.systemBarInsetsCompat import org.oxycblt.musikr.MusicParent import org.oxycblt.musikr.Song -import org.oxycblt.musikr.resolveNames import timber.log.Timber as L /** diff --git a/app/src/main/java/org/oxycblt/auxio/playback/PlaybackSettings.kt b/app/src/main/java/org/oxycblt/auxio/playback/PlaybackSettings.kt index a86fbee47..a43137f55 100644 --- a/app/src/main/java/org/oxycblt/auxio/playback/PlaybackSettings.kt +++ b/app/src/main/java/org/oxycblt/auxio/playback/PlaybackSettings.kt @@ -24,8 +24,8 @@ import dagger.hilt.android.qualifiers.ApplicationContext import javax.inject.Inject import org.oxycblt.auxio.IntegerTable import org.oxycblt.auxio.R +import org.oxycblt.auxio.music.ReplayGainPreAmp import org.oxycblt.auxio.playback.replaygain.ReplayGainMode -import org.oxycblt.auxio.playback.replaygain.ReplayGainPreAmp import org.oxycblt.auxio.settings.Settings import timber.log.Timber as L diff --git a/app/src/main/java/org/oxycblt/auxio/playback/queue/QueueAdapter.kt b/app/src/main/java/org/oxycblt/auxio/playback/queue/QueueAdapter.kt index 9bc857314..b4ef78f7e 100644 --- a/app/src/main/java/org/oxycblt/auxio/playback/queue/QueueAdapter.kt +++ b/app/src/main/java/org/oxycblt/auxio/playback/queue/QueueAdapter.kt @@ -32,11 +32,11 @@ import org.oxycblt.auxio.list.adapter.FlexibleListAdapter import org.oxycblt.auxio.list.adapter.PlayingIndicatorAdapter import org.oxycblt.auxio.list.recycler.MaterialDragCallback import org.oxycblt.auxio.list.recycler.SongViewHolder +import org.oxycblt.auxio.music.resolveNames import org.oxycblt.auxio.util.context import org.oxycblt.auxio.util.getAttrColorCompat import org.oxycblt.auxio.util.inflater import org.oxycblt.musikr.Song -import org.oxycblt.musikr.resolveNames import timber.log.Timber as L /** diff --git a/app/src/main/java/org/oxycblt/auxio/playback/replaygain/PreAmpCustomizeDialog.kt b/app/src/main/java/org/oxycblt/auxio/playback/replaygain/PreAmpCustomizeDialog.kt index 0ef752a1d..bf0fc39ad 100644 --- a/app/src/main/java/org/oxycblt/auxio/playback/replaygain/PreAmpCustomizeDialog.kt +++ b/app/src/main/java/org/oxycblt/auxio/playback/replaygain/PreAmpCustomizeDialog.kt @@ -26,6 +26,7 @@ import dagger.hilt.android.AndroidEntryPoint import javax.inject.Inject import org.oxycblt.auxio.R import org.oxycblt.auxio.databinding.DialogPreAmpBinding +import org.oxycblt.auxio.music.ReplayGainPreAmp import org.oxycblt.auxio.playback.PlaybackSettings import org.oxycblt.auxio.ui.ViewBindingMaterialDialogFragment import timber.log.Timber as L diff --git a/app/src/main/java/org/oxycblt/auxio/playback/replaygain/ReplayGain.kt b/app/src/main/java/org/oxycblt/auxio/playback/replaygain/ReplayGainMode.kt similarity index 61% rename from app/src/main/java/org/oxycblt/auxio/playback/replaygain/ReplayGain.kt rename to app/src/main/java/org/oxycblt/auxio/playback/replaygain/ReplayGainMode.kt index 012bdfce3..8fec198aa 100644 --- a/app/src/main/java/org/oxycblt/auxio/playback/replaygain/ReplayGain.kt +++ b/app/src/main/java/org/oxycblt/auxio/playback/replaygain/ReplayGainMode.kt @@ -1,6 +1,6 @@ /* - * Copyright (c) 2022 Auxio Project - * ReplayGain.kt is part of Auxio. + * Copyright (c) 2024 Auxio Project + * ReplayGainMode.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 @@ -18,10 +18,7 @@ package org.oxycblt.auxio.playback.replaygain -import android.content.Context -import kotlin.math.abs import org.oxycblt.auxio.IntegerTable -import org.oxycblt.auxio.R /** * The current ReplayGain configuration. @@ -55,34 +52,3 @@ enum class ReplayGainMode { } } } - -/** - * Represents a ReplayGain adjustment to apply during song playback. - * - * @param track The track-specific adjustment that should be applied. Null if not available. - * @param album A more general album-specific adjustment that should be applied. Null if not - * available. - */ -data class ReplayGainAdjustment(val track: Float?, val album: Float?) - -/** - * The current ReplayGain pre-amp configuration. - * - * @param with The pre-amp (in dB) to use when ReplayGain tags are present. - * @param without The pre-amp (in dB) to use when ReplayGain tags are not present. - * @author Alexander Capehart (OxygenCobalt) - */ -data class ReplayGainPreAmp(val with: Float, val without: Float) - -/** - * Format a decibel value in a human-readable format. - * - * @param context The context to resolve resources from. - * @return A formatted decibel value. Will be prefixed by a + or - sign. - */ -fun Float.formatDb(context: Context) = - if (this >= 0) { - context.getString(R.string.fmt_db_pos, this) - } else { - context.getString(R.string.fmt_db_neg, abs(this)) - } diff --git a/app/src/main/java/org/oxycblt/auxio/playback/replaygain/ReplayGainUtil.kt b/app/src/main/java/org/oxycblt/auxio/playback/replaygain/ReplayGainUtil.kt new file mode 100644 index 000000000..fc258b83c --- /dev/null +++ b/app/src/main/java/org/oxycblt/auxio/playback/replaygain/ReplayGainUtil.kt @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2024 Auxio Project + * ReplayGainUtil.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.playback.replaygain + +import android.content.Context +import kotlin.math.abs +import org.oxycblt.auxio.R + +/** + * Format a decibel value in a human-readable format. + * + * @param context The context to resolve resources from. + * @return A formatted decibel value. Will be prefixed by a + or - sign. + */ +fun Float.formatDb(context: Context) = + if (this >= 0) { + context.getString(R.string.fmt_db_pos, this) + } else { + context.getString(R.string.fmt_db_neg, abs(this)) + } diff --git a/app/src/main/java/org/oxycblt/auxio/playback/service/MediaSessionHolder.kt b/app/src/main/java/org/oxycblt/auxio/playback/service/MediaSessionHolder.kt index f57643bca..a7ed418e3 100644 --- a/app/src/main/java/org/oxycblt/auxio/playback/service/MediaSessionHolder.kt +++ b/app/src/main/java/org/oxycblt/auxio/playback/service/MediaSessionHolder.kt @@ -36,6 +36,7 @@ import org.oxycblt.auxio.IntegerTable import org.oxycblt.auxio.R import org.oxycblt.auxio.image.BitmapProvider import org.oxycblt.auxio.image.ImageSettings +import org.oxycblt.auxio.music.resolveNames import org.oxycblt.auxio.music.service.MediaSessionUID import org.oxycblt.auxio.music.service.toMediaDescription import org.oxycblt.auxio.playback.ActionMode @@ -48,7 +49,6 @@ import org.oxycblt.auxio.util.newBroadcastPendingIntent import org.oxycblt.auxio.util.newMainPendingIntent import org.oxycblt.musikr.MusicParent import org.oxycblt.musikr.Song -import org.oxycblt.musikr.resolveNames import timber.log.Timber as L /** diff --git a/app/src/main/java/org/oxycblt/auxio/util/LangUtil.kt b/app/src/main/java/org/oxycblt/auxio/util/LangUtil.kt index 91eb66ed6..d5f9465f0 100644 --- a/app/src/main/java/org/oxycblt/auxio/util/LangUtil.kt +++ b/app/src/main/java/org/oxycblt/auxio/util/LangUtil.kt @@ -18,11 +18,8 @@ package org.oxycblt.auxio.util -import java.security.MessageDigest -import java.util.UUID import kotlin.reflect.KClass import org.oxycblt.auxio.BuildConfig -import org.oxycblt.musikr.tag.Date /** * Sanitizes a value that is unlikely to be null. On debug builds, this aliases to [requireNotNull], @@ -43,28 +40,6 @@ fun unlikelyToBeNull(value: T?) = */ 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 Long.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 - -/** - * Aliases a check to ensure a given value is in a specified range. - * - * @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 - /** * Lazily set up a reflected field. Automatically handles visibility changes. Adapted from Material * Files: https://github.com/zhanghai/MaterialFiles @@ -75,6 +50,7 @@ fun Int.inRangeOrNull(range: IntRange) = if (range.contains(this)) this else nul fun lazyReflectedField(clazz: KClass<*>, field: String) = lazy { clazz.java.getDeclaredField(field).also { it.isAccessible = true } } + /** * Lazily set up a reflected method. Automatically handles visibility changes. Adapted from Material * Files: https://github.com/zhanghai/MaterialFiles @@ -87,64 +63,3 @@ fun lazyReflectedMethod(clazz: KClass<*>, method: String, vararg params: KClass< it.isAccessible = true } } - -/** - * Convert a [String] to a [UUID]. - * - * @return A [UUID] converted from the [String] value, or null if the value was not valid. - * @see UUID.fromString - */ -fun String.toUuidOrNull(): UUID? = - try { - UUID.fromString(this) - } catch (e: IllegalArgumentException) { - null - } - -/** - * Update a [MessageDigest] with a lowercase [String]. - * - * @param string The [String] to hash. If null, it will not be hashed. - */ -fun MessageDigest.update(string: String?) { - if (string != null) { - update(string.lowercase().toByteArray()) - } else { - update(0) - } -} - -/** - * Update a [MessageDigest] with the string representation of a [Date]. - * - * @param date The [Date] to hash. If null, nothing will be done. - */ -fun MessageDigest.update(date: Date?) { - if (date != null) { - update(date.toString().toByteArray()) - } else { - update(0) - } -} - -/** - * Update a [MessageDigest] with the lowercase versions of all of the input [String]s. - * - * @param strings The [String]s to hash. If a [String] is null, it will not be hashed. - */ -fun MessageDigest.update(strings: List) { - strings.forEach(::update) -} - -/** - * Update a [MessageDigest] with the little-endian bytes of a [Int]. - * - * @param n The [Int] to write. If null, nothing will be done. - */ -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 { - update(0) - } -} diff --git a/app/src/main/java/org/oxycblt/auxio/widgets/WidgetProvider.kt b/app/src/main/java/org/oxycblt/auxio/widgets/WidgetProvider.kt index 5757976c5..9dc85edc8 100644 --- a/app/src/main/java/org/oxycblt/auxio/widgets/WidgetProvider.kt +++ b/app/src/main/java/org/oxycblt/auxio/widgets/WidgetProvider.kt @@ -30,12 +30,12 @@ import android.view.View import android.widget.RemoteViews import org.oxycblt.auxio.BuildConfig import org.oxycblt.auxio.R +import org.oxycblt.auxio.music.resolveNames import org.oxycblt.auxio.playback.service.PlaybackActions import org.oxycblt.auxio.playback.state.RepeatMode import org.oxycblt.auxio.ui.UISettings import org.oxycblt.auxio.ui.UISettingsImpl import org.oxycblt.auxio.util.newBroadcastPendingIntent -import org.oxycblt.musikr.resolveNames import timber.log.Timber as L /** diff --git a/app/src/main/java/org/oxycblt/musikr/Music.kt b/app/src/main/java/org/oxycblt/musikr/Music.kt index 93e4d7faa..c03996e94 100644 --- a/app/src/main/java/org/oxycblt/musikr/Music.kt +++ b/app/src/main/java/org/oxycblt/musikr/Music.kt @@ -18,20 +18,13 @@ package org.oxycblt.musikr -import android.content.Context import android.net.Uri import android.os.Parcelable import androidx.room.TypeConverter import java.security.MessageDigest import java.util.UUID -import kotlin.math.max import kotlinx.parcelize.IgnoredOnParcel import kotlinx.parcelize.Parcelize -import org.oxycblt.auxio.list.Item -import org.oxycblt.auxio.music.MusicType -import org.oxycblt.auxio.playback.replaygain.ReplayGainAdjustment -import org.oxycblt.auxio.util.concatLocalized -import org.oxycblt.auxio.util.toUuidOrNull import org.oxycblt.musikr.cover.Cover import org.oxycblt.musikr.fs.Format import org.oxycblt.musikr.fs.Path @@ -39,6 +32,8 @@ import org.oxycblt.musikr.tag.Date import org.oxycblt.musikr.tag.Disc import org.oxycblt.musikr.tag.Name import org.oxycblt.musikr.tag.ReleaseType +import org.oxycblt.musikr.tag.ReplayGainAdjustment +import org.oxycblt.musikr.util.toUuidOrNull /** * Abstract music data. This contains universal information about all concrete music @@ -46,7 +41,7 @@ import org.oxycblt.musikr.tag.ReleaseType * * @author Alexander Capehart (OxygenCobalt) */ -sealed interface Music : Item { +sealed interface Music { /** * A unique identifier for this music item. * @@ -189,7 +184,7 @@ sealed interface Music : Item { * Creates a MusicBrainz-style [UID] with a [UUID] derived from the MusicBrainz ID * extracted from a file. * - * @param item The analogous [MusicType] of the item that created this [UID]. + * @param item The [Item] that created this [UID]. * @param mbid The analogous MusicBrainz ID for this item that was extracted from a * file. * @return A new MusicBrainz-style [UID]. @@ -372,32 +367,3 @@ interface Playlist : MusicParent { /** Useful information to quickly obtain a (single) cover for a Genre. */ val cover: Cover } - -/** - * Run [Name.resolve] on each instance in the given list and concatenate them into a [String] in a - * localized manner. - * - * @param context [Context] required - * @return A concatenated string. - */ -fun List.resolveNames(context: Context) = - concatLocalized(context) { it.name.resolve(context) } - -/** - * Returns if [Music.name] matches for each item in a list. Useful for scenarios where the display - * information of an item must be compared without a context. - * - * @param other The list of items to compare to. - * @return True if they are the same (by [Music.name]), false otherwise. - */ -fun List.areNamesTheSame(other: List): Boolean { - for (i in 0 until max(size, other.size)) { - val a = getOrNull(i) ?: return false - val b = other.getOrNull(i) ?: return false - if (a.name != b.name) { - return false - } - } - - return true -} diff --git a/app/src/main/java/org/oxycblt/musikr/cover/Cover.kt b/app/src/main/java/org/oxycblt/musikr/cover/Cover.kt index 1e1c32b1e..c206bfd7d 100644 --- a/app/src/main/java/org/oxycblt/musikr/cover/Cover.kt +++ b/app/src/main/java/org/oxycblt/musikr/cover/Cover.kt @@ -18,7 +18,6 @@ package org.oxycblt.musikr.cover -import org.oxycblt.auxio.list.sort.Sort import org.oxycblt.musikr.Song sealed interface Cover { @@ -31,8 +30,6 @@ sealed interface Cover { } companion object { - private val FALLBACK_SORT = Sort(Sort.Mode.ByName, Sort.Direction.ASCENDING) - fun nil() = Multi(listOf()) fun single(key: String) = Single(key) @@ -40,10 +37,11 @@ sealed interface Cover { fun multi(songs: Collection) = order(songs).run { Multi(this) } private fun order(songs: Collection) = - FALLBACK_SORT.songs(songs) + songs .mapNotNull { it.cover } .groupBy { it.key } .entries + .sortedByDescending { it.key } .sortedByDescending { it.value.size } .map { it.value.first() } } diff --git a/app/src/main/java/org/oxycblt/musikr/fs/Format.kt b/app/src/main/java/org/oxycblt/musikr/fs/Format.kt index d4172238e..3652a80df 100644 --- a/app/src/main/java/org/oxycblt/musikr/fs/Format.kt +++ b/app/src/main/java/org/oxycblt/musikr/fs/Format.kt @@ -19,7 +19,7 @@ package org.oxycblt.musikr.fs import android.webkit.MimeTypeMap -import org.oxycblt.auxio.util.unlikelyToBeNull +import org.oxycblt.musikr.util.unlikelyToBeNull sealed interface Format { val mimeType: String diff --git a/app/src/main/java/org/oxycblt/musikr/graph/MusicGraph.kt b/app/src/main/java/org/oxycblt/musikr/graph/MusicGraph.kt index 3cb88370f..b5dfea7ab 100644 --- a/app/src/main/java/org/oxycblt/musikr/graph/MusicGraph.kt +++ b/app/src/main/java/org/oxycblt/musikr/graph/MusicGraph.kt @@ -18,12 +18,12 @@ package org.oxycblt.musikr.graph -import org.oxycblt.auxio.util.unlikelyToBeNull import org.oxycblt.musikr.Music import org.oxycblt.musikr.tag.interpret.PreAlbum import org.oxycblt.musikr.tag.interpret.PreArtist import org.oxycblt.musikr.tag.interpret.PreGenre import org.oxycblt.musikr.tag.interpret.PreSong +import org.oxycblt.musikr.util.unlikelyToBeNull import timber.log.Timber as L data class MusicGraph( diff --git a/app/src/main/java/org/oxycblt/musikr/metadata/MetadataExtractor.kt b/app/src/main/java/org/oxycblt/musikr/metadata/MetadataExtractor.kt index 84126dfd0..8fc3ff562 100644 --- a/app/src/main/java/org/oxycblt/musikr/metadata/MetadataExtractor.kt +++ b/app/src/main/java/org/oxycblt/musikr/metadata/MetadataExtractor.kt @@ -21,11 +21,11 @@ package org.oxycblt.musikr.metadata import android.content.Context import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext -import org.oxycblt.auxio.util.unlikelyToBeNull import org.oxycblt.ktaglib.FileRef import org.oxycblt.ktaglib.KTagLib import org.oxycblt.ktaglib.Metadata import org.oxycblt.musikr.fs.query.DeviceFile +import org.oxycblt.musikr.util.unlikelyToBeNull interface MetadataExtractor { suspend fun extract(file: DeviceFile): Metadata? diff --git a/app/src/main/java/org/oxycblt/musikr/model/AlbumImpl.kt b/app/src/main/java/org/oxycblt/musikr/model/AlbumImpl.kt index 972b15ab7..02148c876 100644 --- a/app/src/main/java/org/oxycblt/musikr/model/AlbumImpl.kt +++ b/app/src/main/java/org/oxycblt/musikr/model/AlbumImpl.kt @@ -18,7 +18,6 @@ package org.oxycblt.musikr.model -import org.oxycblt.auxio.util.update import org.oxycblt.musikr.Album import org.oxycblt.musikr.Artist import org.oxycblt.musikr.Music @@ -26,6 +25,7 @@ import org.oxycblt.musikr.Song import org.oxycblt.musikr.cover.Cover import org.oxycblt.musikr.tag.Date import org.oxycblt.musikr.tag.interpret.PreAlbum +import org.oxycblt.musikr.util.update interface AlbumCore { val preAlbum: PreAlbum diff --git a/app/src/main/java/org/oxycblt/musikr/model/ArtistImpl.kt b/app/src/main/java/org/oxycblt/musikr/model/ArtistImpl.kt index 06829e06c..f37f6c264 100644 --- a/app/src/main/java/org/oxycblt/musikr/model/ArtistImpl.kt +++ b/app/src/main/java/org/oxycblt/musikr/model/ArtistImpl.kt @@ -18,7 +18,6 @@ package org.oxycblt.musikr.model -import org.oxycblt.auxio.util.update import org.oxycblt.musikr.Album import org.oxycblt.musikr.Artist import org.oxycblt.musikr.Genre @@ -26,6 +25,7 @@ import org.oxycblt.musikr.Music import org.oxycblt.musikr.Song import org.oxycblt.musikr.cover.Cover import org.oxycblt.musikr.tag.interpret.PreArtist +import org.oxycblt.musikr.util.update interface ArtistCore { val preArtist: PreArtist diff --git a/app/src/main/java/org/oxycblt/musikr/model/GenreImpl.kt b/app/src/main/java/org/oxycblt/musikr/model/GenreImpl.kt index d9146aeb5..8fa91f4e0 100644 --- a/app/src/main/java/org/oxycblt/musikr/model/GenreImpl.kt +++ b/app/src/main/java/org/oxycblt/musikr/model/GenreImpl.kt @@ -18,13 +18,13 @@ package org.oxycblt.musikr.model -import org.oxycblt.auxio.util.update import org.oxycblt.musikr.Artist import org.oxycblt.musikr.Genre import org.oxycblt.musikr.Music import org.oxycblt.musikr.Song import org.oxycblt.musikr.cover.Cover import org.oxycblt.musikr.tag.interpret.PreGenre +import org.oxycblt.musikr.util.update interface GenreCore { val preGenre: PreGenre diff --git a/app/src/main/java/org/oxycblt/musikr/playlist/m3u/M3U.kt b/app/src/main/java/org/oxycblt/musikr/playlist/m3u/M3U.kt index 40f905125..2967d90fd 100644 --- a/app/src/main/java/org/oxycblt/musikr/playlist/m3u/M3U.kt +++ b/app/src/main/java/org/oxycblt/musikr/playlist/m3u/M3U.kt @@ -25,7 +25,7 @@ import java.io.BufferedWriter import java.io.InputStream import java.io.InputStreamReader import java.io.OutputStream -import org.oxycblt.auxio.util.unlikelyToBeNull +import org.oxycblt.auxio.music.resolveNames import org.oxycblt.musikr.Playlist import org.oxycblt.musikr.fs.Components import org.oxycblt.musikr.fs.Path @@ -34,8 +34,8 @@ import org.oxycblt.musikr.fs.path.VolumeManager import org.oxycblt.musikr.playlist.ExportConfig import org.oxycblt.musikr.playlist.ImportedPlaylist import org.oxycblt.musikr.playlist.PossiblePaths -import org.oxycblt.musikr.resolveNames import org.oxycblt.musikr.tag.util.correctWhitespace +import org.oxycblt.musikr.util.unlikelyToBeNull import timber.log.Timber as L /** diff --git a/app/src/main/java/org/oxycblt/musikr/tag/Date.kt b/app/src/main/java/org/oxycblt/musikr/tag/Date.kt index 98f03e1d7..b03b6b885 100644 --- a/app/src/main/java/org/oxycblt/musikr/tag/Date.kt +++ b/app/src/main/java/org/oxycblt/musikr/tag/Date.kt @@ -23,8 +23,8 @@ import java.text.ParseException import java.text.SimpleDateFormat import kotlin.math.max import org.oxycblt.auxio.R -import org.oxycblt.auxio.util.inRangeOrNull -import org.oxycblt.auxio.util.positiveOrNull +import org.oxycblt.musikr.util.inRangeOrNull +import org.oxycblt.musikr.util.positiveOrNull import timber.log.Timber as L /** diff --git a/app/src/main/java/org/oxycblt/musikr/tag/Disc.kt b/app/src/main/java/org/oxycblt/musikr/tag/Disc.kt index 28e45c508..d97569c4f 100644 --- a/app/src/main/java/org/oxycblt/musikr/tag/Disc.kt +++ b/app/src/main/java/org/oxycblt/musikr/tag/Disc.kt @@ -20,7 +20,6 @@ package org.oxycblt.musikr.tag import android.content.Context import org.oxycblt.auxio.R -import org.oxycblt.auxio.list.Item /** * A disc identifier for a song. @@ -28,7 +27,7 @@ import org.oxycblt.auxio.list.Item * @param number The disc number. * @param name The name of the disc group, if any. Null if not present. */ -class Disc(val number: Int, val name: String?) : Item, Comparable { +class Disc(val number: Int, val name: String?) : Comparable { // We don't want to group discs by differing subtitles, so only compare by the number override fun equals(other: Any?) = other is Disc && number == other.number diff --git a/app/src/main/java/org/oxycblt/musikr/tag/ReplayGainAdjustment.kt b/app/src/main/java/org/oxycblt/musikr/tag/ReplayGainAdjustment.kt new file mode 100644 index 000000000..e429ab674 --- /dev/null +++ b/app/src/main/java/org/oxycblt/musikr/tag/ReplayGainAdjustment.kt @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2022 Auxio Project + * ReplayGainAdjustment.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.tag + +/** + * Represents a ReplayGain adjustment to apply during song playback. + * + * @param track The track-specific adjustment that should be applied. Null if not available. + * @param album A more general album-specific adjustment that should be applied. Null if not + * available. + */ +data class ReplayGainAdjustment(val track: Float?, val album: Float?) diff --git a/app/src/main/java/org/oxycblt/musikr/tag/interpret/PreMusic.kt b/app/src/main/java/org/oxycblt/musikr/tag/interpret/PreMusic.kt index e617fa3e4..0cbd2ad11 100644 --- a/app/src/main/java/org/oxycblt/musikr/tag/interpret/PreMusic.kt +++ b/app/src/main/java/org/oxycblt/musikr/tag/interpret/PreMusic.kt @@ -20,8 +20,6 @@ package org.oxycblt.musikr.tag.interpret import android.net.Uri import java.util.UUID -import org.oxycblt.auxio.playback.replaygain.ReplayGainAdjustment -import org.oxycblt.auxio.util.update import org.oxycblt.musikr.Music import org.oxycblt.musikr.cover.Cover import org.oxycblt.musikr.fs.Format @@ -31,6 +29,8 @@ import org.oxycblt.musikr.tag.Date import org.oxycblt.musikr.tag.Disc import org.oxycblt.musikr.tag.Name import org.oxycblt.musikr.tag.ReleaseType +import org.oxycblt.musikr.tag.ReplayGainAdjustment +import org.oxycblt.musikr.util.update data class PreSong( val musicBrainzId: UUID?, diff --git a/app/src/main/java/org/oxycblt/musikr/tag/interpret/TagInterpreter.kt b/app/src/main/java/org/oxycblt/musikr/tag/interpret/TagInterpreter.kt index 8cf1e9856..997fe9310 100644 --- a/app/src/main/java/org/oxycblt/musikr/tag/interpret/TagInterpreter.kt +++ b/app/src/main/java/org/oxycblt/musikr/tag/interpret/TagInterpreter.kt @@ -19,8 +19,6 @@ package org.oxycblt.musikr.tag.interpret 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.Format import org.oxycblt.musikr.fs.query.DeviceFile @@ -28,8 +26,10 @@ import org.oxycblt.musikr.pipeline.RawSong import org.oxycblt.musikr.tag.Disc import org.oxycblt.musikr.tag.Name import org.oxycblt.musikr.tag.ReleaseType +import org.oxycblt.musikr.tag.ReplayGainAdjustment import org.oxycblt.musikr.tag.parse.ParsedTags import org.oxycblt.musikr.tag.util.parseId3GenreNames +import org.oxycblt.musikr.util.toUuidOrNull interface TagInterpreter { fun interpret(song: RawSong, interpretation: Interpretation): PreSong diff --git a/app/src/main/java/org/oxycblt/musikr/tag/parse/ExoPlayerTagFields.kt b/app/src/main/java/org/oxycblt/musikr/tag/parse/ExoPlayerTagFields.kt index f8f309cef..1d10ba3f2 100644 --- a/app/src/main/java/org/oxycblt/musikr/tag/parse/ExoPlayerTagFields.kt +++ b/app/src/main/java/org/oxycblt/musikr/tag/parse/ExoPlayerTagFields.kt @@ -19,11 +19,11 @@ package org.oxycblt.musikr.tag.parse import androidx.core.text.isDigitsOnly -import org.oxycblt.auxio.util.nonZeroOrNull import org.oxycblt.ktaglib.Metadata import org.oxycblt.musikr.tag.Date import org.oxycblt.musikr.tag.util.parseId3v2PositionField import org.oxycblt.musikr.tag.util.parseXiphPositionField +import org.oxycblt.musikr.util.nonZeroOrNull // Song fun Metadata.musicBrainzId() = diff --git a/app/src/main/java/org/oxycblt/musikr/tag/util/Vorbis.kt b/app/src/main/java/org/oxycblt/musikr/tag/util/Vorbis.kt index 7e8378a7a..632a516c4 100644 --- a/app/src/main/java/org/oxycblt/musikr/tag/util/Vorbis.kt +++ b/app/src/main/java/org/oxycblt/musikr/tag/util/Vorbis.kt @@ -18,7 +18,7 @@ package org.oxycblt.musikr.tag.util -import org.oxycblt.auxio.util.positiveOrNull +import org.oxycblt.musikr.util.positiveOrNull /** * Parse an ID3v2-style position + total [String] field. These fields consist of a number and an diff --git a/app/src/main/java/org/oxycblt/musikr/util/LangUtil.kt b/app/src/main/java/org/oxycblt/musikr/util/LangUtil.kt new file mode 100644 index 000000000..3ebd60c6c --- /dev/null +++ b/app/src/main/java/org/oxycblt/musikr/util/LangUtil.kt @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2021 Auxio Project + * LangUtil.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.util + +import java.security.MessageDigest +import java.util.UUID +import org.oxycblt.auxio.BuildConfig +import org.oxycblt.musikr.tag.Date +import kotlin.reflect.KClass + +/** + * Sanitizes a value that is unlikely to be null. On debug builds, this aliases to [requireNotNull], + * otherwise, it aliases to the unchecked dereference operator (!!). This can be used as a minor + * optimization in certain cases. + */ +fun unlikelyToBeNull(value: T?) = + if (BuildConfig.DEBUG) { + requireNotNull(value) + } else { + value!! + } + +/** + * Aliases a check to ensure that the given number is non-zero. + * + * @return The given number if it's non-zero, null otherwise. + */ +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 + +/** + * Aliases a check to ensure a given value is in a specified range. + * + * @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 + +/** + * Convert a [String] to a [UUID]. + * + * @return A [UUID] converted from the [String] value, or null if the value was not valid. + * @see UUID.fromString + */ +fun String.toUuidOrNull(): UUID? = + try { + UUID.fromString(this) + } catch (e: IllegalArgumentException) { + null + } + +/** + * Update a [MessageDigest] with a lowercase [String]. + * + * @param string The [String] to hash. If null, it will not be hashed. + */ +fun MessageDigest.update(string: String?) { + if (string != null) { + update(string.lowercase().toByteArray()) + } else { + update(0) + } +} + +/** + * Update a [MessageDigest] with the string representation of a [Date]. + * + * @param date The [Date] to hash. If null, nothing will be done. + */ +fun MessageDigest.update(date: Date?) { + if (date != null) { + update(date.toString().toByteArray()) + } else { + update(0) + } +} + +/** + * Update a [MessageDigest] with the lowercase versions of all of the input [String]s. + * + * @param strings The [String]s to hash. If a [String] is null, it will not be hashed. + */ +fun MessageDigest.update(strings: List) { + strings.forEach(::update) +} + +/** + * Update a [MessageDigest] with the little-endian bytes of a [Int]. + * + * @param n The [Int] to write. If null, nothing will be done. + */ +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 { + update(0) + } +} + +/** + * Lazily set up a reflected method. Automatically handles visibility changes. Adapted from Material + * Files: https://github.com/zhanghai/MaterialFiles + * + * @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 { + clazz.java.getDeclaredMethod(method, *params.map { it.java }.toTypedArray()).also { + it.isAccessible = true + } +} \ No newline at end of file