playback: use custom exoplayer
Use a custom ExoPlayer fork with the FLAC extension enabled. This greatly improves the listening experience, as it enables metadata support on OGG files and FLAC files to be played below API 27.
This commit is contained in:
parent
5e3569d173
commit
2f190f1e0b
9 changed files with 106 additions and 9 deletions
|
@ -61,6 +61,14 @@ I primarily built Auxio for myself, but you can use it too, I guess.
|
|||
- Storage (`READ_EXTERNAL_STORAGE`): to read and play your media files
|
||||
- Services (`FOREGROUND_SERVICE`, `WAKE_LOCK`): to keep the music playing even if the app itself is in background
|
||||
|
||||
## Building
|
||||
|
||||
Auxio relies on a local version of ExoPlayer that enables some extra features. So, the build process is as follows:
|
||||
|
||||
1. Change into the project directory
|
||||
2. Run `python3 prebuild.py`, which installs ExoPlayer and it's extensions.
|
||||
3. Build the project normally in Android Studio.
|
||||
|
||||
## Contributing
|
||||
|
||||
Auxio accepts most contributions as long as they follow the [Contribution Guidelines](/.github/CONTRIBUTING.md).
|
||||
|
|
|
@ -95,7 +95,8 @@ dependencies {
|
|||
// --- THIRD PARTY ---
|
||||
|
||||
// ExoPlayer
|
||||
implementation "com.google.android.exoplayer:exoplayer-core:2.16.1"
|
||||
implementation project(':exoplayer-library-core')
|
||||
implementation project(':exoplayer-extension-flac')
|
||||
|
||||
// Image loading
|
||||
implementation 'io.coil-kt:coil:2.0.0-alpha06'
|
||||
|
|
|
@ -18,8 +18,8 @@ import coil.size.pxOrElse
|
|||
import com.google.android.exoplayer2.MediaItem
|
||||
import com.google.android.exoplayer2.MediaMetadata
|
||||
import com.google.android.exoplayer2.MetadataRetriever
|
||||
import com.google.android.exoplayer2.metadata.flac.PictureFrame
|
||||
import com.google.android.exoplayer2.metadata.id3.ApicFrame
|
||||
import com.google.android.exoplayer2.metadata.xiph.PictureFrame
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import okio.buffer
|
||||
|
|
|
@ -25,8 +25,8 @@ import androidx.media.AudioAttributesCompat
|
|||
import androidx.media.AudioFocusRequestCompat
|
||||
import androidx.media.AudioManagerCompat
|
||||
import com.google.android.exoplayer2.metadata.Metadata
|
||||
import com.google.android.exoplayer2.metadata.flac.VorbisComment
|
||||
import com.google.android.exoplayer2.metadata.id3.TextInformationFrame
|
||||
import com.google.android.exoplayer2.metadata.xiph.VorbisComment
|
||||
import org.oxycblt.auxio.playback.state.PlaybackStateManager
|
||||
import org.oxycblt.auxio.settings.SettingsManager
|
||||
import org.oxycblt.auxio.util.getSystemServiceSafe
|
||||
|
|
|
@ -39,6 +39,7 @@ import com.google.android.exoplayer2.RenderersFactory
|
|||
import com.google.android.exoplayer2.TracksInfo
|
||||
import com.google.android.exoplayer2.audio.AudioAttributes
|
||||
import com.google.android.exoplayer2.audio.MediaCodecAudioRenderer
|
||||
import com.google.android.exoplayer2.ext.flac.LibflacAudioRenderer
|
||||
import com.google.android.exoplayer2.extractor.DefaultExtractorsFactory
|
||||
import com.google.android.exoplayer2.mediacodec.MediaCodecSelector
|
||||
import com.google.android.exoplayer2.source.DefaultMediaSourceFactory
|
||||
|
@ -46,9 +47,8 @@ import kotlinx.coroutines.CoroutineScope
|
|||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.flow.flow
|
||||
import kotlinx.coroutines.flow.collect
|
||||
import kotlinx.coroutines.flow.conflate
|
||||
import kotlinx.coroutines.flow.flow
|
||||
import kotlinx.coroutines.flow.takeWhile
|
||||
import kotlinx.coroutines.launch
|
||||
import org.oxycblt.auxio.BuildConfig
|
||||
|
@ -371,7 +371,8 @@ class PlaybackService : Service(), Player.Listener, PlaybackStateManager.Callbac
|
|||
// battery/apk size/cache size
|
||||
val audioRenderer = RenderersFactory { handler, _, audioListener, _, _ ->
|
||||
arrayOf(
|
||||
MediaCodecAudioRenderer(this, MediaCodecSelector.DEFAULT, handler, audioListener)
|
||||
MediaCodecAudioRenderer(this, MediaCodecSelector.DEFAULT, handler, audioListener),
|
||||
LibflacAudioRenderer(handler, audioListener)
|
||||
)
|
||||
}
|
||||
|
||||
|
|
0
gradlew
vendored
Normal file → Executable file
0
gradlew
vendored
Normal file → Executable file
|
@ -27,8 +27,8 @@ ability to be extended to music sources outside of local files. You can read mor
|
|||
#### 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, ACC on all versions of Android. However, FLAC files can only be played
|
||||
on Android 8.1 and above. Below that, Auxio must be patched with the [FLAC Extension](https://github.com/google/ExoPlayer/tree/release-v2/extensions/flac).
|
||||
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 are accents lighter/less saturated in dark mode?
|
||||
|
||||
|
|
85
prebuild.py
Executable file
85
prebuild.py
Executable file
|
@ -0,0 +1,85 @@
|
|||
#!/usr/bin/env python3
|
||||
# This script automatically installs exoplayer with the necessary components.
|
||||
# This is written in version-agnostic python3, because I'd rather
|
||||
# not have to deal with the insanity of bash.
|
||||
import os
|
||||
import platform
|
||||
import sys
|
||||
import subprocess
|
||||
import re
|
||||
|
||||
FLAC_VERSION = "1.3.2"
|
||||
|
||||
FATAL="\033[1;31m"
|
||||
WARN="\033[1;91m"
|
||||
INFO="\033[1;94m"
|
||||
OK="\033[1;92m"
|
||||
NC="\033[0m"
|
||||
|
||||
system = platform.system()
|
||||
|
||||
# We do some shell scripting later on, so we can't support windows.
|
||||
if system not in ["Linux", "Darwin"]:
|
||||
print("fatal: unsupported platform " + system)
|
||||
sys.exit(1)
|
||||
|
||||
def sh(cmd):
|
||||
code = subprocess.call(["sh", "-c", "set -e; " + cmd])
|
||||
|
||||
if code != 0:
|
||||
print(FATAL + "fatal:" + NC + " command failed with exit code " + str(code))
|
||||
sys.exit(1)
|
||||
|
||||
exoplayer_path = os.path.join(os.path.abspath(os.curdir), "deps", "exoplayer")
|
||||
|
||||
if os.path.exists(exoplayer_path):
|
||||
reinstall = input(INFO + "info:" + NC + " ExoPlayer is already installed. Would you like to reinstall it? [y/n] ")
|
||||
|
||||
if not re.match("[yY][eE][sS]|[yY]", reinstall):
|
||||
sys.exit(0)
|
||||
|
||||
ndk_path = os.getenv("NDK_PATH")
|
||||
|
||||
if ndk_path is None or not os.path.isfile(os.path.join(ndk_path, "ndk_build")):
|
||||
# We don't have a proper path. Do some digging on the Android SDK directory
|
||||
# to see if we can find it.
|
||||
if system == "Linux":
|
||||
ndk_root = os.path.join(os.getenv("HOME"), "Android", "Sdk", "ndk")
|
||||
elif system == "Darwin":
|
||||
ndk_root = os.path.join(os.getenv("HOME"), "Library", "Android", "sdk", "ndk")
|
||||
|
||||
candidates = []
|
||||
|
||||
for entry in os.scandir(ndk_root):
|
||||
if entry.is_dir():
|
||||
candidates.append(entry.path)
|
||||
|
||||
if len(candidates) > 0:
|
||||
print(WARN + "warn:" + NC + " NDK_PATH was not set or invalid. Multiple candidates were found however:")
|
||||
|
||||
for i, candidate in enumerate(candidates):
|
||||
print("[" + str(i) + "] " + candidate)
|
||||
|
||||
try:
|
||||
ndk_path = candidates[int(input("Enter the NDK to use [Default 0]: "))]
|
||||
except:
|
||||
ndk_path = candidates[0]
|
||||
else:
|
||||
print(FATAL + "fatal:" + NC + " NDK_PATH is either invalid, or the Android NDK was not installed at a recognized location.")
|
||||
system.exit(1)
|
||||
|
||||
# Now try to install ExoPlayer.
|
||||
sh("rm -rf deps")
|
||||
|
||||
print(INFO + "info:" + NC + " Cloning ExoPlayer...")
|
||||
sh("git clone https://github.com/oxygencobalt/ExoPlayer.git " + exoplayer_path)
|
||||
os.chdir(exoplayer_path)
|
||||
sh("git checkout release-v2")
|
||||
|
||||
flac_ext_jni_path = os.path.join("extensions", "flac", "src", "main", "jni")
|
||||
print(INFO + "info:" + NC + " Installing FLAC extension...")
|
||||
os.chdir(flac_ext_jni_path)
|
||||
sh('curl "https://ftp.osuosl.org/pub/xiph/releases/flac/flac-' + FLAC_VERSION + '.tar.xz" | tar xJ && mv "flac-' + FLAC_VERSION + '" flac')
|
||||
sh(ndk_path + "/ndk-build APP_ABI=all -j4")
|
||||
|
||||
print(OK + "Prebuild successful." + NC)
|
|
@ -1,2 +1,4 @@
|
|||
include ':app'
|
||||
rootProject.name = "Auxio"
|
||||
rootProject.name = "Auxio"
|
||||
gradle.ext.exoplayerModulePrefix = 'exoplayer-'
|
||||
apply from: file("deps/exoplayer/core_settings.gradle")
|
Loading…
Reference in a new issue