From c9151c23a27566137b957f71694f8e7b6e67146d Mon Sep 17 00:00:00 2001 From: bachinger Date: Tue, 18 Jan 2022 18:24:31 +0000 Subject: [PATCH] Include audio metadata with DefaultMediaItemConverter for Cast This change adds more standard metadata fields to Cast metadata including the artwork URL that makes the cast device show the artwork in the Cast route dialog (https://screenshot.googleplex.com/uj4n4Jqd7it9bob) and the Cast device. This change also discriminates between media with an audio MIME type and others. For audio MIME type the Cast metadata is set to MEDIA_TYPE_MUSIC_TRACK which changes the layout and shows artwork and additional audio meta data to be displayed (https://screenshot.googleplex.com/ASy3KDcsTdJDM2T). Issue: google/ExoPlayer#9663 PiperOrigin-RevId: 422589957 --- .../cast/DefaultMediaItemConverter.java | 92 ++++++++++++++++--- 1 file changed, 77 insertions(+), 15 deletions(-) diff --git a/libraries/cast/src/main/java/androidx/media3/cast/DefaultMediaItemConverter.java b/libraries/cast/src/main/java/androidx/media3/cast/DefaultMediaItemConverter.java index 62cd2aaf32c..d4bcbd4b9d1 100644 --- a/libraries/cast/src/main/java/androidx/media3/cast/DefaultMediaItemConverter.java +++ b/libraries/cast/src/main/java/androidx/media3/cast/DefaultMediaItemConverter.java @@ -19,11 +19,13 @@ import androidx.annotation.Nullable; import androidx.media3.common.C; import androidx.media3.common.MediaItem; +import androidx.media3.common.MimeTypes; import androidx.media3.common.util.Assertions; import androidx.media3.common.util.UnstableApi; import com.google.android.gms.cast.MediaInfo; import com.google.android.gms.cast.MediaMetadata; import com.google.android.gms.cast.MediaQueueItem; +import com.google.android.gms.common.images.WebImage; import java.util.HashMap; import java.util.Iterator; import java.util.UUID; @@ -47,10 +49,43 @@ public final class DefaultMediaItemConverter implements MediaItemConverter { @Override public MediaItem toMediaItem(MediaQueueItem mediaQueueItem) { - // `item` came from `toMediaQueueItem()` so the custom JSON data must be set. - MediaInfo mediaInfo = mediaQueueItem.getMedia(); + @Nullable MediaInfo mediaInfo = mediaQueueItem.getMedia(); Assertions.checkNotNull(mediaInfo); - return getMediaItem(Assertions.checkNotNull(mediaInfo.getCustomData())); + androidx.media3.common.MediaMetadata.Builder metadataBuilder = + new androidx.media3.common.MediaMetadata.Builder(); + @Nullable MediaMetadata metadata = mediaInfo.getMetadata(); + if (metadata != null) { + if (metadata.containsKey(MediaMetadata.KEY_TITLE)) { + metadataBuilder.setTitle(metadata.getString(MediaMetadata.KEY_TITLE)); + } + if (metadata.containsKey(MediaMetadata.KEY_SUBTITLE)) { + metadataBuilder.setSubtitle(metadata.getString(MediaMetadata.KEY_SUBTITLE)); + } + if (metadata.containsKey(MediaMetadata.KEY_ARTIST)) { + metadataBuilder.setArtist(metadata.getString(MediaMetadata.KEY_ARTIST)); + } + if (metadata.containsKey(MediaMetadata.KEY_ALBUM_ARTIST)) { + metadataBuilder.setAlbumArtist(metadata.getString(MediaMetadata.KEY_ALBUM_ARTIST)); + } + if (metadata.containsKey(MediaMetadata.KEY_ALBUM_TITLE)) { + metadataBuilder.setArtist(metadata.getString(MediaMetadata.KEY_ALBUM_TITLE)); + } + if (!metadata.getImages().isEmpty()) { + metadataBuilder.setArtworkUri(metadata.getImages().get(0).getUrl()); + } + if (metadata.containsKey(MediaMetadata.KEY_COMPOSER)) { + metadataBuilder.setComposer(metadata.getString(MediaMetadata.KEY_COMPOSER)); + } + if (metadata.containsKey(MediaMetadata.KEY_DISC_NUMBER)) { + metadataBuilder.setDiscNumber(metadata.getInt(MediaMetadata.KEY_DISC_NUMBER)); + } + if (metadata.containsKey(MediaMetadata.KEY_TRACK_NUMBER)) { + metadataBuilder.setTrackNumber(metadata.getInt(MediaMetadata.KEY_TRACK_NUMBER)); + } + } + // `mediaQueueItem` came from `toMediaQueueItem()` so the custom JSON data must be set. + return getMediaItem( + Assertions.checkNotNull(mediaInfo.getCustomData()), metadataBuilder.build()); } @Override @@ -59,10 +94,41 @@ public MediaQueueItem toMediaQueueItem(MediaItem mediaItem) { if (mediaItem.localConfiguration.mimeType == null) { throw new IllegalArgumentException("The item must specify its mimeType"); } - MediaMetadata metadata = new MediaMetadata(MediaMetadata.MEDIA_TYPE_MOVIE); + MediaMetadata metadata = + new MediaMetadata( + MimeTypes.isAudio(mediaItem.localConfiguration.mimeType) + ? MediaMetadata.MEDIA_TYPE_MUSIC_TRACK + : MediaMetadata.MEDIA_TYPE_MOVIE); if (mediaItem.mediaMetadata.title != null) { metadata.putString(MediaMetadata.KEY_TITLE, mediaItem.mediaMetadata.title.toString()); } + if (mediaItem.mediaMetadata.subtitle != null) { + metadata.putString(MediaMetadata.KEY_SUBTITLE, mediaItem.mediaMetadata.subtitle.toString()); + } + if (mediaItem.mediaMetadata.artist != null) { + metadata.putString(MediaMetadata.KEY_ARTIST, mediaItem.mediaMetadata.artist.toString()); + } + if (mediaItem.mediaMetadata.albumArtist != null) { + metadata.putString( + MediaMetadata.KEY_ALBUM_ARTIST, mediaItem.mediaMetadata.albumArtist.toString()); + } + if (mediaItem.mediaMetadata.albumTitle != null) { + metadata.putString( + MediaMetadata.KEY_ALBUM_TITLE, mediaItem.mediaMetadata.albumTitle.toString()); + } + if (mediaItem.mediaMetadata.artworkUri != null) { + metadata.addImage(new WebImage(mediaItem.mediaMetadata.artworkUri)); + } + if (mediaItem.mediaMetadata.composer != null) { + metadata.putString(MediaMetadata.KEY_COMPOSER, mediaItem.mediaMetadata.composer.toString()); + } + if (mediaItem.mediaMetadata.discNumber != null) { + metadata.putInt(MediaMetadata.KEY_DISC_NUMBER, mediaItem.mediaMetadata.discNumber); + } + if (mediaItem.mediaMetadata.trackNumber != null) { + metadata.putInt(MediaMetadata.KEY_TRACK_NUMBER, mediaItem.mediaMetadata.trackNumber); + } + MediaInfo mediaInfo = new MediaInfo.Builder(mediaItem.localConfiguration.uri.toString()) .setStreamType(MediaInfo.STREAM_TYPE_BUFFERED) @@ -75,19 +141,15 @@ public MediaQueueItem toMediaQueueItem(MediaItem mediaItem) { // Deserialization. - private static MediaItem getMediaItem(JSONObject customData) { + private static MediaItem getMediaItem( + JSONObject customData, androidx.media3.common.MediaMetadata mediaMetadata) { try { JSONObject mediaItemJson = customData.getJSONObject(KEY_MEDIA_ITEM); - MediaItem.Builder builder = new MediaItem.Builder(); - builder.setUri(Uri.parse(mediaItemJson.getString(KEY_URI))); - builder.setMediaId(mediaItemJson.getString(KEY_MEDIA_ID)); - if (mediaItemJson.has(KEY_TITLE)) { - androidx.media3.common.MediaMetadata mediaMetadata = - new androidx.media3.common.MediaMetadata.Builder() - .setTitle(mediaItemJson.getString(KEY_TITLE)) - .build(); - builder.setMediaMetadata(mediaMetadata); - } + MediaItem.Builder builder = + new MediaItem.Builder() + .setUri(Uri.parse(mediaItemJson.getString(KEY_URI))) + .setMediaId(mediaItemJson.getString(KEY_MEDIA_ID)) + .setMediaMetadata(mediaMetadata); if (mediaItemJson.has(KEY_MIME_TYPE)) { builder.setMimeType(mediaItemJson.getString(KEY_MIME_TYPE)); }