all: remove immature comments
Remove childish wording/diatribes from the codebase that were added when I was younger. I'm an adult now. I have to make this repository at least somewhat professional.
This commit is contained in:
parent
381286802d
commit
873f15ff40
17 changed files with 68 additions and 185 deletions
|
@ -144,9 +144,9 @@ class MainFragment :
|
|||
}
|
||||
|
||||
override fun onPreDraw(): Boolean {
|
||||
// CoordinatorLayout is insane and thus makes bottom sheet callbacks insane. Do our
|
||||
// checks before every draw, which is not ideal in the slightest but also has minimal
|
||||
// performance impact since we are only mutating attributes used during drawing.
|
||||
// We overload CoordinatorLayout far too much to rely on any of it's typical
|
||||
// callback functionality. Just update all transitions before every draw. Should
|
||||
// probably be cheap *enough.*
|
||||
val binding = requireBinding()
|
||||
|
||||
val playbackSheetBehavior =
|
||||
|
|
|
@ -26,7 +26,6 @@ import org.oxycblt.auxio.home.tabs.Tab
|
|||
import org.oxycblt.auxio.music.Album
|
||||
import org.oxycblt.auxio.music.Artist
|
||||
import org.oxycblt.auxio.music.Genre
|
||||
import org.oxycblt.auxio.music.Music
|
||||
import org.oxycblt.auxio.music.MusicMode
|
||||
import org.oxycblt.auxio.music.MusicStore
|
||||
import org.oxycblt.auxio.music.Song
|
||||
|
|
|
@ -33,9 +33,9 @@ import org.oxycblt.auxio.util.getColorCompat
|
|||
import org.oxycblt.auxio.util.getDrawableCompat
|
||||
|
||||
/**
|
||||
* View that displays the playback indicator. Nominally emulates [StyledImageView], but is much
|
||||
* different internally as an animated icon can't be wrapped within StyledDrawable without causing
|
||||
* insane issues.
|
||||
* View that displays the playback indicator. Nominally emulates [StyledImageView], but
|
||||
* relies on the existing ImageView infrastructure to achieve the same result while also
|
||||
* allowing animation to work.
|
||||
* @author OxygenCobalt
|
||||
*/
|
||||
class IndicatorView
|
||||
|
|
|
@ -83,10 +83,8 @@ abstract class BaseFetcher : Fetcher {
|
|||
// First try MediaMetadataRetriever. We will always do this first, as it supports
|
||||
// a variety of formats, has multiple levels of fault tolerance, and is pretty fast
|
||||
// for a manual parser.
|
||||
// However, Samsung seems to cripple this class as to force people to use their ad-infested
|
||||
// music app which relies on proprietary OneUI extensions instead of AOSP. That means
|
||||
// we have to add even more layers of redundancy to make sure we can extract a cover.
|
||||
// Thanks Samsung. Prick.
|
||||
// However, this does not seem to work on some devices (Notably Samsung), so we
|
||||
// have to have redundancy.
|
||||
fetchAospMetadataCovers(context, album)
|
||||
?: fetchExoplayerCover(context, album) ?: fetchMediaStoreCovers(context, album)
|
||||
|
||||
|
@ -109,12 +107,12 @@ abstract class BaseFetcher : Fetcher {
|
|||
|
||||
// future.get is a blocking call that makes us spin until the future is done.
|
||||
// This is bad for a co-routine, as it prevents cancellation and by extension
|
||||
// messes with the image loading process and causes frustrating bugs.
|
||||
// messes with the image loading process and causes annoying bugs.
|
||||
// To fix this we wrap this around in a withContext call to make it suspend and make
|
||||
// sure that the runner can do other coroutines.
|
||||
@Suppress("BlockingMethodInNonBlockingContext")
|
||||
val tracks =
|
||||
withContext(Dispatchers.IO) {
|
||||
withContext(Dispatchers.Default) {
|
||||
try {
|
||||
future.get()
|
||||
} catch (e: Exception) {
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
package org.oxycblt.auxio.music.extractor
|
||||
|
||||
import android.content.Context
|
||||
|
@ -39,62 +39,6 @@ import org.oxycblt.auxio.util.contentResolverSafe
|
|||
import org.oxycblt.auxio.util.getSystemServiceCompat
|
||||
import org.oxycblt.auxio.util.logD
|
||||
|
||||
/*
|
||||
* This file acts as the base for most the black magic required to get a remotely sensible music
|
||||
* indexing system from MediaStore while still optimizing for time. I would recommend you leave
|
||||
* this file now before you lose your sanity trying to understand the hoops I had to jump through
|
||||
* for this system, but if you really want to stay, here's a debrief on why this code is so awful.
|
||||
*
|
||||
* MediaStore is not a good API. It is not even a bad API. Calling it a bad API is an insult to
|
||||
* other bad android APIs, like CoordinatorLayout or InputMethodManager. No. MediaStore is a crime
|
||||
* against humanity and probably a way to summon Zalgo if you look at it the wrong way.
|
||||
*
|
||||
* You think that if you wanted to query a song's genre from a media database, you could just put
|
||||
* "genre" in the query and it would return it, right? But not with MediaStore! No, that's too
|
||||
* straightforward for this database that was dropped on it's head as a baby. So instead, you have
|
||||
* to query for each genre, query all the songs in each genre, and then iterate through those songs
|
||||
* to link every song with their genre. This is not documented anywhere, and the O(mom im scared)
|
||||
* algorithm you have to run to get it working single-handedly DOUBLES Auxio's query times. At no
|
||||
* point have the devs considered that this system is absolutely insane, and instead focused on
|
||||
* adding infuriat- I mean nice proprietary extensions to MediaStore for their own Google Play
|
||||
* Music, and of course every Google Play Music user knew how great that turned out!
|
||||
*
|
||||
* It's not even ergonomics that makes this API bad. It's base implementation is completely borked
|
||||
* as well. Did you know that MediaStore doesn't accept dates that aren't from ID3v2.3 MP3 files? I
|
||||
* sure didn't, until I decided to upgrade my music collection to ID3v2.4 and FLAC only to see that
|
||||
* the metadata parser has a brain aneurysm the moment it stumbles upon a dreaded TRDC or DATE tag.
|
||||
* Once again, this is because internally android uses an ancient in-house metadata parser to get
|
||||
* everything indexed, and so far they have not bothered to modernize this parser or even switch it
|
||||
* to something that actually works, not even in Android 12. ID3v2.4 has been around for *21
|
||||
* years.* *It can drink now.*
|
||||
*
|
||||
* Not to mention all the other infuriating quirks. Pretty much every OEM has added some extension
|
||||
* or quirk to MediaStore that I cannot reproduce, with some OEMs (COUGHSAMSUNGCOUGH) crippling the
|
||||
* normal tables so that you're railroaded into their music app. I have to use a semi-deprecated
|
||||
* field to work with file paths, and the supposedly "modern" method is SLOWER and causes even more
|
||||
* problems since some devices just don't expose those fields for some insane reason. Sometimes
|
||||
* music will have a deformed clone that I can't filter out, sometimes Genres will just break for
|
||||
* no reason, and sometimes tags encoded in UTF-8 will be interpreted as anything from UTF-16 to
|
||||
* Latin-1 to *Shift JIS* WHY WHY WHY WHY WHY WHY WHY WHY WHY WHY WHY WHY WHY WHY WHY WHY WHY WHY
|
||||
*
|
||||
* Is there anything we can do about it? No. Google has routinely shut down issues that begged
|
||||
* google to fix glaring issues with MediaStore or to just take the API behind the woodshed and
|
||||
* shoot it. Largely because they have zero incentive to improve it given how "obscure" local music
|
||||
* listening is. As a result, I am forced to write my own extractor (Which is the contents of the
|
||||
* rest of this module) based on ExoPlayer that at least tries to correct the insane metadata that
|
||||
* this API returns, but not only is that system horrifically slow and bug-prone, it also faces the
|
||||
* even larger issue of how google keeps trying to kill the filesystem and force you into their
|
||||
* ContentResolver API. In the future MediaStore could be the only system we have, which is also
|
||||
* the day that greenland melts and birthdays stop happening forever.
|
||||
*
|
||||
* I'm pretty sure nothing is going to happen and MediaStore will continue to be neglected and
|
||||
* probably deprecated eventually for a "new" API that just coincidentally excludes music indexing.
|
||||
* Because go screw yourself for wanting to listen to music you own. Be a good consoomer and listen
|
||||
* to your AlgoPop StreamMix™.
|
||||
*
|
||||
* I wish I was born in the neolithic.
|
||||
*/
|
||||
|
||||
/**
|
||||
* The layer that loads music from the MediaStore database. This is an intermediate step in the
|
||||
* music loading process.
|
||||
|
@ -205,7 +149,8 @@ abstract class MediaStoreExtractor(
|
|||
// Since we can't obtain the genre tag from a song query, we must construct
|
||||
// our own equivalent from genre database queries. Theoretically, this isn't
|
||||
// needed since MetadataLayer will fill this in for us, but I'd imagine there
|
||||
// are some obscure formats where genre support is only really covered by this.
|
||||
// are some obscure formats where genre support is only really covered by this,
|
||||
// so we are forced to bite the O(n^2) complexity here.
|
||||
context.contentResolverSafe.useQuery(
|
||||
MediaStore.Audio.Genres.EXTERNAL_CONTENT_URI,
|
||||
arrayOf(MediaStore.Audio.Genres._ID, MediaStore.Audio.Genres.NAME)) { genreCursor ->
|
||||
|
|
|
@ -33,9 +33,9 @@ import org.oxycblt.auxio.util.logW
|
|||
/**
|
||||
* The layer that leverages ExoPlayer's metadata retrieval system to index metadata.
|
||||
*
|
||||
* Normally, leveraging ExoPlayer's metadata system would be a terrible idea, as it is horrifically
|
||||
* slow. However, if we parallelize it, we can get similar throughput to other metadata extractors,
|
||||
* which is nice as it means we don't have to bundle a redundant metadata library like JAudioTagger.
|
||||
* Normally, ExoPlayer's metadata system is quite slow. However, if we parallelize it, we can get
|
||||
* similar throughput to other metadata extractors, which is nice as it means we don't have to
|
||||
* bundle a redundant metadata library like JAudioTagger.
|
||||
*
|
||||
* Now, ExoPlayer's metadata API is not the best. It's opaque, undocumented, and prone to weird
|
||||
* pitfalls given ExoPlayer's cozy relationship with native code. However, this backend should do
|
||||
|
@ -312,16 +312,8 @@ class Task(context: Context, private val raw: Song.Raw) {
|
|||
}
|
||||
|
||||
/**
|
||||
* Copies and sanitizes this string under the assumption that it is UTF-8.
|
||||
*
|
||||
* Sometimes ExoPlayer emits weird UTF-8. Worse still, sometimes it emits strings backed by data
|
||||
* allocated by some native function. This could easily cause a terrible crash if you even look
|
||||
* at the malformed string the wrong way.
|
||||
*
|
||||
* This function mitigates it by first encoding the string as UTF-8 bytes (replacing malformed
|
||||
* characters with the replacement in the process), and then re-interpreting it as a new string,
|
||||
* which hopefully fixes encoding insanity while also copying the string out of dodgy native
|
||||
* memory.
|
||||
* Copies and sanitizes this string under the assumption that it is UTF-8. This should
|
||||
* launder away any weird UTF-8 issues that ExoPlayer may cause.
|
||||
*/
|
||||
private fun String.sanitize() = String(encodeToByteArray())
|
||||
}
|
||||
|
|
|
@ -25,8 +25,8 @@ import org.oxycblt.auxio.music.Song
|
|||
import org.oxycblt.auxio.playback.state.PlaybackStateManager
|
||||
|
||||
/**
|
||||
* Class enabling more advanced queue list functionality and queue editing.
|
||||
* TODO: Allow editing previous parts of the queue
|
||||
* Class enabling more advanced queue list functionality and queue editing. TODO: Allow editing
|
||||
* previous parts of the queue
|
||||
* @author OxygenCobalt
|
||||
*/
|
||||
class QueueViewModel : ViewModel(), PlaybackStateManager.Callback {
|
||||
|
|
|
@ -34,11 +34,10 @@ import org.oxycblt.auxio.util.logE
|
|||
import org.oxycblt.auxio.util.logW
|
||||
|
||||
/**
|
||||
* Master class (and possible god object) for the playback state.
|
||||
* Core playback controller class.
|
||||
*
|
||||
* Whereas other apps centralize the playback state around the MediaSession, Auxio does not, as
|
||||
* MediaSession is a terrible API that prevents nice features like better album cover loading or a
|
||||
* reasonable queue system.
|
||||
* MediaSession is poorly designed. We use our own playback state system instead.
|
||||
*
|
||||
* This should ***NOT*** be used outside of the playback module.
|
||||
* - If you want to use the playback state in the UI, use
|
||||
|
|
|
@ -40,20 +40,10 @@ import org.oxycblt.auxio.settings.Settings
|
|||
import org.oxycblt.auxio.util.logD
|
||||
|
||||
/**
|
||||
* The component managing the [MediaSessionCompat] instance, alongside the [NotificationComponent]
|
||||
* The component managing the [MediaSessionCompat] instance, alongside the [NotificationComponent].
|
||||
*
|
||||
* MediaSession is easily one of the most poorly thought out APIs in Android. It tries to hard to be
|
||||
* hElpfUl and implement so many fundamental behaviors into a one-size-fits-all package that it only
|
||||
* ends up causing bugs and frustration. The queue system is horribly designed, the playback state
|
||||
* system has unending coherency issues, and the overstretched abstractions result in god-awful
|
||||
* performance bottlenecks and insane state bugs.
|
||||
*
|
||||
* The sheer absurdity of the hoops we have jump through to get this working in an okay manner is
|
||||
* the reason why Auxio only mirrors a saner playback state to the media session instead of relying
|
||||
* on it. I thought that Android 13 would at least try to make the state more coherent, but NOPE.
|
||||
* You still have to do a delicate dance of posting notifications and updating the session state
|
||||
* while also keeping in mind the absurd rate limiting system in place just to have a sort-of
|
||||
* coherent state. And even then it will break if you skip too much.
|
||||
* Auxio does not directly rely on MediaSession, as it is extremely poorly designed. We instead
|
||||
* just mirror the playback state into the media session.
|
||||
*
|
||||
* @author OxygenCobalt
|
||||
*/
|
||||
|
@ -165,17 +155,9 @@ class MediaSessionComponent(private val context: Context, private val callback:
|
|||
|
||||
song.date?.let { builder.putString(MediaMetadataCompat.METADATA_KEY_DATE, it.toString()) }
|
||||
|
||||
// Cover loading is a mess. Android expects you to provide a clean, easy URI for it to
|
||||
// leverage, but Auxio cannot do that as quality-of-life features like scaling or
|
||||
// 1:1 cropping could not be used.
|
||||
//
|
||||
// Thus, we have two options to handle album art:
|
||||
// 1. Load the bitmap, then post the notification
|
||||
// 2. Post the notification with text metadata, then post it with the bitmap when it's
|
||||
// loaded.
|
||||
//
|
||||
// Neither of these are good, but 1 is the only one that will work on all versions
|
||||
// without the notification being eaten by rate-limiting.
|
||||
// We are normally supposed to use URIs for album art, but that removes some of the
|
||||
// nice things we can do like square cropping or high quality covers. Instead,
|
||||
// we load a full-size bitmap into the media session and take the performance hit.
|
||||
provider.load(
|
||||
song,
|
||||
object : BitmapProvider.Target {
|
||||
|
|
|
@ -27,17 +27,8 @@ import org.oxycblt.auxio.util.inflater
|
|||
import org.oxycblt.auxio.util.logD
|
||||
|
||||
/**
|
||||
* A wrapper around [Slider] that shows not only position and duration values, but also basically
|
||||
* hacks in behavior consistent with a normal SeekBar in a way that will not crash the app.
|
||||
*
|
||||
* SeekBar, like most android OS components, is a version-specific mess that requires constant hacks
|
||||
* on older versions. Instead, we use the more "modern" [Slider] component, but it is not designed
|
||||
* for the job that Auxio's progress bar has. It does not gracefully degrade when positions don't
|
||||
* make sense (which happens incredibly often), it just crashes the entire app, which is insane but
|
||||
* also checks out for something more meant for configuration than seeking.
|
||||
*
|
||||
* Instead, we wrap it in a safe class that hopefully implements enough sanity checks to not crash
|
||||
* the app or result in blatantly janky behavior. Mostly.
|
||||
* A wrapper around [Slider] that shows not only position and duration values, but also hacks
|
||||
* in bounds checking to avoid app crashes if bad position input comes in.
|
||||
*
|
||||
* @author OxygenCobalt
|
||||
*/
|
||||
|
|
|
@ -79,15 +79,8 @@ class PreferenceFragment : PreferenceFragmentCompat() {
|
|||
override fun onDisplayPreferenceDialog(preference: Preference) {
|
||||
when (preference) {
|
||||
is IntListPreference -> {
|
||||
// Creating our own preference dialog is hilariously difficult. For one, we need
|
||||
// to override this random method within the class in order to launch the dialog in
|
||||
// the first (because apparently you can't just implement some interface that
|
||||
// automatically provides this behavior), then we also need to use a deprecated
|
||||
// method to adequately supply a "target fragment" (otherwise we will crash since
|
||||
// the dialog requires one), and then we need to actually show the dialog, making
|
||||
// sure we use the parent FragmentManager as again, it will crash if we don't.
|
||||
//
|
||||
// Fragments were a mistake.
|
||||
// Copy the built-in preference dialog launching code into our project so
|
||||
// we can automatically use the provided preference class.
|
||||
val dialog = IntListPreferenceDialog.from(preference)
|
||||
dialog.setTargetFragment(this, 0)
|
||||
dialog.show(parentFragmentManager, IntListPreferenceDialog.TAG)
|
||||
|
|
|
@ -1,3 +1,20 @@
|
|||
/*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.oxycblt.auxio.ui
|
||||
|
||||
import androidx.lifecycle.ViewModel
|
||||
|
@ -23,4 +40,4 @@ class SelectionViewModel : ViewModel() {
|
|||
_selected.value = items
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -199,12 +199,13 @@ val AndroidViewModel.application: Application
|
|||
fun <R> SQLiteDatabase.queryAll(tableName: String, block: (Cursor) -> R) =
|
||||
query(tableName, null, null, null, null, null, null)?.use(block)
|
||||
|
||||
// Note: WindowInsetsCompat and it's related methods are an over-engineered mess that does not
|
||||
// work for Auxio's use-case. Use our own compat methods instead.
|
||||
// Note: WindowInsetsCompat and it's related methods cause too many issues.
|
||||
// Use our own compat methods instead.
|
||||
|
||||
|
||||
/**
|
||||
* Resolve system bar insets in a version-aware manner. This can be used to apply padding to a view
|
||||
* that properly follows all the frustrating changes that were made between Android 8-11.
|
||||
* that properly follows all the changes that were made between Android 8-11.
|
||||
*/
|
||||
val WindowInsets.systemBarInsetsCompat: Insets
|
||||
get() =
|
||||
|
@ -217,8 +218,8 @@ val WindowInsets.systemBarInsetsCompat: Insets
|
|||
|
||||
/**
|
||||
* Resolve gesture insets in a version-aware manner. This can be used to apply padding to a view
|
||||
* that properly follows all the frustrating changes that were made between Android 8-11. Note that
|
||||
* if the gesture insets are not present (i.e zeroed), the bar insets will be used instead.
|
||||
* that properly follows all the changes that were made between Android 8-11. Note that if the
|
||||
* gesture insets are not present (i.e zeroed), the bar insets will be used instead.
|
||||
*/
|
||||
val WindowInsets.systemGestureInsetsCompat: Insets
|
||||
get() =
|
||||
|
@ -241,7 +242,7 @@ val WindowInsets.systemGestureInsetsCompat: Insets
|
|||
}
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
fun WindowInsets.getSystemWindowCompatInsets() =
|
||||
private fun WindowInsets.getSystemWindowCompatInsets() =
|
||||
Insets.of(
|
||||
systemWindowInsetLeft,
|
||||
systemWindowInsetTop,
|
||||
|
@ -250,14 +251,14 @@ fun WindowInsets.getSystemWindowCompatInsets() =
|
|||
|
||||
@Suppress("DEPRECATION")
|
||||
@RequiresApi(Build.VERSION_CODES.Q)
|
||||
fun WindowInsets.getSystemGestureCompatInsets() = Insets.toCompatInsets(systemGestureInsets)
|
||||
private fun WindowInsets.getSystemGestureCompatInsets() = Insets.toCompatInsets(systemGestureInsets)
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.R)
|
||||
fun WindowInsets.getCompatInsets(typeMask: Int) = Insets.toCompatInsets(getInsets(typeMask))
|
||||
private fun WindowInsets.getCompatInsets(typeMask: Int) = Insets.toCompatInsets(getInsets(typeMask))
|
||||
|
||||
/**
|
||||
* Replaces the system bar insets in a version-aware manner. This can be used to modify the insets
|
||||
* for child views in a way that follows all of the frustrating changes that were made between 8-11.
|
||||
* for child views in a way that follows all of the changes that were made between 8-11.
|
||||
*/
|
||||
fun WindowInsets.replaceSystemBarInsetsCompat(
|
||||
left: Int,
|
||||
|
|
|
@ -34,7 +34,7 @@ fun Any.logD(obj: Any?) = logD("$obj")
|
|||
* objects
|
||||
*/
|
||||
fun Any.logD(msg: String) {
|
||||
if (BuildConfig.DEBUG && !basedCopyleftNotice()) {
|
||||
if (BuildConfig.DEBUG && !copyleftNotice()) {
|
||||
Log.d(autoTag, msg)
|
||||
}
|
||||
}
|
||||
|
@ -50,37 +50,11 @@ private val Any.autoTag: String
|
|||
get() = "Auxio.${this::class.simpleName ?: "Anonymous Object"}"
|
||||
|
||||
/**
|
||||
* Note: If you are politely forking this project while keeping the source open, you can ignore the
|
||||
* following passage. If not, give me a moment of your time.
|
||||
*
|
||||
* Consider what you are doing with your life, plagiarizers. Do you want to live a fulfilling
|
||||
* existence on this planet? Or do you want to spend your life taking work others did and making it
|
||||
* objectively worse so you could arbitrage a fraction of a penny on every AdMob impression you get?
|
||||
* You could do so many great things if you simply had the courage to come up with an idea of your
|
||||
* own.
|
||||
*
|
||||
* If you still want to go on, I guess the only thing I can say is this:
|
||||
*
|
||||
* JUNE 1989 TIANAMEN SQUARE PROTESTS AND MASSACRE / 六四事件
|
||||
*
|
||||
* 2022 RUSSIAN INVASION OF UKRAINE / ВТОРЖЕНИЕ РОССИИ НА УКРАИНУ
|
||||
*
|
||||
* WOMEN'S RIGHTS IN THE ISLAMIC REPUBLIC OF IRAN / حقوق زنان در ایران
|
||||
*
|
||||
* UYGHUR GENOCIDE/XINJIANG INTERNMENT CAMPS / 新疆种族灭绝指控/新疆再教育營
|
||||
*
|
||||
* KASHMIR INDEPENDENCE MOVEMENT
|
||||
*
|
||||
* FREE TIBET / 西藏自由
|
||||
*
|
||||
* 1915-1916 ARMENIAN GENOCIDE / ERMENI KIRIMI
|
||||
*
|
||||
* 2018 TORTURE AND ASSASSINATION OF JAMAL KHASHOGGI / مقتل جمال خاشقجي
|
||||
*
|
||||
* UNITED ARAB EMIRATES ENSLAVED MIGRANT WORKERS
|
||||
* Please don't plagiarize Auxio! You are free to remove this as long as you continue to keep your
|
||||
* source open.
|
||||
*/
|
||||
@Suppress("KotlinConstantConditions")
|
||||
private fun basedCopyleftNotice(): Boolean {
|
||||
private fun copyleftNotice(): Boolean {
|
||||
if (BuildConfig.APPLICATION_ID != "org.oxycblt.auxio" &&
|
||||
BuildConfig.APPLICATION_ID != "org.oxycblt.auxio.debug") {
|
||||
Log.d(
|
||||
|
|
|
@ -4,13 +4,6 @@
|
|||
xmlns:tools="http://schemas.android.com/tools"
|
||||
app:startDestination="@id/home_fragment">
|
||||
|
||||
<!--
|
||||
Now, it would be quite cool if we could implement shared element transitions
|
||||
between elements in this navigation web. Sadly though, the shared element transition
|
||||
system is filled with so many bugs and visual errors to make this a terrible idea.
|
||||
Just use the boring, yet sane and functional axis transitions.
|
||||
-->
|
||||
|
||||
<fragment
|
||||
android:id="@+id/artist_detail_fragment"
|
||||
android:name="org.oxycblt.auxio.detail.ArtistDetailFragment"
|
||||
|
|
|
@ -155,7 +155,7 @@ Monitoring the loading progress (Internally called the indexing state) should be
|
|||
and is best done with `MusicViewModel`.
|
||||
|
||||
#### Playback System
|
||||
The android/androidx media state APIs are terrible, and are often the cause of the strange queue
|
||||
The android/androidx media state APIs are poorly designed, and are often the cause of the strange queue
|
||||
behavior and jank you see in other apps. So, Auxio does not use it, instead implementing it's own
|
||||
playback engine that is more controllable and sensible and simply mirroring it to the android APIs.
|
||||
|
||||
|
@ -246,7 +246,7 @@ playing indicator and one custom view.
|
|||
#### `.music`
|
||||
This package contains all `Music` implementations, the music loading implementation, and the music
|
||||
folder system. This is the second most complicated package in the app, as loading music in a sane
|
||||
way is horribly difficult.
|
||||
way is quite difficult.
|
||||
|
||||
The major classes are:
|
||||
- `MusicStore`, which is the container for a `Library` instance. Any code wanting to access the
|
||||
|
@ -314,8 +314,7 @@ default implementations.
|
|||
- `ForegroundManager` and `ServiceNotification`, which remove boilerplate regarding service
|
||||
foreground instantiation.
|
||||
- The `RecyclerView` adapter framework described previously.
|
||||
- `BottomSheetLayout`, which implements a bottom sheet in a way that is not completely broken and
|
||||
insane.
|
||||
- `BottomSheetLayout`, which implements a bottom sheet in a way that is not completely broken.
|
||||
- Standard `ViewHolder` implementations that can be used for common datatypes.
|
||||
- `NavigationViewModel`, which acts as an interface to control navigation to a particular item and
|
||||
navigation within `MainFragment`
|
||||
|
|
|
@ -47,7 +47,7 @@ metadata parser is stuck in 2008.
|
|||
|
||||
**Some files with accented/symbolic characters have corrupted tags:** When Android extracts metadata, at some point it tries to convert the bytes it extracted to a
|
||||
java string, which apparently involves detecting the encoding of the data dynamically and then converting it to Java's Unicode dialect. Of course, trying to detect
|
||||
codings on the fly like that is a [terrible idea](https://en.wikipedia.org/wiki/Bush_hid_the_facts), and more often than not it results in UTF-8 tags (Seen on
|
||||
codings on the fly like that is a [bad idea](https://en.wikipedia.org/wiki/Bush_hid_the_facts), and more often than not it results in UTF-8 tags (Seen on
|
||||
FLAC/OGG/OPUS files most often) being corrupted. It also affects MP3 files with ID3v2.4.0 tags that use the UTF-8 encoding in text-based tags.
|
||||
|
||||
**I have a large library and Auxio takes really long to load it:** This is expected since reading from the audio database takes awhile, especially with libraries
|
||||
|
|
Loading…
Reference in a new issue