Start injecting shared object instances.
This is not a 100% conversion, as certain portions of the code are not
really ready for 100% DI constructors just yet.
Parallelize music loading.
- Queries over Media DB and Cache are ran parallel
- MediaStoreExtractor can now continue extracting songs independent
of MetadataExtractor's task pool capacity
- Library and Cache are saved in parallel
Resolves#343.
This should result in some pretty signifigant performance gains
due to the operations now being ran in parallel instead of
sequentially.
Hide the MusicStore implementation behind an interface, transforming it
into a new MusicRepository class.
This is in preparation for dependency injection.
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.
Completely rework the detail list implementations so that resorting the
song list causes a replace operation instead of a diff operation.
This finally makes the list experience consistent across the app.
Make list instructions generic in preparation for the detail list
update.
Detail views need their own instructions datatype, so this is meant to
allow that to be implemented without issue.
Split up the settings ui into four categories.
This should reduce the visual load on the user as Auxio continues to
accrue possible configuration options.
Resolves#323.
Just pre-emptively add support for TXXX variations of the non-standard
vorbis artist fields to the ID3v2 parser.
I'd imagine the naming convention will be similar between them, so why
not.
Make all adapters relying on diffing unified into a DiffAdapter
superclass that can then accurately respond to the new
UpdateInstructions data.
UpdateInstructions is still not fully used everywhere, but will be
soon.
Add non-standard ARTISTS/ALBUMARTIST fields to reasonable places in the
ID3v2 and Vorbis parsers.
Turns out these are stupidly common when multi-artist information is
used in order to maximize player compatibility. More or less, TPE1 and
ARTIST will be filled in with delimited values, while ARTISTS will be
filled in with native multi-value information.
This is stupid and insane, but I want to prioritize a good out of box
experience without much user fiddling, so I may as well implement
these.
Currently, I'm only adding the non-standard fields that I know exist.
This doesn't include hypothetical but unencountered fields like
TXXX:ALBUMARTISTS.
Add the ability to play or shuffle a selection.
This finally allows "arbitrary" playback to be created from any
combination of songs/albums/artist/genres, rather than just from
pre-defined options.
Resolves#313.
Add library-change sanitization to the queue.
It is hard to describe how unbeliveably difficult this was. It's so
hard to wrap your head around this system and I really would have never
used it if it was not for ExoPlayer's insistence on it's busted
ShuffleOrder code.
Re-enabling state persistence should be easier following this.
Fix moving items with the new queue system.
This took a bit of thinking, but I think this is the correct way to
implement this in a future-proof manner.
When the back button is pressed, clear the current selection before
navigating back.
This is something I was planning to do but then completely forgot about
when implementing multi-select.
Resolves#316.
Switch back to using settings-specific listeners rather than the
SharedPreference listener.
Again, this is due to the need to decouple android code from settings.
It also allows us to fully obscure the details of what settings we are
actually working with.
Decouple the settings god object into feature-specific settings.
This should make testing settings-dependent code much easier, as it no
longer requires a context.
Turns out using isActive to indicate that the AudioProcessor is a no-op
is too unreliable due to how they are managed internally.
Instead, I really do just have to use a copy. Once again ExoPlayer
picks the most absurd possible design choices for no good reason.
Resolves#293.
Band-aid certain types of queue moves that will fail to cauase the
index to correct. Just do this by assuming all queue moves are swaps
and then forgetting about it.
I'll need to figure out how to "properly" do this eventually.
Allow past and currently playing queue items to be edited, instead of
just future queue items.
This was a somewhat requested feature that was impossible with the
prior queue system. With some fixes, the new queue system can now be
used to do this.
This even works with edge cases like removing the currently playing
song. Albeit, it's likely that more bug fixes and testing will be
needed.
Resolves#223.
Implement a new heap-based queue system into the app.
Unlike the prior queue, this one no longer keeps one canonical queue
and then simply swaps between shuffled and ordered queues by
re-grabbing the song list currently being played. Instead, the same
"heap" of songs is used throughout, with only the way they are
interpreted changing.
This enables a bunch of near functionality that would not be possible
with the prior queue system, but is also really unstable and needs a
lot more testing.
Currently this commit disables state saving at the moment. It will be
re-enabled when the new queue can be reliably restored.
Make all list listeners operate on generic values.
Wanted to do this for awhile, but couldn't figure out how to get the
listener to work with sub-typed listeners until I learned what the in
keyword actually does. This removes a ton of type-checking boilerplate
that it's not even funny.
Fix a crash that would occur when trying to add music dirs without a
file manager to handle it.
Some users apparently disable the built-in file manager under the
assumption that the same intents will work with other file managers.
They do not, and so we need to handle that case and let the user know.
Add a button to reset the pre-amp to it's default setting.
This way, you don't have to specifically seek to the 0 dB value in the
dialog in order to reset it.
Refactor the internal tag management portion of MetadataExtractor into a
new "Tags" object that can now be re-used in the ReplayGain system.
This also does a minor rework to the ReplayGain object to make it
totally self-sufficient.
Split off parsing-related components from extractor into a new parsing
module.
A lot of these methods are used in non-extractor code, so it makes more
sense for them to not be part of the extractors.
The code that is really extractor-specific can remain within the
extractor files.