info: retire info documents

Retire the old information documents in favor of the new wiki.
This commit is contained in:
Alexander Capehart 2022-12-28 14:45:22 -07:00
parent 195ea074ca
commit 5764c19801
No known key found for this signature in database
GPG key ID: 37DBE3621FE9AD47
11 changed files with 8 additions and 516 deletions

View file

@ -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>

View file

@ -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() {

View file

@ -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 {

View file

@ -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)
}

View file

@ -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)
}
}

View file

@ -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)
}

View file

@ -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)) }
}

View file

@ -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+)

View file

@ -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.

View file

@ -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.

View file

@ -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 |