From 213409924b7bb79bb7dc1107c75f6e6adde71acb Mon Sep 17 00:00:00 2001 From: Alexander Capehart Date: Mon, 13 Feb 2023 09:05:36 -0700 Subject: [PATCH] playback: switch to ffmpeg extension Switch to the FFMpeg ExoPlayer extension, which should enable support for ALAC while also retaining support for FLAC below Android 8. --- CHANGELOG.md | 2 ++ app/build.gradle | 1 - .../auxio/music/cache/CacheDatabase.kt | 4 +-- .../oxycblt/auxio/music/cache/CacheModule.kt | 2 -- .../auxio/music/cache/CacheRepository.kt | 4 +-- .../oxycblt/auxio/music/storage/Filesystem.kt | 2 ++ .../music/storage/MediaStoreExtractor.kt | 2 +- .../org/oxycblt/auxio/music/system/Indexer.kt | 2 +- .../auxio/music/system/IndexerService.kt | 6 ++-- .../auxio/playback/system/PlaybackService.kt | 4 +-- .../auxio/ui/RippleFixMaterialButton.kt | 8 +++-- .../oxycblt/auxio/widgets/WidgetProvider.kt | 2 -- .../res/layout/view_preference_switch.xml | 1 - app/src/main/res/values/styles_ui.xml | 1 + prebuild.py | 32 +++++++++++-------- 15 files changed, 40 insertions(+), 33 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2fbdc1ee5..18d3fa24b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ #### What's New - Added support for disc subtitles +- Added support for ALAC files #### What's Improved - Auxio will now accept zeroed track/disc numbers in the presence of non-zero total @@ -11,6 +12,7 @@ track/disc fields - Music loading has been made slightly faster - Improved sort menu usability - Fall back to `TXXX:RELEASETYPE` on ID3v2 files +- Switches and checkboxes have been mildly visually refreshed #### What's Fixed - Fixed non-functioning "repeat all" repeat mode diff --git a/app/build.gradle b/app/build.gradle index d48bce1cd..02626b87e 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -127,7 +127,6 @@ dependencies { kapt "com.google.dagger:dagger-compiler:$dagger_version" implementation "com.google.dagger:hilt-android:$hilt_version" kapt "com.google.dagger:hilt-android-compiler:$hilt_version" - // Testing debugImplementation "com.squareup.leakcanary:leakcanary-android:2.9.1" testImplementation "junit:junit:4.13.2" diff --git a/app/src/main/java/org/oxycblt/auxio/music/cache/CacheDatabase.kt b/app/src/main/java/org/oxycblt/auxio/music/cache/CacheDatabase.kt index 3cf4f215f..3d3957d08 100644 --- a/app/src/main/java/org/oxycblt/auxio/music/cache/CacheDatabase.kt +++ b/app/src/main/java/org/oxycblt/auxio/music/cache/CacheDatabase.kt @@ -47,13 +47,13 @@ interface CachedSongsDao { @TypeConverters(CachedSong.Converters::class) data class CachedSong( /** - * The ID of the [Song]'s audio file, obtained from MediaStore. Note that this ID is highly + * The ID of the [RawSong]'s audio file, obtained from MediaStore. Note that this ID is highly * unstable and should only be used for accessing the audio file. */ @PrimaryKey var mediaStoreId: Long, /** @see RawSong.dateAdded */ var dateAdded: Long, - /** The latest date the [Song]'s audio file was modified, as a unix epoch timestamp. */ + /** The latest date the [RawSong]'s audio file was modified, as a unix epoch timestamp. */ var dateModified: Long, /** @see RawSong.size */ var size: Long? = null, diff --git a/app/src/main/java/org/oxycblt/auxio/music/cache/CacheModule.kt b/app/src/main/java/org/oxycblt/auxio/music/cache/CacheModule.kt index 992704084..4dac9555d 100644 --- a/app/src/main/java/org/oxycblt/auxio/music/cache/CacheModule.kt +++ b/app/src/main/java/org/oxycblt/auxio/music/cache/CacheModule.kt @@ -26,8 +26,6 @@ import dagger.hilt.InstallIn import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.components.SingletonComponent import javax.inject.Singleton -import org.oxycblt.auxio.music.extractor.CacheRepository -import org.oxycblt.auxio.music.extractor.CacheRepositoryImpl @Module @InstallIn(SingletonComponent::class) diff --git a/app/src/main/java/org/oxycblt/auxio/music/cache/CacheRepository.kt b/app/src/main/java/org/oxycblt/auxio/music/cache/CacheRepository.kt index de1fefce2..34b19a617 100644 --- a/app/src/main/java/org/oxycblt/auxio/music/cache/CacheRepository.kt +++ b/app/src/main/java/org/oxycblt/auxio/music/cache/CacheRepository.kt @@ -15,11 +15,9 @@ * along with this program. If not, see . */ -package org.oxycblt.auxio.music.extractor +package org.oxycblt.auxio.music.cache import javax.inject.Inject -import org.oxycblt.auxio.music.cache.CachedSong -import org.oxycblt.auxio.music.cache.CachedSongsDao import org.oxycblt.auxio.music.model.RawSong import org.oxycblt.auxio.util.* diff --git a/app/src/main/java/org/oxycblt/auxio/music/storage/Filesystem.kt b/app/src/main/java/org/oxycblt/auxio/music/storage/Filesystem.kt index 1ca010d92..73c969633 100644 --- a/app/src/main/java/org/oxycblt/auxio/music/storage/Filesystem.kt +++ b/app/src/main/java/org/oxycblt/auxio/music/storage/Filesystem.kt @@ -157,6 +157,8 @@ data class MimeType(val fromExtension: String, val fromFormat: String?) { MediaFormat.MIMETYPE_AUDIO_VORBIS -> R.string.cdc_vorbis MediaFormat.MIMETYPE_AUDIO_OPUS -> R.string.cdc_opus MediaFormat.MIMETYPE_AUDIO_FLAC -> R.string.cdc_flac + // TODO: Add ALAC to this as soon as I can stop using MediaFormat for + // extracting metadata and just use ExoPlayer. // We don't give a name to more unpopular formats. else -> -1 } diff --git a/app/src/main/java/org/oxycblt/auxio/music/storage/MediaStoreExtractor.kt b/app/src/main/java/org/oxycblt/auxio/music/storage/MediaStoreExtractor.kt index 6308b450d..32912061d 100644 --- a/app/src/main/java/org/oxycblt/auxio/music/storage/MediaStoreExtractor.kt +++ b/app/src/main/java/org/oxycblt/auxio/music/storage/MediaStoreExtractor.kt @@ -29,7 +29,7 @@ import java.io.File import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.yield import org.oxycblt.auxio.music.MusicSettings -import org.oxycblt.auxio.music.extractor.Cache +import org.oxycblt.auxio.music.cache.Cache import org.oxycblt.auxio.music.metadata.Date import org.oxycblt.auxio.music.metadata.parseId3v2PositionField import org.oxycblt.auxio.music.metadata.transformPositionField diff --git a/app/src/main/java/org/oxycblt/auxio/music/system/Indexer.kt b/app/src/main/java/org/oxycblt/auxio/music/system/Indexer.kt index fbc62f42f..cd6a591a9 100644 --- a/app/src/main/java/org/oxycblt/auxio/music/system/Indexer.kt +++ b/app/src/main/java/org/oxycblt/auxio/music/system/Indexer.kt @@ -35,7 +35,7 @@ import kotlinx.coroutines.withContext import kotlinx.coroutines.yield import org.oxycblt.auxio.BuildConfig import org.oxycblt.auxio.music.* -import org.oxycblt.auxio.music.extractor.* +import org.oxycblt.auxio.music.cache.CacheRepository import org.oxycblt.auxio.music.metadata.TagExtractor import org.oxycblt.auxio.music.model.Library import org.oxycblt.auxio.music.model.RawSong diff --git a/app/src/main/java/org/oxycblt/auxio/music/system/IndexerService.kt b/app/src/main/java/org/oxycblt/auxio/music/system/IndexerService.kt index 0a1b80254..81e22ce51 100644 --- a/app/src/main/java/org/oxycblt/auxio/music/system/IndexerService.kt +++ b/app/src/main/java/org/oxycblt/auxio/music/system/IndexerService.kt @@ -56,8 +56,10 @@ import org.oxycblt.auxio.util.logD */ @AndroidEntryPoint class IndexerService : Service(), Indexer.Controller, MusicSettings.Listener { - @Inject lateinit var indexer: Indexer + @Inject lateinit var imageLoader: ImageLoader @Inject lateinit var musicRepository: MusicRepository + @Inject lateinit var indexer: Indexer + @Inject lateinit var musicSettings: MusicSettings @Inject lateinit var playbackManager: PlaybackStateManager private val serviceJob = Job() private val indexScope = CoroutineScope(serviceJob + Dispatchers.IO) @@ -67,8 +69,6 @@ class IndexerService : Service(), Indexer.Controller, MusicSettings.Listener { private lateinit var observingNotification: ObservingNotification private lateinit var wakeLock: PowerManager.WakeLock private lateinit var indexerContentObserver: SystemContentObserver - @Inject lateinit var musicSettings: MusicSettings - @Inject lateinit var imageLoader: ImageLoader override fun onCreate() { super.onCreate() diff --git a/app/src/main/java/org/oxycblt/auxio/playback/system/PlaybackService.kt b/app/src/main/java/org/oxycblt/auxio/playback/system/PlaybackService.kt index edc0fd119..a42be58c3 100644 --- a/app/src/main/java/org/oxycblt/auxio/playback/system/PlaybackService.kt +++ b/app/src/main/java/org/oxycblt/auxio/playback/system/PlaybackService.kt @@ -34,7 +34,7 @@ import com.google.android.exoplayer2.RenderersFactory import com.google.android.exoplayer2.audio.AudioAttributes import com.google.android.exoplayer2.audio.AudioCapabilities import com.google.android.exoplayer2.audio.MediaCodecAudioRenderer -import com.google.android.exoplayer2.ext.flac.LibflacAudioRenderer +import com.google.android.exoplayer2.ext.ffmpeg.FfmpegAudioRenderer import com.google.android.exoplayer2.extractor.DefaultExtractorsFactory import com.google.android.exoplayer2.mediacodec.MediaCodecSelector import com.google.android.exoplayer2.source.DefaultMediaSourceFactory @@ -128,7 +128,7 @@ class PlaybackService : audioListener, AudioCapabilities.DEFAULT_AUDIO_CAPABILITIES, replayGainProcessor), - LibflacAudioRenderer(handler, audioListener, replayGainProcessor)) + FfmpegAudioRenderer(handler, audioListener, replayGainProcessor)) } player = diff --git a/app/src/main/java/org/oxycblt/auxio/ui/RippleFixMaterialButton.kt b/app/src/main/java/org/oxycblt/auxio/ui/RippleFixMaterialButton.kt index 4741606cd..514858f63 100644 --- a/app/src/main/java/org/oxycblt/auxio/ui/RippleFixMaterialButton.kt +++ b/app/src/main/java/org/oxycblt/auxio/ui/RippleFixMaterialButton.kt @@ -21,6 +21,7 @@ import android.content.Context import android.util.AttributeSet import androidx.annotation.AttrRes import com.google.android.material.button.MaterialButton +import org.oxycblt.auxio.R import org.oxycblt.auxio.util.fixDoubleRipple /** @@ -30,8 +31,11 @@ import org.oxycblt.auxio.util.fixDoubleRipple */ open class RippleFixMaterialButton @JvmOverloads -constructor(context: Context, attrs: AttributeSet? = null, @AttrRes defStyleAttr: Int = 0) : - MaterialButton(context, attrs, defStyleAttr) { +constructor( + context: Context, + attrs: AttributeSet? = null, + @AttrRes defStyleAttr: Int = R.attr.materialButtonStyle +) : MaterialButton(context, attrs, defStyleAttr) { init { fixDoubleRipple() } diff --git a/app/src/main/java/org/oxycblt/auxio/widgets/WidgetProvider.kt b/app/src/main/java/org/oxycblt/auxio/widgets/WidgetProvider.kt index 07f0fdc32..813105c7f 100644 --- a/app/src/main/java/org/oxycblt/auxio/widgets/WidgetProvider.kt +++ b/app/src/main/java/org/oxycblt/auxio/widgets/WidgetProvider.kt @@ -196,7 +196,6 @@ class WidgetProvider : AppWidgetProvider() { /** * Set up the control bar in a [RemoteViews] layout that contains one. This is a kind of * "floating" drawable that sits in front of the cover and contains the controls. - * @param context [Context] required to set up the view. */ private fun RemoteViews.setupBar(): RemoteViews { // Below API 31, enable a rounded bar only if round mode is enabled. @@ -214,7 +213,6 @@ class WidgetProvider : AppWidgetProvider() { /** * Set up the background in a [RemoteViews] layout that contains one. This is largely * self-explanatory, being a solid-color background that sits behind the cover and controls. - * @param context [Context] required to set up the view. */ private fun RemoteViews.setupBackground(): RemoteViews { // Below API 31, enable a rounded background only if round mode is enabled. diff --git a/app/src/main/res/layout/view_preference_switch.xml b/app/src/main/res/layout/view_preference_switch.xml index b1f3a1435..51b1df5ad 100644 --- a/app/src/main/res/layout/view_preference_switch.xml +++ b/app/src/main/res/layout/view_preference_switch.xml @@ -1,6 +1,5 @@ \ No newline at end of file diff --git a/app/src/main/res/values/styles_ui.xml b/app/src/main/res/values/styles_ui.xml index b184ad116..d6f9e5d21 100644 --- a/app/src/main/res/values/styles_ui.xml +++ b/app/src/main/res/values/styles_ui.xml @@ -5,6 +5,7 @@ diff --git a/prebuild.py b/prebuild.py index 09e632feb..3610d3ac1 100755 --- a/prebuild.py +++ b/prebuild.py @@ -17,10 +17,8 @@ import sys import subprocess import re -# WARNING: THE EXOPLAYER VERSION MUST BE KEPT IN LOCK-STEP WITH THE FLAC EXTENSION AND +# WARNING: THE EXOPLAYER VERSION MUST BE KEPT IN LOCK-STEP WITH THE FFMPEG EXTENSION AND # THE GRADLE DEPENDENCY. IF NOT, VERY UNFRIENDLY BUILD FAILURES AND CRASHES MAY ENSUE. -# EXO_VERSION = "2.18.2" -FLAC_VERSION = "1.3.2" OK="\033[1;32m" # Bold green FATAL="\033[1;31m" # Bold red @@ -102,18 +100,26 @@ sh("git clone https://github.com/OxygenCobalt/ExoPlayer.git " + exoplayer_path) os.chdir(exoplayer_path) sh("git checkout auxio") -print(INFO + "info:" + NC + " assembling flac extension...") -flac_ext_aar_path = os.path.join(exoplayer_path, "extensions", "flac", - "buildout", "outputs", "aar", "extension-flac-release.aar") -flac_ext_jni_path = os.path.join("extensions", "flac", "src", "main", "jni") +print(INFO + "info:" + NC + " assembling ffmpeg extension...") +if system == "Linux": + host = "linux-x86_64" +elif system == "Darwin": + host = "darwin-x86_64" -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_build_path + " APP_ABI=all -j4") +ffmpeg_ext_path = os.path.join(exoplayer_path, "extensions", "ffmpeg", "src", "main") +ffmpeg_ext_aar_path = os.path.join(exoplayer_path, "extensions", "ffmpeg", "buildout", "outputs", "aar", "extension-ffmpeg-release.aar") +ffmpeg_ext_jni_path = os.path.join(exoplayer_path, "extensions", "ffmpeg", "src", "main", "jni") +ffmpeg_src_path = os.path.join(ffmpeg_ext_jni_path, "ffmpeg") + +os.chdir(ffmpeg_ext_jni_path) +sh("git clone git://source.ffmpeg.org/ffmpeg ffmpeg") +os.chdir(ffmpeg_src_path) +sh("git checkout release/4.2") +os.chdir(ffmpeg_ext_jni_path) +sh('./build_ffmpeg.sh "' + ffmpeg_ext_path + '" "' + ndk_path + '" "' + host + '" "' + "flac" + '" "' + "alac" + '"') os.chdir(exoplayer_path) -sh("./gradlew extension-flac:bundleReleaseAar") +sh("./gradlew extension-ffmpeg:bundleReleaseAar") print(INFO + "info:" + NC + " assembling extractor component...") @@ -124,7 +130,7 @@ sh("./gradlew library-extractor:bundleReleaseAar") os.chdir(start_path) sh("mkdir " + libs_path) -sh("cp " + flac_ext_aar_path + " " + libs_path) +sh("cp " + ffmpeg_ext_aar_path + " " + libs_path) sh("cp " + extractor_aar_path + " " + libs_path) print(OK + "success:" + NC + " completed pre-build")