From e68765887439bfb658b732e6af768a99bc81b251 Mon Sep 17 00:00:00 2001 From: Alexander Capehart Date: Mon, 22 Apr 2024 08:36:59 -0600 Subject: [PATCH 1/4] image: properly handle uniqueness of non-embedded covers Use a UID instead. This is non-ideal but all we can do. --- .../org/oxycblt/auxio/image/extractor/Components.kt | 2 +- .../java/org/oxycblt/auxio/image/extractor/Cover.kt | 11 +++++++++-- .../org/oxycblt/auxio/music/device/DeviceMusicImpl.kt | 6 +++++- 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/org/oxycblt/auxio/image/extractor/Components.kt b/app/src/main/java/org/oxycblt/auxio/image/extractor/Components.kt index 4e3083316..0bf1de4a2 100644 --- a/app/src/main/java/org/oxycblt/auxio/image/extractor/Components.kt +++ b/app/src/main/java/org/oxycblt/auxio/image/extractor/Components.kt @@ -27,7 +27,7 @@ import javax.inject.Inject class CoverKeyer @Inject constructor() : Keyer> { override fun key(data: Collection, options: Options) = - "${data.map { it.perceptualHash }.hashCode()}" + "${data.map { it.uniqueness }.hashCode()}" } class CoverFetcher diff --git a/app/src/main/java/org/oxycblt/auxio/image/extractor/Cover.kt b/app/src/main/java/org/oxycblt/auxio/image/extractor/Cover.kt index 4595a0dcf..bb0b6197f 100644 --- a/app/src/main/java/org/oxycblt/auxio/image/extractor/Cover.kt +++ b/app/src/main/java/org/oxycblt/auxio/image/extractor/Cover.kt @@ -20,6 +20,7 @@ package org.oxycblt.auxio.image.extractor import android.net.Uri import org.oxycblt.auxio.list.sort.Sort +import org.oxycblt.auxio.music.Music import org.oxycblt.auxio.music.Song /** @@ -31,14 +32,20 @@ import org.oxycblt.auxio.music.Song * an album cover. * @author Alexander Capehart (OxygenCobalt) */ -data class Cover(val perceptualHash: String?, val mediaStoreUri: Uri, val songUri: Uri) { +data class Cover(val uniqueness: Uniqueness?, val mediaStoreUri: Uri, val songUri: Uri) { + sealed interface Uniqueness { + data class PerceptualHash(val perceptualHash: String) : Uniqueness + + data class UID(val uid: Music.UID) : Uniqueness + } + companion object { private val FALLBACK_SORT = Sort(Sort.Mode.ByAlbum, Sort.Direction.ASCENDING) fun order(songs: Collection) = FALLBACK_SORT.songs(songs) .map { it.cover } - .groupBy { it.perceptualHash } + .groupBy { it.uniqueness } .entries .sortedByDescending { it.value.size } .map { it.value.first() } diff --git a/app/src/main/java/org/oxycblt/auxio/music/device/DeviceMusicImpl.kt b/app/src/main/java/org/oxycblt/auxio/music/device/DeviceMusicImpl.kt index 6604c3579..96ef5fa3c 100644 --- a/app/src/main/java/org/oxycblt/auxio/music/device/DeviceMusicImpl.kt +++ b/app/src/main/java/org/oxycblt/auxio/music/device/DeviceMusicImpl.kt @@ -114,7 +114,11 @@ class SongImpl( get() = _genres override val cover = - Cover(rawSong.coverPerceptualHash, requireNotNull(rawSong.mediaStoreId).toCoverUri(), uri) + Cover( + rawSong.coverPerceptualHash?.let { Cover.Uniqueness.PerceptualHash(it) } + ?: Cover.Uniqueness.UID(uid), + requireNotNull(rawSong.mediaStoreId).toCoverUri(), + uri) /** * The [RawAlbum] instances collated by the [Song]. This can be used to group [Song]s into an From a4838cefaa5efb20e2d0e801e461141b1579455d Mon Sep 17 00:00:00 2001 From: Alexander Capehart Date: Mon, 22 Apr 2024 10:44:03 -0600 Subject: [PATCH 2/4] image: properly differentiate cover types - If we could find an embedded cover, then we can treat it as a per-song cover - Otherwise, just do our old album-based behavior. --- .../auxio/image/extractor/Components.kt | 2 +- .../oxycblt/auxio/image/extractor/Cover.kt | 35 +++++++++++-------- .../auxio/image/extractor/CoverExtractor.kt | 23 +++++++----- .../auxio/music/device/DeviceMusicImpl.kt | 27 +++++++++----- .../org/oxycblt/auxio/music/fs/StorageUtil.kt | 6 ++-- 5 files changed, 59 insertions(+), 34 deletions(-) diff --git a/app/src/main/java/org/oxycblt/auxio/image/extractor/Components.kt b/app/src/main/java/org/oxycblt/auxio/image/extractor/Components.kt index 0bf1de4a2..f38d00695 100644 --- a/app/src/main/java/org/oxycblt/auxio/image/extractor/Components.kt +++ b/app/src/main/java/org/oxycblt/auxio/image/extractor/Components.kt @@ -27,7 +27,7 @@ import javax.inject.Inject class CoverKeyer @Inject constructor() : Keyer> { override fun key(data: Collection, options: Options) = - "${data.map { it.uniqueness }.hashCode()}" + "${data.map { it.key }.hashCode()}" } class CoverFetcher diff --git a/app/src/main/java/org/oxycblt/auxio/image/extractor/Cover.kt b/app/src/main/java/org/oxycblt/auxio/image/extractor/Cover.kt index bb0b6197f..7e64252f9 100644 --- a/app/src/main/java/org/oxycblt/auxio/image/extractor/Cover.kt +++ b/app/src/main/java/org/oxycblt/auxio/image/extractor/Cover.kt @@ -20,23 +20,28 @@ package org.oxycblt.auxio.image.extractor import android.net.Uri import org.oxycblt.auxio.list.sort.Sort -import org.oxycblt.auxio.music.Music import org.oxycblt.auxio.music.Song -/** - * Bundle of [Uri] information used in [CoverExtractor] to ensure consistent [Uri] use when loading - * images. - * - * @param mediaStoreUri The album cover [Uri] obtained from MediaStore. - * @param song The [Uri] of the first song (by track) of the album, which can also be used to obtain - * an album cover. - * @author Alexander Capehart (OxygenCobalt) - */ -data class Cover(val uniqueness: Uniqueness?, val mediaStoreUri: Uri, val songUri: Uri) { - sealed interface Uniqueness { - data class PerceptualHash(val perceptualHash: String) : Uniqueness +sealed interface Cover { + val key: String + val mediaStoreCoverUri: Uri - data class UID(val uid: Music.UID) : Uniqueness + /** + * The song has an embedded cover art we support, so we can operate with it on a per-song + * basis. + */ + data class Embedded(val songCoverUri: Uri, val songUri: Uri, val perceptualHash: String) : Cover { + override val mediaStoreCoverUri = songCoverUri + override val key = perceptualHash + } + + /** + * We couldn't find any embedded cover art ourselves, but the android system might have some + * through a cover.jpg file or something similar. + */ + data class External(val albumCoverUri: Uri) : Cover { + override val mediaStoreCoverUri = albumCoverUri + override val key = albumCoverUri.toString() } companion object { @@ -45,7 +50,7 @@ data class Cover(val uniqueness: Uniqueness?, val mediaStoreUri: Uri, val songUr fun order(songs: Collection) = FALLBACK_SORT.songs(songs) .map { it.cover } - .groupBy { it.uniqueness } + .groupBy { it.key } .entries .sortedByDescending { it.value.size } .map { it.value.first() } diff --git a/app/src/main/java/org/oxycblt/auxio/image/extractor/CoverExtractor.kt b/app/src/main/java/org/oxycblt/auxio/image/extractor/CoverExtractor.kt index 556b11445..3a6a337ea 100644 --- a/app/src/main/java/org/oxycblt/auxio/image/extractor/CoverExtractor.kt +++ b/app/src/main/java/org/oxycblt/auxio/image/extractor/CoverExtractor.kt @@ -140,21 +140,28 @@ constructor( private suspend fun openCoverInputStream(cover: Cover) = try { - when (imageSettings.coverMode) { - CoverMode.OFF -> null - CoverMode.MEDIA_STORE -> extractMediaStoreCover(cover) - CoverMode.QUALITY -> extractQualityCover(cover) + when (cover) { + is Cover.Embedded -> + when (imageSettings.coverMode) { + CoverMode.OFF -> null + CoverMode.MEDIA_STORE -> extractMediaStoreCover(cover) + CoverMode.QUALITY -> extractQualityCover(cover) + } + + is Cover.External -> { + extractMediaStoreCover(cover) + } } } catch (e: Exception) { logE("Unable to extract album cover due to an error: $e") null } - private suspend fun extractQualityCover(cover: Cover) = + private suspend fun extractQualityCover(cover: Cover.Embedded) = extractAospMetadataCover(cover) ?: extractExoplayerCover(cover) ?: extractMediaStoreCover(cover) - private fun extractAospMetadataCover(cover: Cover): InputStream? = + private fun extractAospMetadataCover(cover: Cover.Embedded): InputStream? = MediaMetadataRetriever().run { // This call is time-consuming but it also doesn't seem to hold up the main thread, // so it's probably fine not to wrap it.rmt @@ -166,7 +173,7 @@ constructor( embeddedPicture?.let { ByteArrayInputStream(it) }.also { release() } } - private suspend fun extractExoplayerCover(cover: Cover): InputStream? { + private suspend fun extractExoplayerCover(cover: Cover.Embedded): InputStream? { val tracks = MetadataRetriever.retrieveMetadata(mediaSourceFactory, MediaItem.fromUri(cover.songUri)) .asDeferred() @@ -186,7 +193,7 @@ constructor( private suspend fun extractMediaStoreCover(cover: Cover) = // Eliminate any chance that this blocking call might mess up the loading process - withContext(Dispatchers.IO) { context.contentResolver.openInputStream(cover.mediaStoreUri) } + withContext(Dispatchers.IO) { context.contentResolver.openInputStream(cover.mediaStoreCoverUri) } /** Derived from phonograph: https://github.com/kabouzeid/Phonograph */ private suspend fun createMosaic(streams: List, size: Size): FetchResult { diff --git a/app/src/main/java/org/oxycblt/auxio/music/device/DeviceMusicImpl.kt b/app/src/main/java/org/oxycblt/auxio/music/device/DeviceMusicImpl.kt index 96ef5fa3c..dcfda228f 100644 --- a/app/src/main/java/org/oxycblt/auxio/music/device/DeviceMusicImpl.kt +++ b/app/src/main/java/org/oxycblt/auxio/music/device/DeviceMusicImpl.kt @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package org.oxycblt.auxio.music.device import org.oxycblt.auxio.R @@ -29,8 +29,9 @@ import org.oxycblt.auxio.music.Music import org.oxycblt.auxio.music.MusicType import org.oxycblt.auxio.music.Song import org.oxycblt.auxio.music.fs.MimeType +import org.oxycblt.auxio.music.fs.toAlbumCoverUri import org.oxycblt.auxio.music.fs.toAudioUri -import org.oxycblt.auxio.music.fs.toCoverUri +import org.oxycblt.auxio.music.fs.toSongCoverUri import org.oxycblt.auxio.music.info.Date import org.oxycblt.auxio.music.info.Disc import org.oxycblt.auxio.music.info.Name @@ -76,7 +77,8 @@ class SongImpl( override val name = nameFactory.parse( requireNotNull(rawSong.name) { "Invalid raw ${rawSong.path}: No title" }, - rawSong.sortName) + rawSong.sortName + ) override val track = rawSong.track override val disc = rawSong.disc?.let { Disc(it, rawSong.subtitle) } @@ -114,11 +116,20 @@ class SongImpl( get() = _genres override val cover = - Cover( - rawSong.coverPerceptualHash?.let { Cover.Uniqueness.PerceptualHash(it) } - ?: Cover.Uniqueness.UID(uid), - requireNotNull(rawSong.mediaStoreId).toCoverUri(), - uri) + rawSong.coverPerceptualHash?.let { + // We were able to confirm that the song had a parsable cover and can be used on + // a per-song basis. Otherwise, just fall back to a per-album cover instead, as + // it implies either a cover.jpg pattern is used (likely) or ExoPlayer does not + // support the cover metadata of a given spec (unlikely). + Cover.Embedded( + requireNotNull(rawSong.mediaStoreId) { "Invalid raw ${rawSong.path}: No id" }.toSongCoverUri(), + uid, + it + ) + } + ?: Cover.External( + requireNotNull(rawSong.albumMediaStoreId).toAlbumCoverUri() + ) /** * The [RawAlbum] instances collated by the [Song]. This can be used to group [Song]s into an diff --git a/app/src/main/java/org/oxycblt/auxio/music/fs/StorageUtil.kt b/app/src/main/java/org/oxycblt/auxio/music/fs/StorageUtil.kt index da61d613b..6cdc7df67 100644 --- a/app/src/main/java/org/oxycblt/auxio/music/fs/StorageUtil.kt +++ b/app/src/main/java/org/oxycblt/auxio/music/fs/StorageUtil.kt @@ -102,13 +102,15 @@ fun Long.toAudioUri() = * @return An external storage image [Uri]. May not exist. * @see ContentUris.withAppendedId */ -fun Long.toCoverUri(): Uri = +fun Long.toSongCoverUri(): Uri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI.buildUpon().run { - appendPath(this@toCoverUri.toString()) + appendPath(this@toSongCoverUri.toString()) appendPath("albumart") build() } +fun Long.toAlbumCoverUri(): Uri = ContentUris.withAppendedId(externalCoversUri, this) + // --- STORAGEMANAGER UTILITIES --- // Largely derived from Material Files: https://github.com/zhanghai/MaterialFiles From aec08bb48b452b8c8ea51febc7e4f93e0c16a66d Mon Sep 17 00:00:00 2001 From: Alexander Capehart Date: Mon, 22 Apr 2024 10:46:44 -0600 Subject: [PATCH 3/4] all: reformat/fixes --- .../main/java/org/oxycblt/auxio/AuxioService.kt | 4 ++-- .../org/oxycblt/auxio/image/extractor/Cover.kt | 6 +++--- .../auxio/image/extractor/CoverExtractor.kt | 5 +++-- .../auxio/list/recycler/MaterialDragCallback.kt | 2 +- .../auxio/music/device/DeviceMusicImpl.kt | 17 +++++++---------- ...erComponent.kt => IndexerServiceFragment.kt} | 4 ++-- .../auxio/music/service/MediaItemTranslation.kt | 10 +++++----- 7 files changed, 23 insertions(+), 25 deletions(-) rename app/src/main/java/org/oxycblt/auxio/music/service/{IndexerComponent.kt => IndexerServiceFragment.kt} (98%) diff --git a/app/src/main/java/org/oxycblt/auxio/AuxioService.kt b/app/src/main/java/org/oxycblt/auxio/AuxioService.kt index 8178a8218..64121e6d1 100644 --- a/app/src/main/java/org/oxycblt/auxio/AuxioService.kt +++ b/app/src/main/java/org/oxycblt/auxio/AuxioService.kt @@ -26,14 +26,14 @@ import androidx.media3.session.MediaLibraryService import androidx.media3.session.MediaSession import dagger.hilt.android.AndroidEntryPoint import javax.inject.Inject -import org.oxycblt.auxio.music.service.IndexingServiceFragment +import org.oxycblt.auxio.music.service.IndexerServiceFragment import org.oxycblt.auxio.playback.service.MediaSessionServiceFragment @AndroidEntryPoint class AuxioService : MediaLibraryService(), ForegroundListener { @Inject lateinit var mediaSessionFragment: MediaSessionServiceFragment - @Inject lateinit var indexingFragment: IndexingServiceFragment + @Inject lateinit var indexingFragment: IndexerServiceFragment @SuppressLint("WrongConstant") override fun onCreate() { diff --git a/app/src/main/java/org/oxycblt/auxio/image/extractor/Cover.kt b/app/src/main/java/org/oxycblt/auxio/image/extractor/Cover.kt index 7e64252f9..bf3cf97cf 100644 --- a/app/src/main/java/org/oxycblt/auxio/image/extractor/Cover.kt +++ b/app/src/main/java/org/oxycblt/auxio/image/extractor/Cover.kt @@ -27,10 +27,10 @@ sealed interface Cover { val mediaStoreCoverUri: Uri /** - * The song has an embedded cover art we support, so we can operate with it on a per-song - * basis. + * The song has an embedded cover art we support, so we can operate with it on a per-song basis. */ - data class Embedded(val songCoverUri: Uri, val songUri: Uri, val perceptualHash: String) : Cover { + data class Embedded(val songCoverUri: Uri, val songUri: Uri, val perceptualHash: String) : + Cover { override val mediaStoreCoverUri = songCoverUri override val key = perceptualHash } diff --git a/app/src/main/java/org/oxycblt/auxio/image/extractor/CoverExtractor.kt b/app/src/main/java/org/oxycblt/auxio/image/extractor/CoverExtractor.kt index 3a6a337ea..d28979b6b 100644 --- a/app/src/main/java/org/oxycblt/auxio/image/extractor/CoverExtractor.kt +++ b/app/src/main/java/org/oxycblt/auxio/image/extractor/CoverExtractor.kt @@ -147,7 +147,6 @@ constructor( CoverMode.MEDIA_STORE -> extractMediaStoreCover(cover) CoverMode.QUALITY -> extractQualityCover(cover) } - is Cover.External -> { extractMediaStoreCover(cover) } @@ -193,7 +192,9 @@ constructor( private suspend fun extractMediaStoreCover(cover: Cover) = // Eliminate any chance that this blocking call might mess up the loading process - withContext(Dispatchers.IO) { context.contentResolver.openInputStream(cover.mediaStoreCoverUri) } + withContext(Dispatchers.IO) { + context.contentResolver.openInputStream(cover.mediaStoreCoverUri) + } /** Derived from phonograph: https://github.com/kabouzeid/Phonograph */ private suspend fun createMosaic(streams: List, size: Size): FetchResult { diff --git a/app/src/main/java/org/oxycblt/auxio/list/recycler/MaterialDragCallback.kt b/app/src/main/java/org/oxycblt/auxio/list/recycler/MaterialDragCallback.kt index 97eed4987..6ccf789b4 100644 --- a/app/src/main/java/org/oxycblt/auxio/list/recycler/MaterialDragCallback.kt +++ b/app/src/main/java/org/oxycblt/auxio/list/recycler/MaterialDragCallback.kt @@ -64,7 +64,7 @@ abstract class MaterialDragCallback : ItemTouchHelper.Callback() { totalSize: Int, msSinceStartScroll: Long ): Int { - // Clamp the scroll speed to prevent thefrom freaking out + // Clamp the scroll speed to prevent the lists from freaking out // Adapted from NewPipe: https://github.com/TeamNewPipe/NewPipe val standardSpeed = super.interpolateOutOfBoundsScroll( diff --git a/app/src/main/java/org/oxycblt/auxio/music/device/DeviceMusicImpl.kt b/app/src/main/java/org/oxycblt/auxio/music/device/DeviceMusicImpl.kt index dcfda228f..674c0cb75 100644 --- a/app/src/main/java/org/oxycblt/auxio/music/device/DeviceMusicImpl.kt +++ b/app/src/main/java/org/oxycblt/auxio/music/device/DeviceMusicImpl.kt @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package org.oxycblt.auxio.music.device import org.oxycblt.auxio.R @@ -77,8 +77,7 @@ class SongImpl( override val name = nameFactory.parse( requireNotNull(rawSong.name) { "Invalid raw ${rawSong.path}: No title" }, - rawSong.sortName - ) + rawSong.sortName) override val track = rawSong.track override val disc = rawSong.disc?.let { Disc(it, rawSong.subtitle) } @@ -122,14 +121,12 @@ class SongImpl( // it implies either a cover.jpg pattern is used (likely) or ExoPlayer does not // support the cover metadata of a given spec (unlikely). Cover.Embedded( - requireNotNull(rawSong.mediaStoreId) { "Invalid raw ${rawSong.path}: No id" }.toSongCoverUri(), - uid, - it - ) + requireNotNull(rawSong.mediaStoreId) { "Invalid raw ${rawSong.path}: No id" } + .toSongCoverUri(), + uri, + it) } - ?: Cover.External( - requireNotNull(rawSong.albumMediaStoreId).toAlbumCoverUri() - ) + ?: Cover.External(requireNotNull(rawSong.albumMediaStoreId).toAlbumCoverUri()) /** * The [RawAlbum] instances collated by the [Song]. This can be used to group [Song]s into an diff --git a/app/src/main/java/org/oxycblt/auxio/music/service/IndexerComponent.kt b/app/src/main/java/org/oxycblt/auxio/music/service/IndexerServiceFragment.kt similarity index 98% rename from app/src/main/java/org/oxycblt/auxio/music/service/IndexerComponent.kt rename to app/src/main/java/org/oxycblt/auxio/music/service/IndexerServiceFragment.kt index 401b49145..6362def6b 100644 --- a/app/src/main/java/org/oxycblt/auxio/music/service/IndexerComponent.kt +++ b/app/src/main/java/org/oxycblt/auxio/music/service/IndexerServiceFragment.kt @@ -1,6 +1,6 @@ /* * Copyright (c) 2024 Auxio Project - * IndexerComponent.kt is part of Auxio. + * IndexerServiceFragment.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 @@ -35,7 +35,7 @@ import org.oxycblt.auxio.playback.state.PlaybackStateManager import org.oxycblt.auxio.util.getSystemServiceCompat import org.oxycblt.auxio.util.logD -class IndexingServiceFragment +class IndexerServiceFragment @Inject constructor( @ApplicationContext override val workerContext: Context, 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 776fed706..2e92157b2 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.mediaStoreUri) + .setArtworkUri(album.cover.single.mediaStoreCoverUri) .setExtras( Bundle().apply { putString("uid", mediaSessionUID.toString()) @@ -105,7 +105,7 @@ fun Album.toMediaItem(context: Context): MediaItem { .setMediaType(MediaMetadata.MEDIA_TYPE_ALBUM) .setIsPlayable(true) .setIsBrowsable(true) - .setArtworkUri(cover.single.mediaStoreUri) + .setArtworkUri(cover.single.mediaStoreCoverUri) .setExtras(Bundle().apply { putString("uid", mediaSessionUID.toString()) }) .build() return MediaItem.Builder() @@ -136,7 +136,7 @@ fun Artist.toMediaItem(context: Context): MediaItem { .setIsPlayable(true) .setIsBrowsable(true) .setGenre(genres.resolveNames(context)) - .setArtworkUri(cover.single.mediaStoreUri) + .setArtworkUri(cover.single.mediaStoreCoverUri) .setExtras(Bundle().apply { putString("uid", mediaSessionUID.toString()) }) .build() return MediaItem.Builder() @@ -159,7 +159,7 @@ fun Genre.toMediaItem(context: Context): MediaItem { .setMediaType(MediaMetadata.MEDIA_TYPE_GENRE) .setIsPlayable(true) .setIsBrowsable(true) - .setArtworkUri(cover.single.mediaStoreUri) + .setArtworkUri(cover.single.mediaStoreCoverUri) .setExtras(Bundle().apply { putString("uid", mediaSessionUID.toString()) }) .build() return MediaItem.Builder() @@ -182,7 +182,7 @@ fun Playlist.toMediaItem(context: Context): MediaItem { .setMediaType(MediaMetadata.MEDIA_TYPE_PLAYLIST) .setIsPlayable(true) .setIsBrowsable(true) - .setArtworkUri(cover?.single?.mediaStoreUri) + .setArtworkUri(cover?.single?.mediaStoreCoverUri) .setExtras(Bundle().apply { putString("uid", mediaSessionUID.toString()) }) .build() return MediaItem.Builder() From f23d1a8eafd682a71c5c5ef777c1696d2eb97120 Mon Sep 17 00:00:00 2001 From: Alexander Capehart Date: Mon, 29 Apr 2024 11:09:08 -0600 Subject: [PATCH 4/4] build: update media --- media | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/media b/media index 6c77cfa13..1d58171e1 160000 --- a/media +++ b/media @@ -1 +1 @@ -Subproject commit 6c77cfa13c83bf2ae5188603d2c9a51ec4cb3ac3 +Subproject commit 1d58171e16107d73ec3c842319663a8a06bfd23a