From 66db61899c70512990cc20291fac8ef45ac7dd20 Mon Sep 17 00:00:00 2001 From: Alexander Capehart Date: Fri, 17 May 2024 13:38:12 -0600 Subject: [PATCH 01/13] playback: remove custom bitmap loading Media3 simply will not tolerate me doing this. I am basically stuck at the mercy of the Android OS now, until I can have my own unified source of truth with cover loading. --- .../image/service/MediaSessionBitmapLoader.kt | 90 ------------------- .../music/service/MediaItemTranslation.kt | 2 +- .../service/ExoPlaybackStateHolder.kt | 18 ++-- .../service/MediaSessionServiceFragment.kt | 6 +- build.gradle | 2 +- 5 files changed, 16 insertions(+), 102 deletions(-) delete mode 100644 app/src/main/java/org/oxycblt/auxio/image/service/MediaSessionBitmapLoader.kt diff --git a/app/src/main/java/org/oxycblt/auxio/image/service/MediaSessionBitmapLoader.kt b/app/src/main/java/org/oxycblt/auxio/image/service/MediaSessionBitmapLoader.kt deleted file mode 100644 index 3d51677e6..000000000 --- a/app/src/main/java/org/oxycblt/auxio/image/service/MediaSessionBitmapLoader.kt +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (c) 2024 Auxio Project - * MediaSessionBitmapLoader.kt is part of Auxio. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package org.oxycblt.auxio.image.service - -import android.content.Context -import android.graphics.Bitmap -import android.net.Uri -import androidx.media3.common.MediaMetadata -import androidx.media3.common.util.BitmapLoader -import coil.ImageLoader -import coil.memory.MemoryCache -import coil.request.Options -import com.google.common.util.concurrent.ListenableFuture -import com.google.common.util.concurrent.SettableFuture -import dagger.hilt.android.qualifiers.ApplicationContext -import javax.inject.Inject -import org.oxycblt.auxio.image.BitmapProvider -import org.oxycblt.auxio.image.extractor.CoverKeyer -import org.oxycblt.auxio.music.MusicRepository -import org.oxycblt.auxio.music.service.MediaSessionUID - -class MediaSessionBitmapLoader -@Inject -constructor( - @ApplicationContext private val context: Context, - private val musicRepository: MusicRepository, - private val bitmapProvider: BitmapProvider, - private val keyer: CoverKeyer, - private val imageLoader: ImageLoader, -) : BitmapLoader { - override fun decodeBitmap(data: ByteArray): ListenableFuture { - throw NotImplementedError() - } - - override fun loadBitmap(uri: Uri): ListenableFuture { - throw NotImplementedError() - } - - override fun supportsMimeType(mimeType: String): Boolean { - return true - } - - override fun loadBitmapFromMetadata(metadata: MediaMetadata): ListenableFuture? { - val deviceLibrary = musicRepository.deviceLibrary ?: return null - val future = SettableFuture.create() - val song = - when (val uid = - metadata.extras?.getString("uid")?.let { MediaSessionUID.fromString(it) }) { - is MediaSessionUID.Single -> deviceLibrary.findSong(uid.uid) - is MediaSessionUID.Joined -> deviceLibrary.findSong(uid.childUid) - else -> return null - } - ?: return null - // Even launching a coroutine to obtained cached covers is enough to make the notification - // go without covers. - val key = keyer.key(listOf(song.cover), Options(context)) - if (imageLoader.memoryCache?.get(MemoryCache.Key(key)) != null) { - future.set(imageLoader.memoryCache?.get(MemoryCache.Key(key))?.bitmap) - return future - } - bitmapProvider.load( - song, - object : BitmapProvider.Target { - override fun onCompleted(bitmap: Bitmap?) { - if (bitmap == null) { - future.setException(IllegalStateException("Bitmap is null")) - } else { - future.set(bitmap) - } - } - }) - return future - } -} diff --git a/app/src/main/java/org/oxycblt/auxio/music/service/MediaItemTranslation.kt b/app/src/main/java/org/oxycblt/auxio/music/service/MediaItemTranslation.kt index 2e92157b2..bde25c1b5 100644 --- a/app/src/main/java/org/oxycblt/auxio/music/service/MediaItemTranslation.kt +++ b/app/src/main/java/org/oxycblt/auxio/music/service/MediaItemTranslation.kt @@ -74,7 +74,7 @@ fun Song.toMediaItem(context: Context, parent: MusicParent?): MediaItem { .setMediaType(MediaMetadata.MEDIA_TYPE_MUSIC) .setIsPlayable(true) .setIsBrowsable(false) - .setArtworkUri(album.cover.single.mediaStoreCoverUri) + .setArtworkUri(cover.mediaStoreCoverUri) .setExtras( Bundle().apply { putString("uid", mediaSessionUID.toString()) diff --git a/app/src/main/java/org/oxycblt/auxio/playback/service/ExoPlaybackStateHolder.kt b/app/src/main/java/org/oxycblt/auxio/playback/service/ExoPlaybackStateHolder.kt index 070432bc8..e8dca68be 100644 --- a/app/src/main/java/org/oxycblt/auxio/playback/service/ExoPlaybackStateHolder.kt +++ b/app/src/main/java/org/oxycblt/auxio/playback/service/ExoPlaybackStateHolder.kt @@ -21,6 +21,7 @@ package org.oxycblt.auxio.playback.service import android.content.Context import android.content.Intent import android.media.audiofx.AudioEffect +import android.os.Bundle import androidx.media3.common.AudioAttributes import androidx.media3.common.C import androidx.media3.common.MediaItem @@ -42,6 +43,7 @@ import kotlinx.coroutines.delay import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import kotlinx.coroutines.yield +import org.oxycblt.auxio.image.ImageSettings import org.oxycblt.auxio.music.MusicParent import org.oxycblt.auxio.music.MusicRepository import org.oxycblt.auxio.music.Song @@ -69,13 +71,15 @@ class ExoPlaybackStateHolder( private val persistenceRepository: PersistenceRepository, private val playbackSettings: PlaybackSettings, private val commandFactory: PlaybackCommand.Factory, + private val replayGainProcessor: ReplayGainAudioProcessor, private val musicRepository: MusicRepository, - private val replayGainProcessor: ReplayGainAudioProcessor + private val imageSettings: ImageSettings ) : PlaybackStateHolder, Player.Listener, MusicRepository.UpdateListener, - PlaybackSettings.Listener { + PlaybackSettings.Listener, + ImageSettings.Listener { private val saveJob = Job() private val saveScope = CoroutineScope(Dispatchers.IO + saveJob) private val restoreScope = CoroutineScope(Dispatchers.IO + saveJob) @@ -86,6 +90,7 @@ class ExoPlaybackStateHolder( private set fun attach() { + imageSettings.registerListener(this) player.addListener(this) replayGainProcessor.attach() playbackManager.registerStateHolder(this) @@ -99,6 +104,7 @@ class ExoPlaybackStateHolder( playbackManager.unregisterStateHolder(this) musicRepository.removeUpdateListener(this) replayGainProcessor.release() + imageSettings.unregisterListener(this) player.release() } @@ -516,9 +522,10 @@ class ExoPlaybackStateHolder( private val persistenceRepository: PersistenceRepository, private val playbackSettings: PlaybackSettings, private val commandFactory: PlaybackCommand.Factory, - private val musicRepository: MusicRepository, private val mediaSourceFactory: MediaSource.Factory, - private val replayGainProcessor: ReplayGainAudioProcessor + private val replayGainProcessor: ReplayGainAudioProcessor, + private val musicRepository: MusicRepository, + private val imageSettings: ImageSettings, ) { fun create(): ExoPlaybackStateHolder { // Since Auxio is a music player, only specify an audio renderer to save @@ -556,8 +563,9 @@ class ExoPlaybackStateHolder( persistenceRepository, playbackSettings, commandFactory, + replayGainProcessor, musicRepository, - replayGainProcessor) + imageSettings) } } diff --git a/app/src/main/java/org/oxycblt/auxio/playback/service/MediaSessionServiceFragment.kt b/app/src/main/java/org/oxycblt/auxio/playback/service/MediaSessionServiceFragment.kt index a626cd4b6..8152b1053 100644 --- a/app/src/main/java/org/oxycblt/auxio/playback/service/MediaSessionServiceFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/playback/service/MediaSessionServiceFragment.kt @@ -48,7 +48,6 @@ import org.oxycblt.auxio.BuildConfig import org.oxycblt.auxio.ForegroundListener import org.oxycblt.auxio.IntegerTable import org.oxycblt.auxio.R -import org.oxycblt.auxio.image.service.MediaSessionBitmapLoader import org.oxycblt.auxio.music.service.MediaItemBrowser import org.oxycblt.auxio.playback.state.DeferredPlayback import org.oxycblt.auxio.playback.state.PlaybackStateManager @@ -61,7 +60,6 @@ constructor( private val playbackManager: PlaybackStateManager, private val actionHandler: PlaybackActionHandler, private val mediaItemBrowser: MediaItemBrowser, - private val bitmapLoader: MediaSessionBitmapLoader, exoHolderFactory: ExoPlaybackStateHolder.Factory ) : MediaLibrarySession.Callback, @@ -143,9 +141,7 @@ constructor( } private fun createSession(service: MediaLibraryService) = - MediaLibrarySession.Builder(service, exoHolder.mediaSessionPlayer, this) - .setBitmapLoader(bitmapLoader) - .build() + MediaLibrarySession.Builder(service, exoHolder.mediaSessionPlayer, this).build() override fun onConnect( session: MediaSession, diff --git a/build.gradle b/build.gradle index 2b2c7a9c5..a81768d25 100644 --- a/build.gradle +++ b/build.gradle @@ -12,7 +12,7 @@ buildscript { } plugins { - id "com.android.application" version '8.3.2' apply false + id "com.android.application" version '8.4.0' apply false id "androidx.navigation.safeargs.kotlin" version "$navigation_version" apply false id "org.jetbrains.kotlin.android" version "$kotlin_version" apply false id "com.google.devtools.ksp" version '1.9.23-1.0.20' apply false From 8e5d061af5500f506a4caa457aae8cf77472d992 Mon Sep 17 00:00:00 2001 From: Alexander Capehart Date: Fri, 17 May 2024 16:18:01 -0600 Subject: [PATCH 02/13] playback: re-add old swap move Turns out this did have a reason to exist, ExoPlayer doesn't have intrinsic capabilities to update the shuffle order on moves. --- .../oxycblt/auxio/playback/service/ExoPlaybackStateHolder.kt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/org/oxycblt/auxio/playback/service/ExoPlaybackStateHolder.kt b/app/src/main/java/org/oxycblt/auxio/playback/service/ExoPlaybackStateHolder.kt index e8dca68be..8413738b9 100644 --- a/app/src/main/java/org/oxycblt/auxio/playback/service/ExoPlaybackStateHolder.kt +++ b/app/src/main/java/org/oxycblt/auxio/playback/service/ExoPlaybackStateHolder.kt @@ -21,7 +21,6 @@ package org.oxycblt.auxio.playback.service import android.content.Context import android.content.Intent import android.media.audiofx.AudioEffect -import android.os.Bundle import androidx.media3.common.AudioAttributes import androidx.media3.common.C import androidx.media3.common.MediaItem @@ -329,12 +328,16 @@ class ExoPlaybackStateHolder( val trueFrom = indices[from] val trueTo = indices[to] + // ExoPlayer does not actually update it's ShuffleOrder when moving items. Retain a + // semblance of "normalcy" by doing a weird no-op swap that actually moves the item. when { trueFrom > trueTo -> { player.moveMediaItem(trueFrom, trueTo) + player.moveMediaItem(trueTo + 1, trueFrom) } trueTo > trueFrom -> { player.moveMediaItem(trueFrom, trueTo) + player.moveMediaItem(trueTo - 1, trueFrom) } } playbackManager.ack(this, ack) From e1e1e63dbbf79fab1c20d877e4a2d016a0a96b5e Mon Sep 17 00:00:00 2001 From: Alexander Capehart Date: Fri, 17 May 2024 19:00:38 -0600 Subject: [PATCH 03/13] playback: basic tasker plugin No idea if this works. Should be helpful for testing more service independence stuff. --- app/build.gradle | 3 + app/src/main/AndroidManifest.xml | 13 +++ .../java/org/oxycblt/auxio/AuxioService.kt | 4 + .../java/org/oxycblt/auxio/tasker/Start.kt | 79 +++++++++++++++++++ .../java/org/oxycblt/auxio/tasker/Tasker.kt | 19 ----- 5 files changed, 99 insertions(+), 19 deletions(-) create mode 100644 app/src/main/java/org/oxycblt/auxio/tasker/Start.kt delete mode 100644 app/src/main/java/org/oxycblt/auxio/tasker/Tasker.kt diff --git a/app/build.gradle b/app/build.gradle index e43141a3c..f74962d9c 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -151,6 +151,9 @@ dependencies { // Speed dial implementation "com.leinardi.android:speed-dial:3.3.0" + // Tasker + implementation 'com.joaomgcd:taskerpluginlibrary:0.4.10' + // Testing debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.12' testImplementation "junit:junit:4.13.2" diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 53c1b4e2b..a65f67788 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -134,5 +134,18 @@ android:name="android.appwidget.provider" android:resource="@xml/widget_info" /> + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/org/oxycblt/auxio/AuxioService.kt b/app/src/main/java/org/oxycblt/auxio/AuxioService.kt index 64121e6d1..fd44f6a5b 100644 --- a/app/src/main/java/org/oxycblt/auxio/AuxioService.kt +++ b/app/src/main/java/org/oxycblt/auxio/AuxioService.kt @@ -28,6 +28,8 @@ import dagger.hilt.android.AndroidEntryPoint import javax.inject.Inject import org.oxycblt.auxio.music.service.IndexerServiceFragment import org.oxycblt.auxio.playback.service.MediaSessionServiceFragment +import org.oxycblt.auxio.tasker.indicateServiceRunning +import org.oxycblt.auxio.tasker.indicateServiceStopped @AndroidEntryPoint class AuxioService : MediaLibraryService(), ForegroundListener { @@ -40,6 +42,7 @@ class AuxioService : MediaLibraryService(), ForegroundListener { super.onCreate() mediaSessionFragment.attach(this, this) indexingFragment.attach(this) + indicateServiceRunning() } override fun onBind(intent: Intent?): IBinder? { @@ -70,6 +73,7 @@ class AuxioService : MediaLibraryService(), ForegroundListener { override fun onDestroy() { super.onDestroy() + indicateServiceStopped() indexingFragment.release() mediaSessionFragment.release() } diff --git a/app/src/main/java/org/oxycblt/auxio/tasker/Start.kt b/app/src/main/java/org/oxycblt/auxio/tasker/Start.kt new file mode 100644 index 000000000..0191e0133 --- /dev/null +++ b/app/src/main/java/org/oxycblt/auxio/tasker/Start.kt @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2024 Auxio Project + * Start.kt is part of Auxio. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package org.oxycblt.auxio.tasker + +import android.app.Activity +import android.content.Context +import android.content.Intent +import android.os.Bundle +import androidx.core.content.ContextCompat +import com.joaomgcd.taskerpluginlibrary.action.TaskerPluginRunnerActionNoOutputOrInput +import com.joaomgcd.taskerpluginlibrary.config.TaskerPluginConfig +import com.joaomgcd.taskerpluginlibrary.config.TaskerPluginConfigHelperNoOutputOrInput +import com.joaomgcd.taskerpluginlibrary.config.TaskerPluginConfigNoInput +import com.joaomgcd.taskerpluginlibrary.input.TaskerInput +import com.joaomgcd.taskerpluginlibrary.runner.TaskerPluginResult +import com.joaomgcd.taskerpluginlibrary.runner.TaskerPluginResultSucess +import org.oxycblt.auxio.AuxioService + +private var serviceRunning = false + +fun indicateServiceRunning() { + serviceRunning = true +} + +fun indicateServiceStopped() { + serviceRunning = false +} + +class StartActionHelper(config: TaskerPluginConfig) : + TaskerPluginConfigHelperNoOutputOrInput(config) { + override val runnerClass: Class + get() = StartActionRunner::class.java + + override fun addToStringBlurb(input: TaskerInput, blurbBuilder: StringBuilder) { + blurbBuilder.append( + "Starts the Auxio Service. This will block until the service is fully initialized." + + "You must start active playback/foreground state after this or Auxio may" + + "crash.") + } +} + +class StartConfigBasicAction : Activity(), TaskerPluginConfigNoInput { + override val context: Context + get() = applicationContext + + private val taskerHelper by lazy { StartActionHelper(this) } + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + taskerHelper.finishForTasker() + } +} + +class StartActionRunner : TaskerPluginRunnerActionNoOutputOrInput() { + override fun run(context: Context, input: TaskerInput): TaskerPluginResult { + ContextCompat.startForegroundService(context, Intent(context, AuxioService::class.java)) + while (!serviceRunning) { + Thread.sleep(100) + } + + return TaskerPluginResultSucess() + } +} diff --git a/app/src/main/java/org/oxycblt/auxio/tasker/Tasker.kt b/app/src/main/java/org/oxycblt/auxio/tasker/Tasker.kt deleted file mode 100644 index ec2d6ac99..000000000 --- a/app/src/main/java/org/oxycblt/auxio/tasker/Tasker.kt +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright (c) 2024 Auxio Project - * Tasker.kt is part of Auxio. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package org.oxycblt.auxio.tasker From d21a7eee9340ca14ea2395452ad3adf1a9fd6f78 Mon Sep 17 00:00:00 2001 From: Alexander Capehart Date: Fri, 17 May 2024 19:31:33 -0600 Subject: [PATCH 04/13] playback: more coherent notif action setup --- .../service/MediaSessionServiceFragment.kt | 4 ++ .../playback/service/PlaybackActionHandler.kt | 37 ------------------- media | 2 +- 3 files changed, 5 insertions(+), 38 deletions(-) diff --git a/app/src/main/java/org/oxycblt/auxio/playback/service/MediaSessionServiceFragment.kt b/app/src/main/java/org/oxycblt/auxio/playback/service/MediaSessionServiceFragment.kt index 8152b1053..0ac779b04 100644 --- a/app/src/main/java/org/oxycblt/auxio/playback/service/MediaSessionServiceFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/playback/service/MediaSessionServiceFragment.kt @@ -76,6 +76,10 @@ constructor( .setNotificationId(IntegerTable.PLAYBACK_NOTIFICATION_CODE) .setChannelId(BuildConfig.APPLICATION_ID + ".channel.PLAYBACK") .setChannelName(R.string.lbl_playback) + .setPlayDrawableResourceId(R.drawable.ic_play_24) + .setPauseDrawableResourceId(R.drawable.ic_pause_24) + .setSkipNextDrawableResourceId(R.drawable.ic_skip_next_24) + .setSkipPrevDrawableResourceId(R.drawable.ic_skip_prev_24) .build() .also { it.setSmallIcon(R.drawable.ic_auxio_24) } private var foregroundListener: ForegroundListener? = null diff --git a/app/src/main/java/org/oxycblt/auxio/playback/service/PlaybackActionHandler.kt b/app/src/main/java/org/oxycblt/auxio/playback/service/PlaybackActionHandler.kt index 7aa37e36b..8597770de 100644 --- a/app/src/main/java/org/oxycblt/auxio/playback/service/PlaybackActionHandler.kt +++ b/app/src/main/java/org/oxycblt/auxio/playback/service/PlaybackActionHandler.kt @@ -27,7 +27,6 @@ import android.os.Bundle import androidx.core.content.ContextCompat import androidx.media3.common.Player import androidx.media3.session.CommandButton -import androidx.media3.session.DefaultMediaNotificationProvider import androidx.media3.session.SessionCommand import androidx.media3.session.SessionCommands import dagger.hilt.android.qualifiers.ApplicationContext @@ -106,12 +105,6 @@ constructor( .setSessionCommand( SessionCommand(PlaybackActions.ACTION_INC_REPEAT_MODE, Bundle())) .setEnabled(true) - .setExtras( - Bundle().apply { - putInt( - DefaultMediaNotificationProvider.COMMAND_KEY_COMPACT_VIEW_INDEX, - 0) - }) .build()) } ActionMode.SHUFFLE -> { @@ -135,36 +128,6 @@ constructor( .setDisplayName(context.getString(R.string.desc_skip_prev)) .setPlayerCommand(Player.COMMAND_SEEK_TO_PREVIOUS) .setEnabled(true) - .setExtras( - Bundle().apply { - putInt(DefaultMediaNotificationProvider.COMMAND_KEY_COMPACT_VIEW_INDEX, 1) - }) - .build()) - - actions.add( - CommandButton.Builder() - .setIconResId( - if (playbackManager.progression.isPlaying) R.drawable.ic_pause_24 - else R.drawable.ic_play_24) - .setDisplayName(context.getString(R.string.desc_play_pause)) - .setPlayerCommand(Player.COMMAND_PLAY_PAUSE) - .setEnabled(true) - .setExtras( - Bundle().apply { - putInt(DefaultMediaNotificationProvider.COMMAND_KEY_COMPACT_VIEW_INDEX, 2) - }) - .build()) - - actions.add( - CommandButton.Builder() - .setIconResId(R.drawable.ic_skip_next_24) - .setDisplayName(context.getString(R.string.desc_skip_next)) - .setPlayerCommand(Player.COMMAND_SEEK_TO_NEXT) - .setEnabled(true) - .setExtras( - Bundle().apply { - putInt(DefaultMediaNotificationProvider.COMMAND_KEY_COMPACT_VIEW_INDEX, 3) - }) .build()) actions.add( diff --git a/media b/media index 1d58171e1..9d84bc235 160000 --- a/media +++ b/media @@ -1 +1 @@ -Subproject commit 1d58171e16107d73ec3c842319663a8a06bfd23a +Subproject commit 9d84bc2351a21b768a9649bb40a45412259e2cda From 189cc63de771b987cdbb5fc92700a5664028ffee Mon Sep 17 00:00:00 2001 From: Alexander Capehart Date: Fri, 17 May 2024 19:50:12 -0600 Subject: [PATCH 05/13] music: fix incorrect mp4 sort tag interpretation --- media | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/media b/media index 9d84bc235..f445eca7d 160000 --- a/media +++ b/media @@ -1 +1 @@ -Subproject commit 9d84bc2351a21b768a9649bb40a45412259e2cda +Subproject commit f445eca7d09132fa80af301cfa58c4160f958d94 From 9b7053ab7eed8a90089aadccaa392d26e9d3a191 Mon Sep 17 00:00:00 2001 From: Alexander Capehart Date: Fri, 17 May 2024 19:53:03 -0600 Subject: [PATCH 06/13] ui: fix broken selection on editable song --- app/src/main/res/layout/item_editable_song.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/res/layout/item_editable_song.xml b/app/src/main/res/layout/item_editable_song.xml index dbda5a44a..d49f38c95 100644 --- a/app/src/main/res/layout/item_editable_song.xml +++ b/app/src/main/res/layout/item_editable_song.xml @@ -32,7 +32,7 @@ android:id="@+id/interact_body" android:layout_width="match_parent" android:layout_height="wrap_content" - android:background="@drawable/ui_item_ripple"> + android:background="@drawable/ui_item_bg"> Date: Fri, 17 May 2024 20:07:10 -0600 Subject: [PATCH 07/13] info: update changelog --- CHANGELOG.md | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index da465569a..3e669761a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,24 @@ # Changelog -## dev +## 3.5.0 + +#### What's New +- Android Auto support +- Full media browser implementation +- Service can now operate independently of app +- Added basic tasker plugin + +#### What's Improved +- Album covers are now loaded on a per-song basis + +#### What's Fixed +- Fixed repeat mode not restoring on startup + +#### What's Changed +- For the time being, the media notification will not follow Album Covers or 1:1 Covers settings +- Playback will close automatically after some time left idle + +## 3.4.3 #### What's Improved - Added back option disable ReplayGain for poorly tagged libraries From 830ac34b67f5da31aecbd270b735a91859c13bd9 Mon Sep 17 00:00:00 2001 From: Alexander Capehart Date: Fri, 17 May 2024 20:08:04 -0600 Subject: [PATCH 08/13] build: bump to 3.5.0-dev --- app/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index f74962d9c..8071688a0 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -21,8 +21,8 @@ android { defaultConfig { applicationId namespace - versionName "3.4.3" - versionCode 44 + versionName "3.5.0-dev" + versionCode 45 minSdk 24 targetSdk 34 From 51309ebabbd3922449334e9a80879ddb6da91cf4 Mon Sep 17 00:00:00 2001 From: Alexander Capehart Date: Fri, 17 May 2024 21:07:41 -0600 Subject: [PATCH 09/13] tasker: plugin tweaks --- app/src/main/AndroidManifest.xml | 2 +- app/src/main/java/org/oxycblt/auxio/tasker/Start.kt | 9 +++------ 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index a65f67788..d5c61525b 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -141,7 +141,7 @@ android:name=".tasker.StartConfigBasicAction" android:exported="true" android:icon="@mipmap/ic_launcher" - android:label="My Tasker Action"> + android:label="Start Auxio"> diff --git a/app/src/main/java/org/oxycblt/auxio/tasker/Start.kt b/app/src/main/java/org/oxycblt/auxio/tasker/Start.kt index 0191e0133..9e27486c6 100644 --- a/app/src/main/java/org/oxycblt/auxio/tasker/Start.kt +++ b/app/src/main/java/org/oxycblt/auxio/tasker/Start.kt @@ -50,8 +50,8 @@ class StartActionHelper(config: TaskerPluginConfig) : override fun addToStringBlurb(input: TaskerInput, blurbBuilder: StringBuilder) { blurbBuilder.append( "Starts the Auxio Service. This will block until the service is fully initialized." + - "You must start active playback/foreground state after this or Auxio may" + - "crash.") + "You must start active playback/foreground state after this or Auxio may" + + "crash.") } } @@ -70,10 +70,7 @@ class StartConfigBasicAction : Activity(), TaskerPluginConfigNoInput { class StartActionRunner : TaskerPluginRunnerActionNoOutputOrInput() { override fun run(context: Context, input: TaskerInput): TaskerPluginResult { ContextCompat.startForegroundService(context, Intent(context, AuxioService::class.java)) - while (!serviceRunning) { - Thread.sleep(100) - } - + while (!serviceRunning) {} return TaskerPluginResultSucess() } } From 4d1df85b5c7e31e4962c2841b9b3919368253c6c Mon Sep 17 00:00:00 2001 From: Alexander Capehart Date: Fri, 17 May 2024 21:44:11 -0600 Subject: [PATCH 10/13] ui: fix broken editable song bg --- app/src/main/res/drawable/ui_selection_bg.xml | 5 +++++ app/src/main/res/layout/item_editable_song.xml | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 app/src/main/res/drawable/ui_selection_bg.xml diff --git a/app/src/main/res/drawable/ui_selection_bg.xml b/app/src/main/res/drawable/ui_selection_bg.xml new file mode 100644 index 000000000..45a1fd8a1 --- /dev/null +++ b/app/src/main/res/drawable/ui_selection_bg.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_editable_song.xml b/app/src/main/res/layout/item_editable_song.xml index d49f38c95..70567899b 100644 --- a/app/src/main/res/layout/item_editable_song.xml +++ b/app/src/main/res/layout/item_editable_song.xml @@ -32,7 +32,7 @@ android:id="@+id/interact_body" android:layout_width="match_parent" android:layout_height="wrap_content" - android:background="@drawable/ui_item_bg"> + android:background="@drawable/ui_selection_bg"> Date: Fri, 17 May 2024 22:05:17 -0600 Subject: [PATCH 11/13] about: remove yrliet sponsor --- .../java/org/oxycblt/auxio/settings/AboutFragment.kt | 4 ---- app/src/main/res/layout/fragment_about.xml | 12 ------------ app/src/main/res/values/donottranslate.xml | 1 - 3 files changed, 17 deletions(-) diff --git a/app/src/main/java/org/oxycblt/auxio/settings/AboutFragment.kt b/app/src/main/java/org/oxycblt/auxio/settings/AboutFragment.kt index 2ece33656..a80bc446d 100644 --- a/app/src/main/java/org/oxycblt/auxio/settings/AboutFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/settings/AboutFragment.kt @@ -68,9 +68,6 @@ class AboutFragment : ViewBindingFragment() { binding.aboutLicenses.setOnClickListener { requireContext().openInBrowser(LINK_LICENSES) } binding.aboutProfile.setOnClickListener { requireContext().openInBrowser(LINK_PROFILE) } binding.aboutDonate.setOnClickListener { requireContext().openInBrowser(LINK_DONATE) } - binding.aboutSupporterYrliet.setOnClickListener { - requireContext().openInBrowser(LINK_YRLIET) - } binding.aboutSupportersPromo.setOnClickListener { requireContext().openInBrowser(LINK_DONATE) } @@ -100,6 +97,5 @@ class AboutFragment : ViewBindingFragment() { const val LINK_LICENSES = "$LINK_WIKI/Licenses" const val LINK_PROFILE = "https://github.com/OxygenCobalt" const val LINK_DONATE = "https://github.com/sponsors/OxygenCobalt" - const val LINK_YRLIET = "https://github.com/yrliet" } } diff --git a/app/src/main/res/layout/fragment_about.xml b/app/src/main/res/layout/fragment_about.xml index 06211fab4..787fcb546 100644 --- a/app/src/main/res/layout/fragment_about.xml +++ b/app/src/main/res/layout/fragment_about.xml @@ -224,18 +224,6 @@ app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" /> - - Microsoft WAVE - yrliet \ No newline at end of file From b955e2f3abd5238673df80fa6fcdd099e6fceada Mon Sep 17 00:00:00 2001 From: Alexander Capehart Date: Sat, 18 May 2024 11:35:30 -0600 Subject: [PATCH 12/13] playback: re-add notif content intent --- .../auxio/playback/service/MediaSessionServiceFragment.kt | 2 ++ media | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/org/oxycblt/auxio/playback/service/MediaSessionServiceFragment.kt b/app/src/main/java/org/oxycblt/auxio/playback/service/MediaSessionServiceFragment.kt index 0ac779b04..fb884cee3 100644 --- a/app/src/main/java/org/oxycblt/auxio/playback/service/MediaSessionServiceFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/playback/service/MediaSessionServiceFragment.kt @@ -52,6 +52,7 @@ import org.oxycblt.auxio.music.service.MediaItemBrowser import org.oxycblt.auxio.playback.state.DeferredPlayback import org.oxycblt.auxio.playback.state.PlaybackStateManager import org.oxycblt.auxio.util.logD +import org.oxycblt.auxio.util.newMainPendingIntent class MediaSessionServiceFragment @Inject @@ -80,6 +81,7 @@ constructor( .setPauseDrawableResourceId(R.drawable.ic_pause_24) .setSkipNextDrawableResourceId(R.drawable.ic_skip_next_24) .setSkipPrevDrawableResourceId(R.drawable.ic_skip_prev_24) + .setContentIntent(context.newMainPendingIntent()) .build() .also { it.setSmallIcon(R.drawable.ic_auxio_24) } private var foregroundListener: ForegroundListener? = null diff --git a/media b/media index f445eca7d..00124cbac 160000 --- a/media +++ b/media @@ -1 +1 @@ -Subproject commit f445eca7d09132fa80af301cfa58c4160f958d94 +Subproject commit 00124cbac493c06a24e19b01893946bdaf8faf58 From 0f691ee65becd0b64479d3d01409333b08bbf4bd Mon Sep 17 00:00:00 2001 From: Alexander Capehart Date: Sat, 18 May 2024 17:34:42 -0600 Subject: [PATCH 13/13] tasker: remove Can't do this right now, lifecycle is broken. --- CHANGELOG.md | 7 +- app/build.gradle | 3 - app/src/main/AndroidManifest.xml | 12 --- .../java/org/oxycblt/auxio/tasker/Start.kt | 76 ------------------- 4 files changed, 5 insertions(+), 93 deletions(-) delete mode 100644 app/src/main/java/org/oxycblt/auxio/tasker/Start.kt diff --git a/CHANGELOG.md b/CHANGELOG.md index 3e669761a..3907a19ae 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,11 +5,10 @@ #### What's New - Android Auto support - Full media browser implementation -- Service can now operate independently of app -- Added basic tasker plugin #### What's Improved - Album covers are now loaded on a per-song basis +- Correctly interpret MP4 sort tags #### What's Fixed - Fixed repeat mode not restoring on startup @@ -18,6 +17,10 @@ - For the time being, the media notification will not follow Album Covers or 1:1 Covers settings - Playback will close automatically after some time left idle +#### dev -> dev1 changes +- Re-added ability to open app from clicking on notification +- Removed tasker plugin + ## 3.4.3 #### What's Improved diff --git a/app/build.gradle b/app/build.gradle index 8071688a0..f5bf46f91 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -151,9 +151,6 @@ dependencies { // Speed dial implementation "com.leinardi.android:speed-dial:3.3.0" - // Tasker - implementation 'com.joaomgcd:taskerpluginlibrary:0.4.10' - // Testing debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.12' testImplementation "junit:junit:4.13.2" diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index d5c61525b..960d2c8ae 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -135,17 +135,5 @@ android:resource="@xml/widget_info" /> - - - - - - - - \ No newline at end of file diff --git a/app/src/main/java/org/oxycblt/auxio/tasker/Start.kt b/app/src/main/java/org/oxycblt/auxio/tasker/Start.kt deleted file mode 100644 index 9e27486c6..000000000 --- a/app/src/main/java/org/oxycblt/auxio/tasker/Start.kt +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (c) 2024 Auxio Project - * Start.kt is part of Auxio. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package org.oxycblt.auxio.tasker - -import android.app.Activity -import android.content.Context -import android.content.Intent -import android.os.Bundle -import androidx.core.content.ContextCompat -import com.joaomgcd.taskerpluginlibrary.action.TaskerPluginRunnerActionNoOutputOrInput -import com.joaomgcd.taskerpluginlibrary.config.TaskerPluginConfig -import com.joaomgcd.taskerpluginlibrary.config.TaskerPluginConfigHelperNoOutputOrInput -import com.joaomgcd.taskerpluginlibrary.config.TaskerPluginConfigNoInput -import com.joaomgcd.taskerpluginlibrary.input.TaskerInput -import com.joaomgcd.taskerpluginlibrary.runner.TaskerPluginResult -import com.joaomgcd.taskerpluginlibrary.runner.TaskerPluginResultSucess -import org.oxycblt.auxio.AuxioService - -private var serviceRunning = false - -fun indicateServiceRunning() { - serviceRunning = true -} - -fun indicateServiceStopped() { - serviceRunning = false -} - -class StartActionHelper(config: TaskerPluginConfig) : - TaskerPluginConfigHelperNoOutputOrInput(config) { - override val runnerClass: Class - get() = StartActionRunner::class.java - - override fun addToStringBlurb(input: TaskerInput, blurbBuilder: StringBuilder) { - blurbBuilder.append( - "Starts the Auxio Service. This will block until the service is fully initialized." + - "You must start active playback/foreground state after this or Auxio may" + - "crash.") - } -} - -class StartConfigBasicAction : Activity(), TaskerPluginConfigNoInput { - override val context: Context - get() = applicationContext - - private val taskerHelper by lazy { StartActionHelper(this) } - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - taskerHelper.finishForTasker() - } -} - -class StartActionRunner : TaskerPluginRunnerActionNoOutputOrInput() { - override fun run(context: Context, input: TaskerInput): TaskerPluginResult { - ContextCompat.startForegroundService(context, Intent(context, AuxioService::class.java)) - while (!serviceRunning) {} - return TaskerPluginResultSucess() - } -}