Populate ICY headers into MediaMetadata
Populate ICY headers into MediaMetadata so that they can propagate to the app via AnalyticsListener#onMediaMetadataChanged(). This change copies IcyHeaders.name into MediaMetadata.description and IcyHeaders.genre into MediaMetadata.genre. Note: MediaItem.metadata maintain their precedence and overwrite any ICY headers parsed. Issue: google/ExoPlayer#9677 #minor-release PiperOrigin-RevId: 410495676
This commit is contained in:
parent
9d21051c22
commit
d5b6250350
@ -75,6 +75,7 @@ public final class MediaMetadata implements Bundleable {
|
|||||||
@Nullable private Integer totalDiscCount;
|
@Nullable private Integer totalDiscCount;
|
||||||
@Nullable private CharSequence genre;
|
@Nullable private CharSequence genre;
|
||||||
@Nullable private CharSequence compilation;
|
@Nullable private CharSequence compilation;
|
||||||
|
@Nullable private CharSequence station;
|
||||||
@Nullable private Bundle extras;
|
@Nullable private Bundle extras;
|
||||||
|
|
||||||
public Builder() {}
|
public Builder() {}
|
||||||
@ -110,6 +111,7 @@ public final class MediaMetadata implements Bundleable {
|
|||||||
this.totalDiscCount = mediaMetadata.totalDiscCount;
|
this.totalDiscCount = mediaMetadata.totalDiscCount;
|
||||||
this.genre = mediaMetadata.genre;
|
this.genre = mediaMetadata.genre;
|
||||||
this.compilation = mediaMetadata.compilation;
|
this.compilation = mediaMetadata.compilation;
|
||||||
|
this.station = mediaMetadata.station;
|
||||||
this.extras = mediaMetadata.extras;
|
this.extras = mediaMetadata.extras;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -348,6 +350,12 @@ public final class MediaMetadata implements Bundleable {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Sets the name of the station streaming the media. */
|
||||||
|
public Builder setStation(@Nullable CharSequence station) {
|
||||||
|
this.station = station;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/** Sets the extras {@link Bundle}. */
|
/** Sets the extras {@link Bundle}. */
|
||||||
public Builder setExtras(@Nullable Bundle extras) {
|
public Builder setExtras(@Nullable Bundle extras) {
|
||||||
this.extras = extras;
|
this.extras = extras;
|
||||||
@ -490,6 +498,9 @@ public final class MediaMetadata implements Bundleable {
|
|||||||
if (mediaMetadata.compilation != null) {
|
if (mediaMetadata.compilation != null) {
|
||||||
setCompilation(mediaMetadata.compilation);
|
setCompilation(mediaMetadata.compilation);
|
||||||
}
|
}
|
||||||
|
if (mediaMetadata.station != null) {
|
||||||
|
setStation(mediaMetadata.station);
|
||||||
|
}
|
||||||
if (mediaMetadata.extras != null) {
|
if (mediaMetadata.extras != null) {
|
||||||
setExtras(mediaMetadata.extras);
|
setExtras(mediaMetadata.extras);
|
||||||
}
|
}
|
||||||
@ -684,6 +695,8 @@ public final class MediaMetadata implements Bundleable {
|
|||||||
@Nullable public final CharSequence genre;
|
@Nullable public final CharSequence genre;
|
||||||
/** Optional compilation. */
|
/** Optional compilation. */
|
||||||
@Nullable public final CharSequence compilation;
|
@Nullable public final CharSequence compilation;
|
||||||
|
/** Optional name of the station streaming the media. */
|
||||||
|
@Nullable public final CharSequence station;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Optional extras {@link Bundle}.
|
* Optional extras {@link Bundle}.
|
||||||
@ -725,6 +738,7 @@ public final class MediaMetadata implements Bundleable {
|
|||||||
this.totalDiscCount = builder.totalDiscCount;
|
this.totalDiscCount = builder.totalDiscCount;
|
||||||
this.genre = builder.genre;
|
this.genre = builder.genre;
|
||||||
this.compilation = builder.compilation;
|
this.compilation = builder.compilation;
|
||||||
|
this.station = builder.station;
|
||||||
this.extras = builder.extras;
|
this.extras = builder.extras;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -771,7 +785,8 @@ public final class MediaMetadata implements Bundleable {
|
|||||||
&& Util.areEqual(discNumber, that.discNumber)
|
&& Util.areEqual(discNumber, that.discNumber)
|
||||||
&& Util.areEqual(totalDiscCount, that.totalDiscCount)
|
&& Util.areEqual(totalDiscCount, that.totalDiscCount)
|
||||||
&& Util.areEqual(genre, that.genre)
|
&& Util.areEqual(genre, that.genre)
|
||||||
&& Util.areEqual(compilation, that.compilation);
|
&& Util.areEqual(compilation, that.compilation)
|
||||||
|
&& Util.areEqual(station, that.station);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -806,7 +821,8 @@ public final class MediaMetadata implements Bundleable {
|
|||||||
discNumber,
|
discNumber,
|
||||||
totalDiscCount,
|
totalDiscCount,
|
||||||
genre,
|
genre,
|
||||||
compilation);
|
compilation,
|
||||||
|
station);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bundleable implementation.
|
// Bundleable implementation.
|
||||||
@ -844,6 +860,7 @@ public final class MediaMetadata implements Bundleable {
|
|||||||
FIELD_TOTAL_DISC_COUNT,
|
FIELD_TOTAL_DISC_COUNT,
|
||||||
FIELD_GENRE,
|
FIELD_GENRE,
|
||||||
FIELD_COMPILATION,
|
FIELD_COMPILATION,
|
||||||
|
FIELD_STATION,
|
||||||
FIELD_EXTRAS
|
FIELD_EXTRAS
|
||||||
})
|
})
|
||||||
private @interface FieldNumber {}
|
private @interface FieldNumber {}
|
||||||
@ -878,6 +895,7 @@ public final class MediaMetadata implements Bundleable {
|
|||||||
private static final int FIELD_GENRE = 27;
|
private static final int FIELD_GENRE = 27;
|
||||||
private static final int FIELD_COMPILATION = 28;
|
private static final int FIELD_COMPILATION = 28;
|
||||||
private static final int FIELD_ARTWORK_DATA_TYPE = 29;
|
private static final int FIELD_ARTWORK_DATA_TYPE = 29;
|
||||||
|
private static final int FIELD_STATION = 30;
|
||||||
private static final int FIELD_EXTRAS = 1000;
|
private static final int FIELD_EXTRAS = 1000;
|
||||||
|
|
||||||
@UnstableApi
|
@UnstableApi
|
||||||
@ -899,6 +917,7 @@ public final class MediaMetadata implements Bundleable {
|
|||||||
bundle.putCharSequence(keyForField(FIELD_CONDUCTOR), conductor);
|
bundle.putCharSequence(keyForField(FIELD_CONDUCTOR), conductor);
|
||||||
bundle.putCharSequence(keyForField(FIELD_GENRE), genre);
|
bundle.putCharSequence(keyForField(FIELD_GENRE), genre);
|
||||||
bundle.putCharSequence(keyForField(FIELD_COMPILATION), compilation);
|
bundle.putCharSequence(keyForField(FIELD_COMPILATION), compilation);
|
||||||
|
bundle.putCharSequence(keyForField(FIELD_STATION), station);
|
||||||
|
|
||||||
if (userRating != null) {
|
if (userRating != null) {
|
||||||
bundle.putBundle(keyForField(FIELD_USER_RATING), userRating.toBundle());
|
bundle.putBundle(keyForField(FIELD_USER_RATING), userRating.toBundle());
|
||||||
@ -976,6 +995,7 @@ public final class MediaMetadata implements Bundleable {
|
|||||||
.setConductor(bundle.getCharSequence(keyForField(FIELD_CONDUCTOR)))
|
.setConductor(bundle.getCharSequence(keyForField(FIELD_CONDUCTOR)))
|
||||||
.setGenre(bundle.getCharSequence(keyForField(FIELD_GENRE)))
|
.setGenre(bundle.getCharSequence(keyForField(FIELD_GENRE)))
|
||||||
.setCompilation(bundle.getCharSequence(keyForField(FIELD_COMPILATION)))
|
.setCompilation(bundle.getCharSequence(keyForField(FIELD_COMPILATION)))
|
||||||
|
.setStation(bundle.getCharSequence(keyForField(FIELD_STATION)))
|
||||||
.setExtras(bundle.getBundle(keyForField(FIELD_EXTRAS)));
|
.setExtras(bundle.getBundle(keyForField(FIELD_EXTRAS)));
|
||||||
|
|
||||||
if (bundle.containsKey(keyForField(FIELD_USER_RATING))) {
|
if (bundle.containsKey(keyForField(FIELD_USER_RATING))) {
|
||||||
|
@ -64,6 +64,7 @@ public class MediaMetadataTest {
|
|||||||
assertThat(mediaMetadata.totalDiscCount).isNull();
|
assertThat(mediaMetadata.totalDiscCount).isNull();
|
||||||
assertThat(mediaMetadata.genre).isNull();
|
assertThat(mediaMetadata.genre).isNull();
|
||||||
assertThat(mediaMetadata.compilation).isNull();
|
assertThat(mediaMetadata.compilation).isNull();
|
||||||
|
assertThat(mediaMetadata.station).isNull();
|
||||||
assertThat(mediaMetadata.extras).isNull();
|
assertThat(mediaMetadata.extras).isNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -149,6 +150,7 @@ public class MediaMetadataTest {
|
|||||||
.setTotalDiscCount(3)
|
.setTotalDiscCount(3)
|
||||||
.setGenre("Pop")
|
.setGenre("Pop")
|
||||||
.setCompilation("Amazing songs.")
|
.setCompilation("Amazing songs.")
|
||||||
|
.setStation("radio station")
|
||||||
.setExtras(extras)
|
.setExtras(extras)
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,7 @@ import android.os.Parcelable;
|
|||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.media3.common.C;
|
import androidx.media3.common.C;
|
||||||
import androidx.media3.common.Format;
|
import androidx.media3.common.Format;
|
||||||
|
import androidx.media3.common.MediaMetadata;
|
||||||
import androidx.media3.common.Metadata;
|
import androidx.media3.common.Metadata;
|
||||||
import androidx.media3.common.util.Assertions;
|
import androidx.media3.common.util.Assertions;
|
||||||
import androidx.media3.common.util.Log;
|
import androidx.media3.common.util.Log;
|
||||||
@ -171,6 +172,16 @@ public final class IcyHeaders implements Metadata.Entry {
|
|||||||
metadataInterval = in.readInt();
|
metadataInterval = in.readInt();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void populateMediaMetadata(MediaMetadata.Builder builder) {
|
||||||
|
if (name != null) {
|
||||||
|
builder.setStation(name);
|
||||||
|
}
|
||||||
|
if (genre != null) {
|
||||||
|
builder.setGenre(genre);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(@Nullable Object obj) {
|
public boolean equals(@Nullable Object obj) {
|
||||||
if (this == obj) {
|
if (this == obj) {
|
||||||
|
@ -18,6 +18,7 @@ package androidx.media3.extractor.metadata.icy;
|
|||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
|
||||||
import android.os.Parcel;
|
import android.os.Parcel;
|
||||||
|
import androidx.media3.common.MediaMetadata;
|
||||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
@ -45,4 +46,23 @@ public final class IcyHeadersTest {
|
|||||||
// Assert equals.
|
// Assert equals.
|
||||||
assertThat(fromParcelIcyHeaders).isEqualTo(icyHeaders);
|
assertThat(fromParcelIcyHeaders).isEqualTo(icyHeaders);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void populateMediaMetadata() {
|
||||||
|
IcyHeaders headers =
|
||||||
|
new IcyHeaders(
|
||||||
|
/* bitrate= */ 1234,
|
||||||
|
/* genre= */ "pop",
|
||||||
|
/* name= */ "radio station",
|
||||||
|
/* url= */ "url",
|
||||||
|
/* isPublic= */ true,
|
||||||
|
/* metadataInterval= */ 5678);
|
||||||
|
MediaMetadata.Builder builder = new MediaMetadata.Builder();
|
||||||
|
|
||||||
|
headers.populateMediaMetadata(builder);
|
||||||
|
MediaMetadata mediaMetadata = builder.build();
|
||||||
|
|
||||||
|
assertThat(mediaMetadata.station.toString()).isEqualTo("radio station");
|
||||||
|
assertThat(mediaMetadata.genre.toString()).isEqualTo("pop");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user