Move everything over to the media3 library instead of ExoPlayer.
Media3 is worse in every way. It labels half of ExoPlayer as "unsafe"
because it thinks that it's garbage uwu "helpful" abstractions are
perfectly servicable when in reality they are a pile of garbage filled
with insane performance issues, race conditions, and a seeming lack
of awareness to the sheer absurdity of android's media APIs. It is
absolutely horrible, but ExoPlayer will stop being maintained soon
and I will have to move over for further maintenance.
Fix an issue where stripping of the FFMpeg extension would not occur,
as AGP would try to default to an entirely different NDK version.
Eventually I'm considering just vendoring the FFMpeg extension outright
once I can upstream some of the ExoPlayer patches.
Move the ExoPlayer build process into gradle by leveraging some shell
scripting and submodule magic.
This more or less kills all windows compatibility, but that is fine.
Who even develops on windows?
FINALLY update to MDC 1.7.0. After over half a year.
I have been continually blocked by doing this due to this absurd ripple
bug that was so continually frustrating. Today, I finally figred out
how to hack a fix in by using R E F L E C T I O N and manually
disabling the bugged code path since google apparently can't be bothered
to fix it.
Now, you might wonder why I didn't update to 1.8.0. That is because
there is ANOTHER RIPPLE BUG. THIS TIME WITH THE TAB LAYOUT. AND ONLY IF
IT'S IN A COLLAPSING TOOLBAR LAYOUT. Can't wait to finally use the new
1.8.0 features in December!
Use dependency injection with Coil.
This allows me to use the coil-base artifact which should remove a bit
of superfluous dexcode, assuming dagger uses less. It probably doesn't.
Finally give up and use Room to persist the playback state.
This should make dependency injection much easier, and the
implementation isn't exactly the *worst*, as I was already using
"raw" data structures for the old queue database.
Manually use our own navigation graph in the new settings view.
This avoids a crash that occurs with the default preferences navigation
(on some devices) where the differing app IDs between debug and release
makes it so that the fragments cannot be found. Because you know.
Android.
Unify the "Show Covers" and "Ignore MediaStore Covers" settings under an
new "Album covers" setting.
This will make it easier to extend to new forms of album cover
collection.
Add caching of already-parsed tag data.
This greatly reduces loading times when the music library has not
changed. This completes the music loader in it's entirety now.
Resolves#207.
Add support for ID3v2.4-style multi-value tags separated by a null
terminator.
This temporarily removes most other forms of separator parsing in the
app. My plan is to reunify it under a new separator setting that allows
the user to select how multi-value tags are separated in their library.
Separator parsing tends to be too destructive by default, so this tends
to be a good option overall.
This commit does require ExoPlayer to be forked once again to add
ID3v2.4 separator support.
Completely rework the ID system to pave the way to MusicBrainz ID
support and greatly increase ID integrity in general.
This changeset removes the old ID field, an emulation of a polynomial
hash that was used in all items, and replaces it with a new type called
UID that is specific to Music. Other types just use plain equals now,
and most instances of "id" to check for equality in the app have either
been inlined into an equals override or removed outright.
The new UID format is as follows:
datatype/format:uuid
Datatype is a tag that is just the lowercase tag name. For example,
"song". Format is the program that created the UID. auxio will be an
md5 hash, and musicbrainz will the a musicbrainz ID extracted from a
file. UUID is the uuid itself.
This is much more reliable and extendable than the old ID format. This
will also be the last time I break compat with old ID formats. From now
on, a legacy UID field will not be included to enable backwards compat,
when the time comes for a breaking change.
Make the playing indicator animate when playback is ongoing.
Previously state issues stopped me from doing this, but apparently this
time I miraculously got it working. Yay.
Resolves#218.
FINALLY upgrade to android 13.
I cannot believe it had to take until the release of the version to
finally update the SDK version, but of course it had to. For some
insane reason that I have no idea why it passed QA, the 33 SDK had
a crippling issue where attributes were not recognized. The only
way to fix this was to:
1. Upgrade to the newer studio version (Chipmunk Patch 2)
2. Upgrade to AGP 7.3.0-beta05.
Funny thing though. AGP 7.3.0 IS NOT COMPATIBLE WITH CHIPMUNK. Okay,
so we can upgrade to Dolphin then and then we can use AGP, right?
HAHAHA NOPE! Dolphin hasn't patched out the XML issue yet despite
every other release channel having a release on August 3rd. Did
some engineer at google just forget to make a release? What?
Okay, so I guess I'm forced to use Electric Eel, the UNSTABLE CANARY
VERSION that IS FILLED WITH BUGS. But oh wait, Electric Eel doesn't
like AGP 7.3.0 EITHER! It wants AGP 7.4.0, which IS ALSO IN ALPHA.
So, I'm forced to use the ALPHA studio and the ALPHA AGP version just
to use the android 13 SDK in a way that is not completely unbearable.
The android SDK, everyone.
(This is not a cry for help, I just want to write down my infinite
frustration with this stupid goose chase somewhere)
Remove EdgeCoordinatorLayout in favor of using fitsSystemWindows when
needed.
EdgeCoordinatorLayout was derived from a misunderstanding about how
window insets worked. Remove it.
Fix lints that have accumulated over time.
Apparently Android Studio just...stopped using lints. For no reason. I
had to upgrade to the beta version to actually get lints.
Fix two issues where Auxio's widget could not be resized to a single
cell, and another where covers would not load into the widget.
The first is caused by a random, subtle change that completely changed
up the minHeight size calculation regarding widgets. Thus, we need to
lower it for android to recognize it still as 1 cell. I cannot believe
we can't just specify the specific minimum grid size that our widget
takes up, like you know, iOS did, nearly a decade after widgets were
first added in Android.
The second is an absurd race condition stemming from me hitting the
RemoteViews memory limit. Turns out my cover bitmaps were simply too
big. Getting them below the limit requires me to resize them to a puny
~500 pixels. Why can't we just render our own views into our widget?
You know, like iOS did, nearly a decade after widgets were first added
to Android.
Nah, screw modernizing the broken widget API. Let's just vaguely copy
iOS widgets because we have to while not fixing a single issue plaguing
widget development on this OS. That way some google engineer can get
promoted faster.
Expose the queue in the MediaSession, at least I hope.
The queue is still not mutable. Don't feel comfortable implementing that
until I rework the in-app queue UI.
Rework album types into release types, with additional support for live
albums, remixes, and mixtapes.
This is not a complete implementation, nor is it meant to be. I don't
want to add technical complexity handling Remix Compilations or
DJ-Mixes unless there is demand.
Update MDC to the alpha version in order to use some extra features.
I was planning to switch to the new MaterialSwitch, but alpha03 has
this insane crippling issue with ripples that blocks such. Use alpha02
and prep the app for the addition of the switch.
Add a new Date class to represent both years and more fine-grained
dates extracted using the ExoPlayer metadata system.
In-app, the year is still shown, but sorting will use the new precision
when present. The MediaSession will also post an RFC 3339 formatted
date with this new precision, as the MediaSession documentation states
I should. No clue if the latter will cause any bugs with naive metadata
UIs in other apps.
Resolves#159.
Fix two major highlighting bugs based around the janky and stupid way
I would handle highlighting previously.
Previously, I would index the views of a RecyclerView in order to
highlight viewholders. In retrospect this was a pretty bad idea,
as viewholders could be in a weird limbo state where they are bound,
but not accessible. I mean, it's in the name. It's a Recycling View.
Fortunately, google actually knew what they were doing and provided
a way to mutate viewholders at runtime using notifyItemChanged.
And the API actually makes sense! Wow! Migrate all detail adapters
to a system that uses notifyItemChanged instead of the terrible
pre-existing system.
Fix a regression where media button controls would no longer work
with GadgetBridge.
In 4a79de4, I assumed that my code was redundant, as there should be
some kind of reciever handling media button events already. I was
completely wrong. Re-add the reciever code (with extra checks) to
make controls work again.
Switch from LiveData to StateFlow.
While LiveData is a pretty good data storage/observer mechanism, it has
a few flaws:
- Values are always nullable in LiveData, even if you make them
non-null.
- LiveData can only be mutated on Dispatchers.Main, which frustrates
possible additions like a more fine-grained music status system.
- LiveData's perks are exclusive to ViewModels, which made coupling
with shared objects somewhat cumbersome.
StateFlow solves all of these by being a native coroutine solution with
proper android bindings. Use it instead.
Move the loading screen into the home view.
Previously, we would use a Snackbar to track the music loading state.
This ended up being a pretty stupid and buggy idea, and would get even
worse with the new music loader changes. Instead, we re-implement the
loading screen into the home view to generally be more sane and
extendable compared to previously.
Revert the introduction of the thin/tiny widgets, but keep the new
cover layout I created while working on them.
There is simply no way I can cram controls and metadata within the
size bucket that the thin widget occupies. I have decided to give up
and revert the widget to it's old form.
I understand why the thin widget is not appealing. However, the sizing
at which a widget can properly accomodate a taller widget is just too
precise and not really large enough to justify it's existance.
Do some miscellanious formatting reworks.
1. Remove all instances of m in favor of _. _ is only used when names
collide or if something should be internal.
2. Make fragments apply their own click listeners.
3. Remove instances of inc/dec and replace them with the more
straightfoward + 1 or - 1.
Rework the style of all album covers in the app to be more in line with
the new track number style.
This is mostly comprised of adding a new background to all cover views
and rescaling error icons to be smaller than they would normally be.
This also includes a change in the cover/track background color from
colorSurfaceVariant to colorOnSurfaceInverse, which seems to provide
the best visibility in all cases.
These changes also apply to the track number views.
Update the album song layout to be more alike to other songs.
Recently I migrated the TextView in the album songs to use 48dp sizing,
like the other song views. However, this resulted in a lot of empty
space that felt off. Fix this by adding a light background to the track
number, which fills the room it takes up a bit more. It also hopefully
primes the track number to take an indicator once multi-select is
added.
Remove databinding entirely.
Databinding was a terrible idea for Auxio. I rarely leveraged it, and
when I did, it produced messy code and bloated build times. Dumpster it
for just viewbinding, which is good. This reduces building times by
nearly 2/3, and generally makes the codebase more coherent and usable.
Switch to the spotless linter with ktfmt used as a backend instead of
ktlint.
This switch was done for two reasons:
1. ktfmt is more thorough than ktlint
2. License headers can be added more effectively with spotless than
the default Android Studio behavior.
Dump all of the changes now so I don't have to deal with it over a long
period of time. I don't care.