info: retire info documents
Retire the old information documents in favor of the new wiki.
This commit is contained in:
parent
195ea074ca
commit
5764c19801
11 changed files with 8 additions and 516 deletions
|
@ -13,7 +13,7 @@
|
|||
</a>
|
||||
<img alt="Minimum SDK Version" src="https://img.shields.io/badge/API-21%2B-32B5ED">
|
||||
</p>
|
||||
<h4 align="center"><a href="/CHANGELOG.md">Changelog</a> | <a href="/info/FAQ.md">FAQ</a> | <a href="/info/LICENSES.md">Licenses</a> | <a href="/.github/CONTRIBUTING.md">Contributing</a> | <a href="/info/ARCHITECTURE.md">Architecture</a></h4>
|
||||
<h4 align="center"><a href="/CHANGELOG.md">Changelog</a> | <a href="https://github.com/OxygenCobalt/Auxio/wiki">Wiki</a>
|
||||
<p align="center">
|
||||
<a href="https://f-droid.org/app/org.oxycblt.auxio"><img src="https://fdroid.gitlab.io/artwork/badge/get-it-on.png" width="170"></a>
|
||||
<a href="https://hosted.weblate.org/engage/auxio/"><img src="https://hosted.weblate.org/widgets/auxio/-/strings/287x66-grey.png" alt="Translation status" /></a>
|
||||
|
|
|
@ -54,6 +54,8 @@ import org.oxycblt.auxio.util.systemBarInsetsCompat
|
|||
*
|
||||
* TODO: Standardize companion object usage
|
||||
*
|
||||
* TODO: Standardize callback/listener naming.
|
||||
*
|
||||
* @author Alexander Capehart (OxygenCobalt)
|
||||
*/
|
||||
class MainActivity : AppCompatActivity() {
|
||||
|
|
|
@ -244,7 +244,6 @@ class AlbumDetailFragment : ListFragment<FragmentDetailBinding>(), AlbumDetailAd
|
|||
binding.detailRecycler.post {
|
||||
// Use a custom smooth scroller that will settle the item in the middle of
|
||||
// the screen rather than the end.
|
||||
// TODO: Can I apply this to the queue view?
|
||||
val centerSmoothScroller =
|
||||
object : LinearSmoothScroller(context) {
|
||||
init {
|
||||
|
|
|
@ -284,7 +284,7 @@ class PlaybackViewModel(application: Application) :
|
|||
* @param song The [Song] to add.
|
||||
*/
|
||||
fun playNext(song: Song) {
|
||||
// TODO: Queue additions without a playing song should map to queued items
|
||||
// TODO: Queue additions without a playing song should map to playing items
|
||||
// (impossible until queue rework)
|
||||
playbackManager.playNext(song)
|
||||
}
|
||||
|
|
|
@ -88,6 +88,7 @@ class QueueFragment : ViewBindingFragment<FragmentQueueBinding>(), QueueAdapter.
|
|||
queueModel.finishReplace()
|
||||
|
||||
// If requested, scroll to a new item (occurs when the index moves)
|
||||
// TODO: Scroll to center/top instead of bottom
|
||||
val scrollTo = queueModel.scrollTo
|
||||
if (scrollTo != null) {
|
||||
// Do not scroll to indices that are in the currently visible range. As that would
|
||||
|
@ -102,7 +103,7 @@ class QueueFragment : ViewBindingFragment<FragmentQueueBinding>(), QueueAdapter.
|
|||
}
|
||||
queueModel.finishScrollTo()
|
||||
|
||||
// Update currently playing item
|
||||
// Update position in list (and thus past/future items)
|
||||
queueAdapter.setPosition(index, isPlaying)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -165,7 +165,7 @@ class Settings(private val context: Context, private val callback: Callback? = n
|
|||
unlikelyToBeNull(callback).onSettingChanged(key)
|
||||
}
|
||||
|
||||
/** TODO: Remove this */
|
||||
/** TODO: Rework this */
|
||||
interface Callback {
|
||||
fun onSettingChanged(key: String)
|
||||
}
|
||||
|
|
|
@ -73,8 +73,7 @@ constructor(context: Context, attrs: AttributeSet? = null, @AttrRes defStyleAttr
|
|||
* @param recycler [RecyclerView] to expand with, or null if one is currently unavailable.
|
||||
*/
|
||||
fun expandWithRecycler(recycler: RecyclerView?) {
|
||||
// TODO: Is it possible to use liftOnScrollTargetViewId to avoid the [RecyclerView]
|
||||
// argument?
|
||||
// TODO: Is it possible to use liftOnScrollTargetViewId to avoid the RecyclerView arg?
|
||||
setExpanded(true)
|
||||
recycler?.let { addOnOffsetChangedListener(ExpansionHackListener(it)) }
|
||||
}
|
||||
|
|
|
@ -1,21 +0,0 @@
|
|||
# Accepted Additions and Requests
|
||||
One of the reasons I built Auxio was out of frustration with other FOSS android music players, which had too many features, frustrating UI/UX flaws, or both. Therefore any additions will have to be accepted by **me** (OxygenCobalt) before they are implemented or merged.
|
||||
|
||||
## Bug Fixes, Optimizations, Architecture Improvements, etc.
|
||||
These will likely be accepted as long as they do not cause too much harm to the codebase.
|
||||
|
||||
## New Customizations/Options
|
||||
While I do like adding new behavior/UI customizations, these will be looked at more closely as certain additions can cause harm to the apps UI/UX while not providing a lot of benefit. These tend to be accepted however.
|
||||
|
||||
## Feature Additions and UI Changes
|
||||
These arent as likely to be accepted. As I said, I do not want Auxio to become overly bloated with features that are rarely used, therefore I only tend to accept features that:
|
||||
- Benefit **my own** usage
|
||||
- Are in line with Auxio's purpose as a music player
|
||||
|
||||
This does not rule out these additions, but they are not accepted as often as others. I will also hold off adding features until I'm able to implement them without disruption or strange behaviors.
|
||||
|
||||
Feel free to fork Auxio to add your own feature set however.
|
||||
|
||||
## Additions that have already been rejected
|
||||
|
||||
To see an up-to-date list on all of the features that have been rejected, see [this link](https://github.com/OxygenCobalt/Auxio/issues?q=label%3Awontadd-technical%2Cwontadd-out-of-scope+)
|
|
@ -1,348 +0,0 @@
|
|||
# Architecture
|
||||
This document is designed to provide an overview of Auxio's architecture and design decisions. It
|
||||
will be updated as Auxio changes, however it may not completely line up as parts of the codebase
|
||||
will change rapidly at times.
|
||||
|
||||
## Core Facets
|
||||
Auxio has a couple of core systems or concepts that should be understood when working with the
|
||||
codebase.
|
||||
|
||||
#### Package Structure
|
||||
Auxio is deliberately structured in a way that I call "Anti-CLEAN Architecture". There is one
|
||||
gradle project, with sub-packages that are strictly feature-oriented. For example, playback code is
|
||||
exclusively in the `playback` package, and detail code is exclusively in the `detail` package.
|
||||
Sub-packages can be related to the code it contains, such as `detail.recycler` for the detail UI
|
||||
adapters, or hey can be related to a sub-feature, like `playback.queue` for the queue UI.
|
||||
|
||||
The outliers here are `.ui` and `.util`, which are generic utility or component packages.
|
||||
|
||||
Sticking to a single project reduces compile times, makes it easier to add new features, and simply
|
||||
makes Auxio's code better to reason about since you don't have to jump across disparately related
|
||||
gradle projects.
|
||||
|
||||
A full run-down of Auxio's current package structure as of the latest version is shown below.
|
||||
|
||||
```
|
||||
org.oxycblt.auxio # Main UIs
|
||||
├──.detail # Album/Artist/Genre detail UIs
|
||||
│ └──.recycler # RecyclerView components for detail UIs
|
||||
├──.home # Home UI
|
||||
│ ├──.fastscroll # Fast scroller UI
|
||||
│ ├──.list # Home item lists
|
||||
│ └──.tabs # Home tab customization
|
||||
├──.image # Image loading components
|
||||
├──.music # Music data and loading
|
||||
│ ├──.dirs # Music folders UI + systems
|
||||
│ └──.system # Internal music loading
|
||||
├──.playback # Playback UI + Systems
|
||||
│ ├──.queue # Queue UI
|
||||
│ ├──.replaygain # ReplayGain System + UIs
|
||||
│ ├──.state # Playback state backend
|
||||
│ └──.system # System-side playback [Services, ExoPlayer]
|
||||
├──.search # Search UI
|
||||
├──.settings # Settings UI + Systems
|
||||
│ └──.ui # Preference extensions
|
||||
├──.ui # Custom android components
|
||||
│ ├──.accent # Color Scheme UI + Systems
|
||||
│ ├──.fragment # Fragment extensions
|
||||
│ ├──.recycler # RecyclerView extensions
|
||||
│ └──.system # System-side components
|
||||
├──.util # Shared utilities
|
||||
└──.widgets # AppWidgets
|
||||
```
|
||||
|
||||
Each package is gone over in more detail later on.
|
||||
|
||||
#### UI Structure
|
||||
Auxio only has one activity, `MainActivity`. Do not try to add more activities to the codebase.
|
||||
Instead, a new UI should be added as a new `Fragment` implementation and added to one of the two
|
||||
navigation graphs:
|
||||
|
||||
- `nav_main`: Navigation *from* `MainFragment`
|
||||
- `nav_explore`: Navigation *in* `MainFragment`
|
||||
|
||||
Fragments themselves are based off several extensions that enable extra functionality, such as
|
||||
ViewBinding or safe `PopupMenu` creation.
|
||||
|
||||
Generally:
|
||||
- Most variables are kept as member variables, and cleared out when the view is destroyed.
|
||||
- Observing data is done through the `Fragment.launch` extension, and always points to another
|
||||
function in order to reduce possible memory leaks.
|
||||
- When possible (and readable), `Fragment` implementations inherit any listener interfaces they
|
||||
need, and simply clear them out when done.
|
||||
|
||||
`findViewById` is to **only** be used when interfacing with non-Auxio views. Otherwise, view-binding
|
||||
should be used in all cases. Code that involves retrieving the binding should be isolated into its
|
||||
own function, with the binding being obtained by calling `requireBinding`.
|
||||
|
||||
At times it may be more appropriate to use a `View` instead of a fragment. This is okay as long as
|
||||
view-binding is still used.
|
||||
|
||||
Auxio uses `RecyclerView` for all list information. To manage some complexity, there are a few
|
||||
conventions that are used when creating adapters. These can be seen in the `RecyclerFramework`
|
||||
file and in adapter implementations.
|
||||
|
||||
#### Object communication
|
||||
Auxio's codebase is mostly centered around 4 different types of code that communicates with
|
||||
each-other.
|
||||
|
||||
- UIs: Fragments, RecyclerView items, and Activities are part of this class. All of them should have
|
||||
little data logic in them and should primarily focus on displaying information in their UIs.
|
||||
- ViewModels: These usually contain data and values that a UI can display, along with doing data
|
||||
processing. The data ten takes the form of `MutableStateFlow` or `StateFlow`, which can be observed.
|
||||
- Services: Auxio's services are intended to perform some kind of long-running task, while driving
|
||||
the Shared Object related to the work that they are doing.
|
||||
- Shared Objects: These are the fundamental building blocks of Auxio, and exist at the process
|
||||
level. These are usually retrieved using `getInstance` or a similar function. Usually, methods in
|
||||
these are also Synchronized to prevent issues with global/mutable/concurrent state. Shared Objects
|
||||
should be avoided in UIs, as their volatility can cause problems. Its better to use a ViewModel
|
||||
and their exposed data instead.
|
||||
- Utilities: These are largely found in the `.util` package, taking the form of standalone or
|
||||
extension functions that can be used anywhere.
|
||||
|
||||
Ideally, UIs should only be talking to ViewModels, ViewModels and Services should only be talking
|
||||
to the Shared Objects, and Shared Objects should only be talking to other shared objects. All
|
||||
objects can use the utility functions where appropriate.
|
||||
|
||||
#### Data objects
|
||||
Auxio represents data in multiple ways.
|
||||
|
||||
`Item` is the base class for most music and UI data in Auxio, with a single ID field meant to mark it as unique.
|
||||
|
||||
It has the following implementations:
|
||||
- `Music` is a `Item` that represents music. It adds a `name` field that represents the raw name
|
||||
of the music (from `MediaStore`), and a `resolveName` method meant to resolve the name in context
|
||||
of the UI.
|
||||
- `MusicParent` is a type of `Music` that contains children.
|
||||
- `Header` corresponds to a simple header with a title and no interaction functionality. There are
|
||||
also the `detail`-specific `DiscHeader` and `SortHeader`, however these are largely unrelated to
|
||||
`Header`.
|
||||
|
||||
Other data types represent a specific UI configuration or state:
|
||||
- Data structures like `Sort` contain an ascending state that can be modified immutably.
|
||||
- Enums like `MusicMode` and `RepeatMode` only contain static data, such as a string resource.
|
||||
|
||||
Things to keep in mind while working with music data:
|
||||
- `id` is not derived from the `MediaStore` ID of the music data. It is actually a hash of the
|
||||
unique, non-subjective fields of the music data. Attempting to use it as a `MediaStore` ID will
|
||||
result in errors.
|
||||
- Any field or method beginning with `_` is off-limits. These fields are meant for use within
|
||||
the indexer and generally provide poor UX to the user. The only reason they are public is to
|
||||
simplify the loading process, as there is no reason to remove internal fields given that it won't
|
||||
free memory.
|
||||
- `rawName` is used when doing internal work, such as saving music data or diffing items
|
||||
- `sortName` is used in the fast scroller indicators and sorting. Avoid it wherever else.
|
||||
- `resolveName()` should be used when displaying any kind of music data to the user.
|
||||
- For songs, `individualArtistRawName` and `resolveIndividualArtistName` should always be used when
|
||||
displaying the artist of a song, as it will always show collaborator information first before
|
||||
defaulting to the album artist.
|
||||
|
||||
#### Music Access
|
||||
Whereas other apps load music from `MediaStore`, Auxio does not do that, as it prevents any kind of
|
||||
reasonable metadata functionality (ex. Album Artists). Instead, Auxio loads all music into an
|
||||
in-memory relational construct called `Library`.
|
||||
|
||||
`Library` is obtained from `MusicStore`, however since Auxio's music loading is asynchronous and
|
||||
can occur several times over the runtime of the app, it is highly recommended for code to rely
|
||||
on `MusicStore.Callback`. In the case that a piece of code would only be ran if there was a library,
|
||||
`requireNotNull` can be used, however this is highly risky.
|
||||
|
||||
Since Shared Objects should not be attached to the Callback system of another Shared Object, it
|
||||
is highly recommended to check for the existence of a `Library` if required, and no-op if it was
|
||||
not available.
|
||||
|
||||
Monitoring the loading progress (Internally called the indexing state) should be done sparingly,
|
||||
and is best done with `MusicViewModel`.
|
||||
|
||||
#### Playback System
|
||||
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.
|
||||
|
||||
The diagram below highlights the overall structure and connections:
|
||||
|
||||
```
|
||||
┌──────────────────── PlaybackService
|
||||
│ │
|
||||
PlaybackStateManager [Communicates with] │
|
||||
│ │ [Controls]
|
||||
│ │
|
||||
│ ├ WidgetComponent
|
||||
│ ├ NotificationComponent
|
||||
│ ├ MediaSessionComponent
|
||||
│ └ Player
|
||||
│
|
||||
│
|
||||
└──────────────────── PlaybackViewModel ───────────────────── UIs
|
||||
[Controls]
|
||||
```
|
||||
|
||||
`PlaybackStateManager` is the shared object that contains the master copy of the playback state,
|
||||
doing all operations on it. This object should ***NEVER*** be used in a UI, as it does not sanitize
|
||||
input and can cause major problems if a Volatile UI interacts with it. It's callback system is also
|
||||
prone to memory leaks if not cleared when done.
|
||||
|
||||
For UIs, `PlaybackViewModel` exists instead. It provides safe, observable data and abstractions to
|
||||
make managing the playback state simple from the UI.
|
||||
|
||||
`PlaybackService`'s job is to use the playback state to manage the ExoPlayer instance, the
|
||||
notification, the media session, the widget, and also modify the state depending on system events,
|
||||
such as when a button is pressed on a headset. It should **never** be bound to, mostly because
|
||||
there is no need given that `PlaybackViewModel` exposes the same data in a much safer fashion.
|
||||
|
||||
#### Data Integers
|
||||
Integer representations of data/UI elements are used heavily in Auxio, primarily for efficiency. To
|
||||
prevent any strange bugs, all integer representations must be unique. To see a table of all current
|
||||
integers, see the `IntegerTable` class within the project.
|
||||
|
||||
Some datatypes [like `Tab` and `Sort`] have even more fine-grained integer representations for other
|
||||
data. More information can be found in the documentation for those datatypes.
|
||||
|
||||
## Package-by-package rundown
|
||||
|
||||
#### `org.oxycblt.auxio`
|
||||
This is the root package and contains the application instance and the landing UIs. This should be
|
||||
kept sparse with most other code being placed into a package.
|
||||
|
||||
#### `.detail`
|
||||
Contains all the detail UIs for some data types in Auxio. All detail user interfaces share the same
|
||||
base layout (A Single RecyclerView) and only change the adapter/data being used. The adapters
|
||||
display both the header with information and the child items of the item itself, usually with a data
|
||||
list similar to this:
|
||||
|
||||
`Item being displayed | Header Item | Child Item | Child Item | Child Item...`
|
||||
|
||||
Note that the actual dataset used is more complex once sorting and disc numbers is taken into
|
||||
account.
|
||||
|
||||
#### `.home`
|
||||
This package contains the components for the "home" UI in Auxio, or the UI that the user first sees
|
||||
when they open the app.
|
||||
|
||||
- The base package contains the top-level components that manage the FloatingActionButton, AppBar,
|
||||
and ViewPager instances.
|
||||
- The `fastscroll` package contains the fast scroll component used in each list of music
|
||||
- The `list` package contains the individual fragments for each list of music. These are all placed
|
||||
in the top-level ViewPager instance.
|
||||
- The `tabs` package contains the data representation of an individual library tab and the UIs for
|
||||
editing them.
|
||||
|
||||
#### `.image`
|
||||
[Coil](https://github.com/coil-kt/coil) is the image loader used by Auxio. This package contains the
|
||||
components Auxio leverages to load images in a stable manner. Usually, you do not need to import
|
||||
this package elsewhere, but there are some important components:
|
||||
|
||||
- `BitmapProvider`, which allows external components (Such as in PlaybackService) to load a `Bitmap`
|
||||
in a way not prone to race conditions. This should not be used for UIs.
|
||||
- `BaseFetcher`, which is effectively Auxio's image loading routine. Most changes to image loading
|
||||
should be done there, and not it's sub-classes like `AlbumArtFetcher`.
|
||||
|
||||
This package also contains the two UI components used for all covers in Auxio:
|
||||
- `StyledImageView`, which adds extensions for dynamically loading covers, handles rounded corners,
|
||||
and a stable icon style.
|
||||
- `ImageGroup`, an extension of `StyledImageView` that all of the previous features, alongside a
|
||||
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 quite difficult.
|
||||
|
||||
The major classes are:
|
||||
- `MusicStore`, which is the container for a `Library` instance. Any code wanting to access the
|
||||
library should use this.
|
||||
- `Indexer`, which manages how music is loaded. This is only used by code that must manage or
|
||||
mirror the music loading state.
|
||||
- The extractor system, which is Auxio's music parser. It's structured as several "Layer" classes
|
||||
that build on eachother to implement version-specific functionality.
|
||||
|
||||
Internally, there are several other major systems:
|
||||
- `IndexerService`, which does the indexer work in the background.
|
||||
- `StorageFramework`, which is a group of utilities that allows Auxio to be volume-aware and to
|
||||
work with both extension-based and format-based mime types.
|
||||
- Configuration models like `MusicMode` and `Sort`, which are tangentally related to operations
|
||||
done on music
|
||||
|
||||
The music loading process is roughly as follows:
|
||||
1. Something triggers `IndexerService` to start indexing, either by the UI or by the service itself
|
||||
starting.
|
||||
2. `Indexer` picks an appropriate `Backend`, and begins loading music. `Indexer` may periodically
|
||||
update it's state during this time with the current progress.
|
||||
3. In the case that `IndexerService` is killed, `Indexer` falls back to a previous state (or null
|
||||
if there isn't one).
|
||||
4. If the music loading process completes, `Indexer` will push a `Response`. `IndexerService` will
|
||||
read this, and in the case that the new `Library` differs, it will push it to `MusicStore`.
|
||||
5. `MusicStore` updates any `Callback` instances with the new `Library`.
|
||||
|
||||
#### `.playback`
|
||||
This module not only contains the playback system described above, but also multiple other
|
||||
components:
|
||||
|
||||
- `queue` contains the Queue UI and it's fancy item system.
|
||||
- `replaygain` contains the ReplayGain implementation and the UIs related to it. Auxio's ReplayGain
|
||||
implementation is somewhat different compared to other apps, as it leverages ExoPlayer's metadata
|
||||
and audio processing systems to not only parse ReplayGain tags, but also allow volume amplification
|
||||
above 100%.
|
||||
- `state` contains the core playback state and persistence system.
|
||||
- `system` contains the system-facing playback system, i.e `PlaybackService`.
|
||||
|
||||
The base package contains the user-facing UIs representing the playback state, specifically the
|
||||
playback bar and the playback panel that it expands into. Note that while the playback UI does rely
|
||||
on `BottomSheetLayout`, the layout is designed to be at least somewhat re-usable, so it is in the
|
||||
generic `.ui` class.
|
||||
|
||||
#### `.search`
|
||||
Package for Auxio's search functionality, `SearchViewHolder` handles the data results and filtering
|
||||
while `SearchFragment`/`SearchAdapter` handles the display of the results and user input.
|
||||
|
||||
#### `.settings`
|
||||
The settings system is primarily based off of `Settings`, a type-safe wrapper around
|
||||
`SharedPreferences`. `Settings` is not a shared object, but actually a utility instantiated
|
||||
with a `Context`. Thus, the way to leverage them differs depending on if the code is in a UI,
|
||||
ViewModel, Shared Object, or Service.
|
||||
|
||||
Internally, the settings package also leverages a couple custom preference implementations,
|
||||
notably `IntListPreference`, which enables a normal choice preference to be backed by the
|
||||
integer data that Auxio uses.
|
||||
|
||||
#### `.ui`
|
||||
Shared views and view configuration models. This contains:
|
||||
|
||||
- Important `Fragment` superclasses like `ViewBindingFragment` and `MenuFragment`
|
||||
- Customized views such as `AuxioAppBarLayout`, and others, which fix shortcomings with the
|
||||
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.
|
||||
- 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`
|
||||
|
||||
#### `.util`
|
||||
Shared utilities. This is primarily for QoL when developing Auxio. Documentation is provided on each method.
|
||||
|
||||
Utilities are separated into a few groups:
|
||||
- Context utilities are extensions of `Context` and generally act as shortcuts for that class.
|
||||
- Framework utilities extend a variety of view implementations to add new behavior or shortcuts.
|
||||
- Primitive utilities operate on basic datatypes and are mostly shortcuts.
|
||||
- Log utilities are a more light-weight logging framework that Auxio leverages instead of
|
||||
bloated and over-engineered libraries like Timber.
|
||||
|
||||
#### `.widgets`
|
||||
This package contains Auxio's AppWidget implementation, which deviates from other AppWidget
|
||||
implementations by packing multiple different layouts into a single widget and then switching
|
||||
between them depending on the widget size. Note that since `RemoteViews` and the AppWidget API
|
||||
in general is incredibly outdated and limited, this package deviates from much of Auxio's normal UI
|
||||
conventions.
|
||||
|
||||
PlaybackService owns `WidgetComponent`, which listens to `PlaybackStateManager` for updates. During
|
||||
an update, it reloads all song metadata and playback state into a `WidgetState`, which is an
|
||||
immutable version of the playback state that negates some of the problems with using a volatile
|
||||
shared object.
|
||||
|
||||
`WidgetProvider` is the widget "implementation" exposed in the manifest. When `WidgetComponent`
|
||||
updates it, the class will create a series of layouts [e.g "Forms"] for a variety of "size buckets"
|
||||
that would adequately contain the widget. This is then used as the widget views, either with the
|
||||
native responsive behavior on Android 12 and above, or with the responsive behavior back-ported
|
||||
to older devices.
|
127
info/FAQ.md
127
info/FAQ.md
|
@ -1,127 +0,0 @@
|
|||
# Auxio - Frequently Asked Questions
|
||||
This FAQ will be continually updated as new changes and updates are made to Auxio.
|
||||
|
||||
#### Where can I download Auxio?
|
||||
Auxio is available on the [F-Droid](https://f-droid.org/en/packages/org.oxycblt.auxio/) repository.
|
||||
Auxio is not and will never be on the play store due to it being a proprietary and draconian platform.
|
||||
|
||||
#### Why ExoPlayer?
|
||||
Unlike the stock `MediaPlayer` API that most music apps use, ExoPlayer is independent from the android system's
|
||||
audio framework. This allows for the following:
|
||||
- Consistent behavior across devices and OS versions
|
||||
- Features that are normally not possible with a normal audio stream (such as positive ReplayGain values)
|
||||
- Playback to be (theoretically) be extended beyond local files in the future
|
||||
|
||||
You can read more about the benefits (and drawbacks) of ExoPlayer [Here](https://exoplayer.dev/pros-and-cons.html).
|
||||
|
||||
#### What formats does Auxio support?
|
||||
As per the [Supported ExoPlayer Formats](https://exoplayer.dev/supported-formats.html), Auxio supports
|
||||
MP4, MP3, MKA, OGG, WAV, MPEG, AAC on all versions of Android. Auxio also supports FLAC on all versions
|
||||
of Android through the use of the ExoPlayer FLAC extension.
|
||||
|
||||
#### Why doesn't Auxio have a built-in equalizer or tag editor?
|
||||
|
||||
Auxio tends to abide by a unix-esque philosophy where programs should try to stay in one
|
||||
category of tasks and do those tasks well.
|
||||
|
||||
- For equalization, Android already supports external equalizers like Wavelet, which tend to
|
||||
work on most modern devices that don't have broken OEM software. This is generally preferred
|
||||
compared to implementing my own equalizer.
|
||||
- For tag editing, external programs like kid3, picard, or ex falso fill this role.
|
||||
|
||||
#### Auxio doesn't load my music correctly!
|
||||
This depends on the context:
|
||||
1. If "Ignore MediaStore Tags" is enabled, please create a bug report.
|
||||
2. If "Ignore MediaStore Tags" is not enabled, please check below to make sure your issue is not already
|
||||
acknowledged before reporting a bug.
|
||||
- Moreover, if the issue encountered does not appear in other apps like Music Player GO, Phonograph,
|
||||
or Retro Music then it should definitely be reported, as it is a logic bug on Auxio's part.
|
||||
|
||||
***Known unfixable music loading issues***
|
||||
|
||||
These are a list of unfixable music loading issues that can only be fixed by enabling "Ignore MediaStore Tags":
|
||||
|
||||
**My FLAC/OGG/OPUS/MP3 files don't have dates:** Android does not read the `DATE` tag from vorbis files. It reads the `YEAR` tag.
|
||||
Similarly, Android does not read ID3v2.4's `TDRC` and actually reads `TYER` regardless of the version. This is because android's
|
||||
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 [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
|
||||
containing 10k songs or more.
|
||||
|
||||
**Auxio does not detect disc numbers:** If your device runs Android 10, then Auxio cannot parse a disc from the media database due to
|
||||
a regression introduced by Google in that version. If this issue appears in another android version, please file an issue.
|
||||
|
||||
***Other music loading issues***
|
||||
|
||||
**There should be one artist, but instead I get a bunch of "Artist & Collaborator" artists:** This likely means your tags are wrong. By default, Auxio will use the
|
||||
"album artist" tag for grouping if present, falling back to the "artist" tag otherwise. If your music does not have such a field, it will result in fragmented artists.
|
||||
The reason why Auxio does not simply parse for separators and then extract artists that way is that it risks mangling artists that don't actually have collaborators,
|
||||
such as "Black Country, New Road" becoming "Black Country". I understand that some users may leverage MusicBrainz tags that enable a song to be referenced by several
|
||||
artists, but such functionality in Auxio will likely take awhile to implement to to UI and technical constraints.
|
||||
|
||||
**Auxio does not detect new music:** This is Auxio's default behavior due to limitations regarding android's filesystem APIs. To enable such behavior, turn on
|
||||
"Automatic reloading" in settings. Note that this option does require a persistent notification and higher battery usage.
|
||||
|
||||
#### What does "Ignore MediaStore Tags" even do?
|
||||
"Ignore MediaStore Tags" configures Auxio's music loader to extract metadata manually using ExoPlayer, which enables the following:
|
||||
- Fixes for most of the annoying, unfixable issues with `MediaStore` that were elaborated on above
|
||||
- Sort tag support
|
||||
- For example, a title written in Japanese could have a phonetic version in their sort tags. This will be used in sorting and search.
|
||||
- Better date support
|
||||
- If an artist released several albums in a single year, you can tag your music to have a particular date and time it was released on, and Auxio will
|
||||
sort the albums accordingly. Examples include `YYYY-MM-DD` or even `YYYY-MM-DD HH:MM:SS`
|
||||
- Auxio is also capable of supporting original dates. If a remastered album was released in 2020, but the original album was released in 2000,
|
||||
you can tag your music with `TDOR`/`TORY` for MP3 and `ORIGINALDATE` for Vorbis with the year 2000, and Auxio will display 2000 in-app.
|
||||
- Release type support from `TXXX:MusicBrainz Release Type`/`GRP1` in MP3 files, and `RELEASETYPE` in OGG/OPUS/FLAC
|
||||
- Auxio specifically expects something formatted like `<primary> + <secondary>`, `<primary>`, or `<secondary>`. This should be contained in a single tag.
|
||||
- `<primary`> corresponds to `album`, `ep`, or `single`
|
||||
- `<secondary>` corresponds to `compilation`, `soundtrack`, `mixtape`, `live`, or `remix`. The first three will override the primary type,
|
||||
(ex. `album + compilation` -> "Compilation"), but the latter two will be used to augment the primary type (ex. `album + live` -> "Live Album").
|
||||
|
||||
#### Why does search return songs that don't match my query?
|
||||
Auxio actually takes several types of metadata in account in searching:
|
||||
- The name, normalized so that any accented/symbolic characters are converted to normal characters. For example, Ü -> U.
|
||||
- The sort tag of a particular song/album/artist, as such often contain latinized/translated versions of a given title.
|
||||
- The file name, as some users don't have usable title metadata, and instead use the file name as the title.
|
||||
|
||||
#### Why does playback pause whenever music is reloaded?
|
||||
Whenever the music library significantly changes, updating the player's data while it is still playing may result in
|
||||
unwanted bugs or unexpected music playing. To safeguard against this, Auxio will pause whenever it reloads a new
|
||||
music library.
|
||||
|
||||
#### ReplayGain isn't working on my music!
|
||||
This is for a couple reason:
|
||||
- Auxio doesn't extract ReplayGain tags for your format. This is a problem on ExoPlayer's end and should be
|
||||
investigated there.
|
||||
- Auxio doesn't recognize your ReplayGain tags. This is usually because of a non-standard tag like ID3v2's `RVAD` or
|
||||
an unrecognized name.
|
||||
|
||||
#### My lossless audio sounds lower-quality in Auxio!
|
||||
This is a current limitation with the ExoPlayer. Basically, all audio is downsampled to 16-bit PCM audio, even
|
||||
if the source audio is higher quality. I can enable something that might be able to remedy such, but implementing it
|
||||
fully may take some time.
|
||||
|
||||
#### Why is playback distorted when I play my FLAC/WAV files?
|
||||
ExoPlayer, while powerful, does add some overhead when playing exceptionally high-quality files (2000+ KB/s bitrate,
|
||||
90000+ Hz sample rate). This is worsened by the ReplayGain system, as it has to copy the audio buffer no matter what.
|
||||
This results in choppy, distorted playback in some cases as audio data cannot be delivered in time. I can also mitigate
|
||||
this similarly to the above issue, but again, it may take some time.
|
||||
|
||||
#### Why are accents lighter/less saturated in dark mode?
|
||||
As per the [Material Design Guidelines](https://material.io/design/color/dark-theme.html), accents should be less
|
||||
saturated on dark mode to reduce eye strain and to increase visual cohesion.
|
||||
|
||||
#### Does this app keep/send any information about myself or my device?
|
||||
Auxio does not log any information about the device or its owner, and it has no internet access to send that information off in the first place.
|
||||
|
||||
#### How can I contribute/report issues?
|
||||
Open an [Issue](https://github.com/OxygenCobalt/Auxio/issues) or a [Pull Request](https://github.com/OxygenCobalt/Auxio/pulls),
|
||||
please note the [Contribution Guidelines](../.github/CONTRIBUTING.md) and [Accepted Additions](ADDITIONS.md) however.
|
||||
|
||||
#### Can I translate Auxio to my native language?
|
||||
Please go to Auxio's [Weblate Project](https://hosted.weblate.org/engage/auxio/) to create new translations for the project.
|
|
@ -1,13 +0,0 @@
|
|||
# Licenses
|
||||
|
||||
Auxio is licensed under the GPLv3.
|
||||
|
||||
Alongside this, Auxio uses a number of third-party libraries. These are listed below with
|
||||
their licenses:
|
||||
|
||||
| Library Name | Author(s) | Purpose | License |
|
||||
|-----------------------------------------------------|----------------------------------------------|----------------|------------|
|
||||
| [ExoPlayer](https://github.com/google/ExoPlayer) | [Google](https://github.com/google) | Music Playback | Apache-2.0 |
|
||||
| [Coil](https://github.com/coil-kt/coil) | [Square](https://github.com/coil-kt) | Image Loading | Apache-2.0 |
|
||||
| [Spotless](https://github.com/diffplug/spotless) | [DiffPlug](https://github.com/diffplug) | Formatting | Apache-2.0 |
|
||||
| [ktfmt](https://github.com/facebookincubator/ktfmt) | [Meta](https://github.com/facebookincubator) | Formatting | Apache-2.0 |
|
Loading…
Reference in a new issue