summaryrefslogtreecommitdiffstats
path: root/mobile/android/exoplayer2/src/main/java/org/mozilla/thirdparty/com/google/android/exoplayer2/metadata/icy/IcyHeaders.java
diff options
context:
space:
mode:
Diffstat (limited to 'mobile/android/exoplayer2/src/main/java/org/mozilla/thirdparty/com/google/android/exoplayer2/metadata/icy/IcyHeaders.java')
-rw-r--r--mobile/android/exoplayer2/src/main/java/org/mozilla/thirdparty/com/google/android/exoplayer2/metadata/icy/IcyHeaders.java243
1 files changed, 243 insertions, 0 deletions
diff --git a/mobile/android/exoplayer2/src/main/java/org/mozilla/thirdparty/com/google/android/exoplayer2/metadata/icy/IcyHeaders.java b/mobile/android/exoplayer2/src/main/java/org/mozilla/thirdparty/com/google/android/exoplayer2/metadata/icy/IcyHeaders.java
new file mode 100644
index 0000000000..638e7594eb
--- /dev/null
+++ b/mobile/android/exoplayer2/src/main/java/org/mozilla/thirdparty/com/google/android/exoplayer2/metadata/icy/IcyHeaders.java
@@ -0,0 +1,243 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.mozilla.thirdparty.com.google.android.exoplayer2.metadata.icy;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+import androidx.annotation.Nullable;
+import org.mozilla.thirdparty.com.google.android.exoplayer2.C;
+import org.mozilla.thirdparty.com.google.android.exoplayer2.Format;
+import org.mozilla.thirdparty.com.google.android.exoplayer2.metadata.Metadata;
+import org.mozilla.thirdparty.com.google.android.exoplayer2.util.Assertions;
+import org.mozilla.thirdparty.com.google.android.exoplayer2.util.Log;
+import org.mozilla.thirdparty.com.google.android.exoplayer2.util.Util;
+import java.util.List;
+import java.util.Map;
+
+/** ICY headers. */
+public final class IcyHeaders implements Metadata.Entry {
+
+ public static final String REQUEST_HEADER_ENABLE_METADATA_NAME = "Icy-MetaData";
+ public static final String REQUEST_HEADER_ENABLE_METADATA_VALUE = "1";
+
+ private static final String TAG = "IcyHeaders";
+
+ private static final String RESPONSE_HEADER_BITRATE = "icy-br";
+ private static final String RESPONSE_HEADER_GENRE = "icy-genre";
+ private static final String RESPONSE_HEADER_NAME = "icy-name";
+ private static final String RESPONSE_HEADER_URL = "icy-url";
+ private static final String RESPONSE_HEADER_PUB = "icy-pub";
+ private static final String RESPONSE_HEADER_METADATA_INTERVAL = "icy-metaint";
+
+ /**
+ * Parses {@link IcyHeaders} from response headers.
+ *
+ * @param responseHeaders The response headers.
+ * @return The parsed {@link IcyHeaders}, or {@code null} if no ICY headers were present.
+ */
+ @Nullable
+ public static IcyHeaders parse(Map<String, List<String>> responseHeaders) {
+ boolean icyHeadersPresent = false;
+ int bitrate = Format.NO_VALUE;
+ String genre = null;
+ String name = null;
+ String url = null;
+ boolean isPublic = false;
+ int metadataInterval = C.LENGTH_UNSET;
+
+ List<String> headers = responseHeaders.get(RESPONSE_HEADER_BITRATE);
+ if (headers != null) {
+ String bitrateHeader = headers.get(0);
+ try {
+ bitrate = Integer.parseInt(bitrateHeader) * 1000;
+ if (bitrate > 0) {
+ icyHeadersPresent = true;
+ } else {
+ Log.w(TAG, "Invalid bitrate: " + bitrateHeader);
+ bitrate = Format.NO_VALUE;
+ }
+ } catch (NumberFormatException e) {
+ Log.w(TAG, "Invalid bitrate header: " + bitrateHeader);
+ }
+ }
+ headers = responseHeaders.get(RESPONSE_HEADER_GENRE);
+ if (headers != null) {
+ genre = headers.get(0);
+ icyHeadersPresent = true;
+ }
+ headers = responseHeaders.get(RESPONSE_HEADER_NAME);
+ if (headers != null) {
+ name = headers.get(0);
+ icyHeadersPresent = true;
+ }
+ headers = responseHeaders.get(RESPONSE_HEADER_URL);
+ if (headers != null) {
+ url = headers.get(0);
+ icyHeadersPresent = true;
+ }
+ headers = responseHeaders.get(RESPONSE_HEADER_PUB);
+ if (headers != null) {
+ isPublic = headers.get(0).equals("1");
+ icyHeadersPresent = true;
+ }
+ headers = responseHeaders.get(RESPONSE_HEADER_METADATA_INTERVAL);
+ if (headers != null) {
+ String metadataIntervalHeader = headers.get(0);
+ try {
+ metadataInterval = Integer.parseInt(metadataIntervalHeader);
+ if (metadataInterval > 0) {
+ icyHeadersPresent = true;
+ } else {
+ Log.w(TAG, "Invalid metadata interval: " + metadataIntervalHeader);
+ metadataInterval = C.LENGTH_UNSET;
+ }
+ } catch (NumberFormatException e) {
+ Log.w(TAG, "Invalid metadata interval: " + metadataIntervalHeader);
+ }
+ }
+ return icyHeadersPresent
+ ? new IcyHeaders(bitrate, genre, name, url, isPublic, metadataInterval)
+ : null;
+ }
+
+ /**
+ * Bitrate in bits per second ({@code (icy-br * 1000)}), or {@link Format#NO_VALUE} if the header
+ * was not present.
+ */
+ public final int bitrate;
+ /** The genre ({@code icy-genre}). */
+ @Nullable public final String genre;
+ /** The stream name ({@code icy-name}). */
+ @Nullable public final String name;
+ /** The URL of the radio station ({@code icy-url}). */
+ @Nullable public final String url;
+ /**
+ * Whether the radio station is listed ({@code icy-pub}), or {@code false} if the header was not
+ * present.
+ */
+ public final boolean isPublic;
+
+ /**
+ * The interval in bytes between metadata chunks ({@code icy-metaint}), or {@link C#LENGTH_UNSET}
+ * if the header was not present.
+ */
+ public final int metadataInterval;
+
+ /**
+ * @param bitrate See {@link #bitrate}.
+ * @param genre See {@link #genre}.
+ * @param name See {@link #name See}.
+ * @param url See {@link #url}.
+ * @param isPublic See {@link #isPublic}.
+ * @param metadataInterval See {@link #metadataInterval}.
+ */
+ public IcyHeaders(
+ int bitrate,
+ @Nullable String genre,
+ @Nullable String name,
+ @Nullable String url,
+ boolean isPublic,
+ int metadataInterval) {
+ Assertions.checkArgument(metadataInterval == C.LENGTH_UNSET || metadataInterval > 0);
+ this.bitrate = bitrate;
+ this.genre = genre;
+ this.name = name;
+ this.url = url;
+ this.isPublic = isPublic;
+ this.metadataInterval = metadataInterval;
+ }
+
+ /* package */ IcyHeaders(Parcel in) {
+ bitrate = in.readInt();
+ genre = in.readString();
+ name = in.readString();
+ url = in.readString();
+ isPublic = Util.readBoolean(in);
+ metadataInterval = in.readInt();
+ }
+
+ @Override
+ public boolean equals(@Nullable Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null || getClass() != obj.getClass()) {
+ return false;
+ }
+ IcyHeaders other = (IcyHeaders) obj;
+ return bitrate == other.bitrate
+ && Util.areEqual(genre, other.genre)
+ && Util.areEqual(name, other.name)
+ && Util.areEqual(url, other.url)
+ && isPublic == other.isPublic
+ && metadataInterval == other.metadataInterval;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = 17;
+ result = 31 * result + bitrate;
+ result = 31 * result + (genre != null ? genre.hashCode() : 0);
+ result = 31 * result + (name != null ? name.hashCode() : 0);
+ result = 31 * result + (url != null ? url.hashCode() : 0);
+ result = 31 * result + (isPublic ? 1 : 0);
+ result = 31 * result + metadataInterval;
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return "IcyHeaders: name=\""
+ + name
+ + "\", genre=\""
+ + genre
+ + "\", bitrate="
+ + bitrate
+ + ", metadataInterval="
+ + metadataInterval;
+ }
+
+ // Parcelable implementation.
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeInt(bitrate);
+ dest.writeString(genre);
+ dest.writeString(name);
+ dest.writeString(url);
+ Util.writeBoolean(dest, isPublic);
+ dest.writeInt(metadataInterval);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ public static final Parcelable.Creator<IcyHeaders> CREATOR =
+ new Parcelable.Creator<IcyHeaders>() {
+
+ @Override
+ public IcyHeaders createFromParcel(Parcel in) {
+ return new IcyHeaders(in);
+ }
+
+ @Override
+ public IcyHeaders[] newArray(int size) {
+ return new IcyHeaders[size];
+ }
+ };
+}