diff --git a/app/src/main/java/org/oxycblt/auxio/music/Music.kt b/app/src/main/java/org/oxycblt/auxio/music/Music.kt index ed9c87944..df165045c 100644 --- a/app/src/main/java/org/oxycblt/auxio/music/Music.kt +++ b/app/src/main/java/org/oxycblt/auxio/music/Music.kt @@ -30,7 +30,6 @@ import org.oxycblt.auxio.music.ui.MusicMode import org.oxycblt.auxio.music.ui.Sort import org.oxycblt.auxio.ui.recycler.Item import org.oxycblt.auxio.util.inRangeOrNull -import org.oxycblt.auxio.util.logD import org.oxycblt.auxio.util.nonZeroOrNull import org.oxycblt.auxio.util.unlikelyToBeNull import java.security.MessageDigest @@ -95,6 +94,11 @@ sealed class Music : Item { * external sources, as it can persist across app restarts and does not need to encode useless * information about the relationships between items. * + * Note: While the core of a UID is a UUID. The whole is not technically a UUID, with + * string representation in particular having multiple extensions to increase uniqueness. + * Please don't try to do anything interesting with this and just assume it's a black box + * that can only be compared, serialized, and deserialized. + * * TODO: MusicBrainz tags * * @author OxygenCobalt @@ -113,8 +117,6 @@ sealed class Music : Item { result = 31 * result + mode.hashCode() result = 31 * result + uuid.hashCode() hashCode = result - - logD(this) } override fun hashCode() = hashCode @@ -131,8 +133,8 @@ sealed class Music : Item { FORMAT_AUXIO } - // Instead of making new string values for the mode, just append it's intCode - // in front of the UUID. So I guess it's technically not a true UUID, but whatever. + // Instead of making new string values for the mode, be lazy and just append it's + // intCode in front of the UUID. return "$format:${mode.intCode.toString(16)}-$uuid" } diff --git a/app/src/main/java/org/oxycblt/auxio/music/extractor/CacheLayer.kt b/app/src/main/java/org/oxycblt/auxio/music/extractor/CacheLayer.kt index 75965476f..5102b74e8 100644 --- a/app/src/main/java/org/oxycblt/auxio/music/extractor/CacheLayer.kt +++ b/app/src/main/java/org/oxycblt/auxio/music/extractor/CacheLayer.kt @@ -24,6 +24,9 @@ class CacheLayer { fun init() { } + // FIXME: Make the raw datatype use raw values, with most parsing being done in the song + // constructor to ensure cache coherency + /** * Write a list of newly-indexed raw songs to the database. */ diff --git a/app/src/main/java/org/oxycblt/auxio/music/dirs/MusicDirAdapter.kt b/app/src/main/java/org/oxycblt/auxio/music/settings/MusicDirAdapter.kt similarity index 98% rename from app/src/main/java/org/oxycblt/auxio/music/dirs/MusicDirAdapter.kt rename to app/src/main/java/org/oxycblt/auxio/music/settings/MusicDirAdapter.kt index 8b3156dab..f39b64fad 100644 --- a/app/src/main/java/org/oxycblt/auxio/music/dirs/MusicDirAdapter.kt +++ b/app/src/main/java/org/oxycblt/auxio/music/settings/MusicDirAdapter.kt @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package org.oxycblt.auxio.music.dirs +package org.oxycblt.auxio.music.settings import android.view.View import android.view.ViewGroup diff --git a/app/src/main/java/org/oxycblt/auxio/music/dirs/MusicDirs.kt b/app/src/main/java/org/oxycblt/auxio/music/settings/MusicDirs.kt similarity index 95% rename from app/src/main/java/org/oxycblt/auxio/music/dirs/MusicDirs.kt rename to app/src/main/java/org/oxycblt/auxio/music/settings/MusicDirs.kt index 748bd43c1..61db8e10c 100644 --- a/app/src/main/java/org/oxycblt/auxio/music/dirs/MusicDirs.kt +++ b/app/src/main/java/org/oxycblt/auxio/music/settings/MusicDirs.kt @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package org.oxycblt.auxio.music.dirs +package org.oxycblt.auxio.music.settings import org.oxycblt.auxio.music.Directory diff --git a/app/src/main/java/org/oxycblt/auxio/music/dirs/MusicDirsDialog.kt b/app/src/main/java/org/oxycblt/auxio/music/settings/MusicDirsDialog.kt similarity index 99% rename from app/src/main/java/org/oxycblt/auxio/music/dirs/MusicDirsDialog.kt rename to app/src/main/java/org/oxycblt/auxio/music/settings/MusicDirsDialog.kt index 0cb79bd92..cdb53db14 100644 --- a/app/src/main/java/org/oxycblt/auxio/music/dirs/MusicDirsDialog.kt +++ b/app/src/main/java/org/oxycblt/auxio/music/settings/MusicDirsDialog.kt @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package org.oxycblt.auxio.music.dirs +package org.oxycblt.auxio.music.settings import android.net.Uri import android.os.Bundle diff --git a/app/src/main/java/org/oxycblt/auxio/music/settings/SeparatorsDialog.kt b/app/src/main/java/org/oxycblt/auxio/music/settings/SeparatorsDialog.kt new file mode 100644 index 000000000..755899521 --- /dev/null +++ b/app/src/main/java/org/oxycblt/auxio/music/settings/SeparatorsDialog.kt @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2022 Auxio Project + * + * 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.settings + +import android.os.Bundle +import android.view.LayoutInflater +import androidx.appcompat.app.AlertDialog +import androidx.core.view.children +import com.google.android.material.checkbox.MaterialCheckBox +import org.oxycblt.auxio.BuildConfig +import org.oxycblt.auxio.R +import org.oxycblt.auxio.databinding.DialogSeparatorsBinding +import org.oxycblt.auxio.settings.Settings +import org.oxycblt.auxio.ui.fragment.ViewBindingDialogFragment +import org.oxycblt.auxio.util.context + +class SeparatorsDialog : ViewBindingDialogFragment() { + private val settings: Settings by lifecycleObject { binding -> Settings(binding.context) } + + override fun onCreateBinding(inflater: LayoutInflater) = + DialogSeparatorsBinding.inflate(inflater) + + override fun onConfigDialog(builder: AlertDialog.Builder) { + builder + .setTitle(R.string.set_separators) + .setNegativeButton(R.string.lbl_cancel, null) + .setPositiveButton(R.string.lbl_save) { _, _ -> + var separators = "" + val binding = requireBinding() + if (binding.separatorComma.isChecked) separators += SEPARATOR_COMMA + if (binding.separatorSemicolon.isChecked) separators += SEPARATOR_SEMICOLON + if (binding.separatorSlash.isChecked) separators += SEPARATOR_SLASH + if (binding.separatorPlus.isChecked) separators += SEPARATOR_PLUS + if (binding.separatorAnd.isChecked) separators += SEPARATOR_AND + settings.separators = separators + } + } + + override fun onBindingCreated(binding: DialogSeparatorsBinding, savedInstanceState: Bundle?) { + for (child in binding.separatorGroup.children) { + (child as MaterialCheckBox).isChecked = false + } + + settings.separators?.forEach { + when (it) { + SEPARATOR_COMMA -> binding.separatorComma.isChecked = true + SEPARATOR_SEMICOLON -> binding.separatorSemicolon.isChecked = true + SEPARATOR_SLASH -> binding.separatorSlash.isChecked = true + SEPARATOR_PLUS -> binding.separatorPlus.isChecked = true + SEPARATOR_AND -> binding.separatorAnd.isChecked = true + else -> error("Unexpected separator in settings data") + } + } + } + + companion object { + const val TAG = BuildConfig.APPLICATION_ID + ".tag.EXCLUDED" + + private const val SEPARATOR_COMMA = ',' + private const val SEPARATOR_SEMICOLON = ';' + private const val SEPARATOR_SLASH = '/' + private const val SEPARATOR_PLUS = '+' + private const val SEPARATOR_AND = '&' + } +} diff --git a/app/src/main/java/org/oxycblt/auxio/music/system/IndexerService.kt b/app/src/main/java/org/oxycblt/auxio/music/system/IndexerService.kt index 90272be9d..a5065d7f1 100644 --- a/app/src/main/java/org/oxycblt/auxio/music/system/IndexerService.kt +++ b/app/src/main/java/org/oxycblt/auxio/music/system/IndexerService.kt @@ -226,7 +226,8 @@ class IndexerService : Service(), Indexer.Controller, Settings.Callback { override fun onSettingChanged(key: String) { when (key) { getString(R.string.set_key_music_dirs), - getString(R.string.set_key_music_dirs_include) -> onStartIndexing() + getString(R.string.set_key_music_dirs_include), + getString(R.string.set_key_separators) -> onStartIndexing() getString(R.string.set_key_observing) -> { if (!indexer.isIndexing) { updateIdleSession() diff --git a/app/src/main/java/org/oxycblt/auxio/settings/Settings.kt b/app/src/main/java/org/oxycblt/auxio/settings/Settings.kt index a26cad628..5195cf60e 100644 --- a/app/src/main/java/org/oxycblt/auxio/settings/Settings.kt +++ b/app/src/main/java/org/oxycblt/auxio/settings/Settings.kt @@ -28,7 +28,7 @@ import org.oxycblt.auxio.IntegerTable import org.oxycblt.auxio.R import org.oxycblt.auxio.home.tabs.Tab import org.oxycblt.auxio.music.Directory -import org.oxycblt.auxio.music.dirs.MusicDirs +import org.oxycblt.auxio.music.settings.MusicDirs import org.oxycblt.auxio.music.ui.MusicMode import org.oxycblt.auxio.music.ui.Sort import org.oxycblt.auxio.playback.BarAction @@ -301,7 +301,7 @@ class Settings(private val context: Context, private val callback: Callback? = n inner.getString(context.getString(R.string.set_key_separators), null)?.ifEmpty { null } set(value) { inner.edit { - putString(context.getString(R.string.set_key_separators), value) + putString(context.getString(R.string.set_key_separators), value?.ifEmpty { null }) apply() } } diff --git a/app/src/main/java/org/oxycblt/auxio/settings/SettingsListFragment.kt b/app/src/main/java/org/oxycblt/auxio/settings/SettingsListFragment.kt index 4fa3cf5fe..fbfeda4a6 100644 --- a/app/src/main/java/org/oxycblt/auxio/settings/SettingsListFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/settings/SettingsListFragment.kt @@ -32,7 +32,8 @@ import coil.Coil import org.oxycblt.auxio.R import org.oxycblt.auxio.home.tabs.TabCustomizeDialog import org.oxycblt.auxio.music.MusicViewModel -import org.oxycblt.auxio.music.dirs.MusicDirsDialog +import org.oxycblt.auxio.music.settings.MusicDirsDialog +import org.oxycblt.auxio.music.settings.SeparatorsDialog import org.oxycblt.auxio.playback.PlaybackViewModel import org.oxycblt.auxio.playback.replaygain.PreAmpCustomizeDialog import org.oxycblt.auxio.settings.ui.IntListPreference @@ -107,6 +108,8 @@ class SettingsListFragment : PreferenceFragmentCompat() { .show(childFragmentManager, PreAmpCustomizeDialog.TAG) context.getString(R.string.set_key_music_dirs) -> MusicDirsDialog().show(childFragmentManager, MusicDirsDialog.TAG) + getString(R.string.set_key_separators) -> + SeparatorsDialog().show(childFragmentManager, SeparatorsDialog.TAG) else -> error("Unexpected dialog key ${preference.key}") } } diff --git a/app/src/main/res/layout/dialog_separators.xml b/app/src/main/res/layout/dialog_separators.xml new file mode 100644 index 000000000..05262399d --- /dev/null +++ b/app/src/main/res/layout/dialog_separators.xml @@ -0,0 +1,79 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 9f650ee07..8e33d337e 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -214,6 +214,8 @@ Content Reload music May wipe playback state + Automatic reloading + Reload your music library whenever it changes (Experimental) Music folders Manage where music should be loaded from @@ -224,8 +226,13 @@ Include Music will only be loaded from the folders you add. - Automatic reloading - Reload your music library whenever it changes (Experimental) + Multi-value separators + Configure the characters that denote multiple values in tags + Comma (,) + Semicolon (;) + Slash (/) + Plus (+) + Ampersand (&) No music found diff --git a/app/src/main/res/xml/prefs_main.xml b/app/src/main/res/xml/prefs_main.xml index 7d4df744f..948cecc4c 100644 --- a/app/src/main/res/xml/prefs_main.xml +++ b/app/src/main/res/xml/prefs_main.xml @@ -148,16 +148,21 @@ app:summary="@string/set_reindex_desc" app:title="@string/set_reindex" /> - - + + + + \ No newline at end of file