Skip to content

Commit

Permalink
Pass the raw ICY metadata through IcyInfo
Browse files Browse the repository at this point in the history
The ICY 'spec' isn't really clear/tight enough to do anything more
specific than this I think.

Issue:#6476
PiperOrigin-RevId: 272405322
  • Loading branch information
icbaker authored and ojw28 committed Oct 13, 2019
1 parent 15df31b commit e0c8cbe
Show file tree
Hide file tree
Showing 5 changed files with 61 additions and 26 deletions.
2 changes: 2 additions & 0 deletions RELEASENOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
* Add `Player.onPlaybackSuppressionReasonChanged` to allow listeners to
detect playbacks suppressions (e.g. audio focus loss) directly
([#6203](https://github.com/google/ExoPlayer/issues/6203)).
* Expose the raw ICY metadata through `IcyInfo`
([#6476](https://github.com/google/ExoPlayer/issues/6476)).

### 2.10.5 (2019-09-20) ###

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,10 @@
*/
package com.google.android.exoplayer2.metadata.icy;

import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import com.google.android.exoplayer2.metadata.Metadata;
import com.google.android.exoplayer2.metadata.MetadataDecoder;
import com.google.android.exoplayer2.metadata.MetadataInputBuffer;
import com.google.android.exoplayer2.util.Log;
import com.google.android.exoplayer2.util.Util;
import java.nio.ByteBuffer;
import java.util.regex.Matcher;
Expand All @@ -36,7 +34,6 @@ public final class IcyDecoder implements MetadataDecoder {
private static final String STREAM_KEY_URL = "streamurl";

@Override
@Nullable
@SuppressWarnings("ByteBufferBackingArray")
public Metadata decode(MetadataInputBuffer inputBuffer) {
ByteBuffer buffer = inputBuffer.data;
Expand All @@ -45,7 +42,6 @@ public Metadata decode(MetadataInputBuffer inputBuffer) {
return decode(Util.fromUtf8Bytes(data, 0, length));
}

@Nullable
@VisibleForTesting
/* package */ Metadata decode(String metadata) {
String name = null;
Expand All @@ -62,12 +58,9 @@ public Metadata decode(MetadataInputBuffer inputBuffer) {
case STREAM_KEY_URL:
url = value;
break;
default:
Log.w(TAG, "Unrecognized ICY tag: " + name);
break;
}
index = matcher.end();
}
return (name != null || url != null) ? new Metadata(new IcyInfo(name, url)) : null;
return new Metadata(new IcyInfo(metadata, name, url));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,26 +19,35 @@
import android.os.Parcelable;
import androidx.annotation.Nullable;
import com.google.android.exoplayer2.metadata.Metadata;
import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.Util;

/** ICY in-stream information. */
public final class IcyInfo implements Metadata.Entry {

/** The complete metadata string used to construct this IcyInfo. */
public final String rawMetadata;
/** The stream title if present, or {@code null}. */
@Nullable public final String title;
/** The stream title if present, or {@code null}. */
/** The stream URL if present, or {@code null}. */
@Nullable public final String url;

/**
* Construct a new IcyInfo from the source metadata string, and optionally a StreamTitle &
* StreamUrl that have been extracted.
*
* @param rawMetadata See {@link #rawMetadata}.
* @param title See {@link #title}.
* @param url See {@link #url}.
*/
public IcyInfo(@Nullable String title, @Nullable String url) {
public IcyInfo(String rawMetadata, @Nullable String title, @Nullable String url) {
this.rawMetadata = rawMetadata;
this.title = title;
this.url = url;
}

/* package */ IcyInfo(Parcel in) {
rawMetadata = Assertions.checkNotNull(in.readString());
title = in.readString();
url = in.readString();
}
Expand All @@ -52,26 +61,27 @@ public boolean equals(@Nullable Object obj) {
return false;
}
IcyInfo other = (IcyInfo) obj;
return Util.areEqual(title, other.title) && Util.areEqual(url, other.url);
// title & url are derived from rawMetadata, so no need to include them in the comparison.
return Util.areEqual(rawMetadata, other.rawMetadata);
}

@Override
public int hashCode() {
int result = 17;
result = 31 * result + (title != null ? title.hashCode() : 0);
result = 31 * result + (url != null ? url.hashCode() : 0);
return result;
// title & url are derived from rawMetadata, so no need to include them in the hash.
return rawMetadata.hashCode();
}

@Override
public String toString() {
return "ICY: title=\"" + title + "\", url=\"" + url + "\"";
return String.format(
"ICY: title=\"%s\", url=\"%s\", rawMetadata=\"%s\"", title, url, rawMetadata);
}

// Parcelable implementation.

@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(rawMetadata);
dest.writeString(title);
dest.writeString(url);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,74 +29,104 @@ public final class IcyDecoderTest {
@Test
public void decode() {
IcyDecoder decoder = new IcyDecoder();
Metadata metadata = decoder.decode("StreamTitle='test title';StreamURL='test_url';");
String icyContent = "StreamTitle='test title';StreamURL='test_url';";
Metadata metadata = decoder.decode(icyContent);

assertThat(metadata.length()).isEqualTo(1);
IcyInfo streamInfo = (IcyInfo) metadata.get(0);
assertThat(streamInfo.rawMetadata).isEqualTo(icyContent);
assertThat(streamInfo.title).isEqualTo("test title");
assertThat(streamInfo.url).isEqualTo("test_url");
}

@Test
public void decode_titleOnly() {
IcyDecoder decoder = new IcyDecoder();
Metadata metadata = decoder.decode("StreamTitle='test title';");
String icyContent = "StreamTitle='test title';";
Metadata metadata = decoder.decode(icyContent);

assertThat(metadata.length()).isEqualTo(1);
IcyInfo streamInfo = (IcyInfo) metadata.get(0);
assertThat(streamInfo.rawMetadata).isEqualTo(icyContent);
assertThat(streamInfo.title).isEqualTo("test title");
assertThat(streamInfo.url).isNull();
}

@Test
public void decode_extraTags() {
String icyContent =
"StreamTitle='test title';StreamURL='test_url';CustomTag|withWeirdSeparator";
IcyDecoder decoder = new IcyDecoder();
Metadata metadata = decoder.decode(icyContent);

assertThat(metadata.length()).isEqualTo(1);
IcyInfo streamInfo = (IcyInfo) metadata.get(0);
assertThat(streamInfo.rawMetadata).isEqualTo(icyContent);
assertThat(streamInfo.title).isEqualTo("test title");
assertThat(streamInfo.url).isEqualTo("test_url");
}

@Test
public void decode_emptyTitle() {
IcyDecoder decoder = new IcyDecoder();
Metadata metadata = decoder.decode("StreamTitle='';StreamURL='test_url';");
String icyContent = "StreamTitle='';StreamURL='test_url';";
Metadata metadata = decoder.decode(icyContent);

assertThat(metadata.length()).isEqualTo(1);
IcyInfo streamInfo = (IcyInfo) metadata.get(0);
assertThat(streamInfo.rawMetadata).isEqualTo(icyContent);
assertThat(streamInfo.title).isEmpty();
assertThat(streamInfo.url).isEqualTo("test_url");
}

@Test
public void decode_semiColonInTitle() {
IcyDecoder decoder = new IcyDecoder();
Metadata metadata = decoder.decode("StreamTitle='test; title';StreamURL='test_url';");
String icyContent = "StreamTitle='test; title';StreamURL='test_url';";
Metadata metadata = decoder.decode(icyContent);

assertThat(metadata.length()).isEqualTo(1);
IcyInfo streamInfo = (IcyInfo) metadata.get(0);
assertThat(streamInfo.rawMetadata).isEqualTo(icyContent);
assertThat(streamInfo.title).isEqualTo("test; title");
assertThat(streamInfo.url).isEqualTo("test_url");
}

@Test
public void decode_quoteInTitle() {
IcyDecoder decoder = new IcyDecoder();
Metadata metadata = decoder.decode("StreamTitle='test' title';StreamURL='test_url';");
String icyContent = "StreamTitle='test' title';StreamURL='test_url';";
Metadata metadata = decoder.decode(icyContent);

assertThat(metadata.length()).isEqualTo(1);
IcyInfo streamInfo = (IcyInfo) metadata.get(0);
assertThat(streamInfo.rawMetadata).isEqualTo(icyContent);
assertThat(streamInfo.title).isEqualTo("test' title");
assertThat(streamInfo.url).isEqualTo("test_url");
}

@Test
public void decode_lineTerminatorInTitle() {
IcyDecoder decoder = new IcyDecoder();
Metadata metadata = decoder.decode("StreamTitle='test\r\ntitle';StreamURL='test_url';");
String icyContent = "StreamTitle='test\r\ntitle';StreamURL='test_url';";
Metadata metadata = decoder.decode(icyContent);

assertThat(metadata.length()).isEqualTo(1);
IcyInfo streamInfo = (IcyInfo) metadata.get(0);
assertThat(streamInfo.rawMetadata).isEqualTo(icyContent);
assertThat(streamInfo.title).isEqualTo("test\r\ntitle");
assertThat(streamInfo.url).isEqualTo("test_url");
}

@Test
public void decode_notIcy() {
public void decode_noReconisedHeaders() {
IcyDecoder decoder = new IcyDecoder();
Metadata metadata = decoder.decode("NotIcyData");

assertThat(metadata).isNull();
assertThat(metadata.length()).isEqualTo(1);
IcyInfo streamInfo = (IcyInfo) metadata.get(0);
assertThat(streamInfo.rawMetadata).isEqualTo("NotIcyData");
assertThat(streamInfo.title).isNull();
assertThat(streamInfo.url).isNull();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,11 @@

/** Test for {@link IcyInfo}. */
@RunWith(AndroidJUnit4.class)
public final class IcyStreamInfoTest {
public final class IcyInfoTest {

@Test
public void parcelEquals() {
IcyInfo streamInfo = new IcyInfo("name", "url");
IcyInfo streamInfo = new IcyInfo("StreamName='name';StreamUrl='url'", "name", "url");
// Write to parcel.
Parcel parcel = Parcel.obtain();
streamInfo.writeToParcel(parcel, 0);
Expand Down

0 comments on commit e0c8cbe

Please sign in to comment.