summaryrefslogtreecommitdiff
path: root/core/src
diff options
context:
space:
mode:
authorDomingos Lopes <domingos86lopes+github@gmail.com>2016-03-27 02:25:15 -0400
committerDomingos Lopes <domingos86lopes+github@gmail.com>2016-04-23 21:39:55 -0400
commit94a16bb9baf2832d8c4c1208d6713c09a237e59d (patch)
tree21da968ab53c8e225d1943e77c467399d83b304e /core/src
parentc4b6f366ca2b8e731f87f0d4423c7e02185289f8 (diff)
downloadAntennaPod-94a16bb9baf2832d8c4c1208d6713c09a237e59d.zip
create RemoteMedia class, add more fields to remote mediametadata
Diffstat (limited to 'core/src')
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/cast/RemoteMedia.java257
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/util/CastUtils.java72
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/util/playback/Playable.java10
3 files changed, 333 insertions, 6 deletions
diff --git a/core/src/main/java/de/danoeh/antennapod/core/cast/RemoteMedia.java b/core/src/main/java/de/danoeh/antennapod/core/cast/RemoteMedia.java
new file mode 100644
index 000000000..dc72897e4
--- /dev/null
+++ b/core/src/main/java/de/danoeh/antennapod/core/cast/RemoteMedia.java
@@ -0,0 +1,257 @@
+package de.danoeh.antennapod.core.cast;
+
+import android.content.SharedPreferences;
+import android.net.Uri;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.text.TextUtils;
+
+import java.util.Date;
+import java.util.List;
+import java.util.concurrent.Callable;
+
+import de.danoeh.antennapod.core.feed.Chapter;
+import de.danoeh.antennapod.core.feed.MediaType;
+import de.danoeh.antennapod.core.util.ChapterUtils;
+import de.danoeh.antennapod.core.util.playback.Playable;
+
+/**
+ * Playable implementation for media on a Cast Device for which a local version of
+ * {@link de.danoeh.antennapod.core.feed.FeedMedia} could not be found.
+ */
+public class RemoteMedia implements Playable {
+
+ public static final int PLAYABLE_TYPE_REMOTE_MEDIA = 3;
+
+ private String downloadUrl;
+ private String itemIdentifier;
+ private String feedUrl;
+ private String feedTitle;
+ private String episodeTitle;
+ private String episodeLink;
+ private String feedAuthor;
+ private String imageUrl;
+ private String mime_type;
+ private Date pubDate;
+ private String notes;
+ private List<Chapter> chapters;
+ private int duration;
+ private int position;
+ private long lastPlayedTime;
+
+ public RemoteMedia(String downloadUrl, String itemId, String feedUrl, String feedTitle,
+ String episodeTitle, String episodeLink, String feedAuthor,
+ String imageUrl, String mime_type, Date pubDate) {
+ this.downloadUrl = downloadUrl;
+ this.itemIdentifier = itemId;
+ this.feedUrl = feedUrl;
+ this.feedTitle = feedTitle;
+ this.episodeTitle = episodeTitle;
+ this.episodeLink = episodeLink;
+ this.feedAuthor = feedAuthor;
+ this.imageUrl = imageUrl;
+ this.mime_type = mime_type;
+ this.pubDate = pubDate;
+ }
+
+ public void setNotes(String notes) {
+ this.notes = notes;
+ }
+
+ @Override
+ public void writeToPreferences(SharedPreferences.Editor prefEditor) {
+ //it seems pointless to do it, since the session should be kept by the remote device.
+ }
+
+ @Override
+ public void loadMetadata() throws PlayableException {
+ //Already loaded
+ }
+
+ @Override
+ public void loadChapterMarks() {
+ ChapterUtils.loadChaptersFromStreamUrl(this);
+ }
+
+ @Override
+ public String getEpisodeTitle() {
+ return episodeTitle;
+ }
+
+ @Override
+ public List<Chapter> getChapters() {
+ return chapters;
+ }
+
+ @Override
+ public String getWebsiteLink() {
+ if (episodeLink != null) {
+ return episodeLink;
+ } else {
+ return feedUrl;
+ }
+ }
+
+ @Override
+ public String getPaymentLink() {
+ return null;
+ }
+
+ @Override
+ public String getFeedTitle() {
+ return feedTitle;
+ }
+
+ @Override
+ public Object getIdentifier() {
+ return itemIdentifier + "@" + feedUrl;
+ }
+
+ @Override
+ public int getDuration() {
+ return duration;
+ }
+
+ @Override
+ public int getPosition() {
+ return position;
+ }
+
+ @Override
+ public long getLastPlayedTime() {
+ return lastPlayedTime;
+ }
+
+ @Override
+ public MediaType getMediaType() {
+ if (TextUtils.isEmpty(mime_type)) {
+ return MediaType.UNKNOWN;
+ } else {
+ if (mime_type.startsWith("audio")) {
+ return MediaType.AUDIO;
+ } else if (mime_type.startsWith("video")) {
+ return MediaType.VIDEO;
+ } else if (mime_type.equals("application/ogg")) {
+ return MediaType.AUDIO;
+ }
+ }
+ return MediaType.UNKNOWN;
+ }
+
+ @Override
+ public String getLocalMediaUrl() {
+ return null;
+ }
+
+ @Override
+ public String getStreamUrl() {
+ return downloadUrl;
+ }
+
+ @Override
+ public boolean localFileAvailable() {
+ return false;
+ }
+
+ @Override
+ public boolean streamAvailable() {
+ return true;
+ }
+
+ @Override
+ public void saveCurrentPosition(SharedPreferences pref, int newPosition, long timestamp) {
+ //we're not saving playback information for this kind of items on preferences
+ setPosition(newPosition);
+ setLastPlayedTime(timestamp);
+ }
+
+ @Override
+ public void setPosition(int newPosition) {
+ position = newPosition;
+ }
+
+ @Override
+ public void setDuration(int newDuration) {
+ duration = newDuration;
+ }
+
+ @Override
+ public void setLastPlayedTime(long lastPlayedTimestamp) {
+ lastPlayedTime = lastPlayedTimestamp;
+ }
+
+ @Override
+ public void onPlaybackStart() {
+ // no-op
+ }
+
+ @Override
+ public void onPlaybackCompleted() {
+ // no-op
+ }
+
+ @Override
+ public int getPlayableType() {
+ return PLAYABLE_TYPE_REMOTE_MEDIA;
+ }
+
+ @Override
+ public void setChapters(List<Chapter> chapters) {
+ this.chapters = chapters;
+ }
+
+ @Override
+ public Uri getImageUri() {
+ if (imageUrl != null) {
+ return Uri.parse(imageUrl);
+ }
+ return null;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public Callable<String> loadShownotes() {
+ return () -> (notes != null) ? notes : "";
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeString(downloadUrl);
+ dest.writeString(itemIdentifier);
+ dest.writeString(feedUrl);
+ dest.writeString(feedTitle);
+ dest.writeString(episodeTitle);
+ dest.writeString(episodeLink);
+ dest.writeString(feedAuthor);
+ dest.writeString(imageUrl);
+ dest.writeString(mime_type);
+ dest.writeLong(pubDate.getTime());
+ dest.writeString(notes);
+ dest.writeInt(duration);
+ dest.writeInt(position);
+ dest.writeLong(lastPlayedTime);
+ }
+
+ public static final Parcelable.Creator<RemoteMedia> CREATOR = new Parcelable.Creator<RemoteMedia>() {
+ @Override
+ public RemoteMedia createFromParcel(Parcel in) {
+ RemoteMedia result = new RemoteMedia(in.readString(), in.readString(), in.readString(),
+ in.readString(), in.readString(), in.readString(), in.readString(), in.readString(),
+ in.readString(), new Date(in.readLong()));
+ result.setNotes(in.readString());
+ result.setDuration(in.readInt());
+ result.setPosition(in.readInt());
+ result.setLastPlayedTime(in.readLong());
+ return result;
+ }
+
+ @Override
+ public RemoteMedia[] newArray(int size) {
+ return new RemoteMedia[size];
+ }
+ };
+}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/CastUtils.java b/core/src/main/java/de/danoeh/antennapod/core/util/CastUtils.java
index 9f41317da..9d665113a 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/util/CastUtils.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/util/CastUtils.java
@@ -1,6 +1,7 @@
package de.danoeh.antennapod.core.util;
import android.net.Uri;
+import android.text.TextUtils;
import android.util.Log;
import com.google.android.gms.cast.CastDevice;
@@ -11,6 +12,7 @@ import com.google.android.gms.common.images.WebImage;
import java.util.Calendar;
import de.danoeh.antennapod.core.cast.CastManager;
+import de.danoeh.antennapod.core.feed.Feed;
import de.danoeh.antennapod.core.feed.FeedImage;
import de.danoeh.antennapod.core.feed.FeedItem;
import de.danoeh.antennapod.core.feed.FeedMedia;
@@ -23,7 +25,27 @@ import de.danoeh.antennapod.core.util.playback.Playable;
public class CastUtils {
private static final String TAG = "CastUtils";
- public static final String KEY_MEDIA_ID = "CastUtils.Id";
+ public static final String KEY_MEDIA_ID = "AntennaPod.MediaId";
+
+ public static final String KEY_EPISODE_IDENTIFIER = "AntennaPod.EpisodeId";
+ public static final String KEY_EPISODE_LINK = "AntennaPod.EpisodeLink";
+ public static final String KEY_FEED_URL = "AntennaPod.FeedUrl";
+ public static final String KEY_FEED_WEBSITE = "AntennaPod.FeedWebsite";
+ public static final String KEY_EPISODE_NOTES = "AntennaPod.EpisodeNotes";
+ public static final int EPISODE_NOTES_MAX_LENGTH = Integer.MAX_VALUE;
+
+ /**
+ * The field <code>AntennaPod.FormatVersion</code> specifies which version of MediaMetaData
+ * fields we're using. Future implementations should try to be backwards compatible with earlier
+ * versions, and earlier versions should be forward compatible until the version indicated by
+ * <code>MAX_VERSION_FORWARD_COMPATIBILITY</code>. If an update makes the format unreadable for
+ * an earlier version, then its version number should be greater than the
+ * <code>MAX_VERSION_FORWARD_COMPATIBILITY</code> value set on the earlier one, so that it
+ * doesn't try to parse the object.
+ */
+ public static final String KEY_FORMAT_VERSION = "AntennaPod.FormatVersion";
+ public static final int FORMAT_VERSION_VALUE = 1;
+ public static final int MAX_VERSION_FORWARD_COMPATIBILITY = 9999;
public static boolean isCastable(Playable media){
if (media == null || media instanceof ExternalMedia) {
@@ -75,17 +97,53 @@ public class CastUtils {
metadata.putString(MediaMetadata.KEY_SUBTITLE, subtitle);
}
FeedImage image = feedItem.getImage();
- if (image != null && image.getDownload_url() != null &&
- !image.getDownload_url().isEmpty()) {
+ if (image != null && !TextUtils.isEmpty(image.getDownload_url())) {
metadata.addImage(new WebImage(Uri.parse(image.getDownload_url())));
}
Calendar calendar = Calendar.getInstance();
calendar.setTime(media.getItem().getPubDate());
metadata.putDate(MediaMetadata.KEY_RELEASE_DATE, calendar);
-
+ Feed feed = feedItem.getFeed();
+ if (feed != null) {
+ if (!TextUtils.isEmpty(feed.getAuthor())) {
+ metadata.putString(MediaMetadata.KEY_ARTIST, feed.getAuthor());
+ }
+ if (!TextUtils.isEmpty(feed.getDownload_url())) {
+ metadata.putString(KEY_FEED_URL, feed.getDownload_url());
+ }
+ if (!TextUtils.isEmpty(feed.getLink())) {
+ metadata.putString(KEY_FEED_WEBSITE, feed.getLink());
+ }
+ }
+ if (!TextUtils.isEmpty(feedItem.getItemIdentifier())) {
+ metadata.putString(KEY_EPISODE_IDENTIFIER, feedItem.getItemIdentifier());
+ } else {
+ metadata.putString(KEY_EPISODE_IDENTIFIER, media.getStreamUrl());
+ }
+ if (!TextUtils.isEmpty(feedItem.getLink())) {
+ metadata.putString(KEY_EPISODE_LINK, feedItem.getLink());
+ }
+ }
+ String notes = null;
+ try {
+ notes = media.loadShownotes().call();
+ } catch (Exception e) {
+ Log.e(TAG, "Unable to load FeedMedia notes", e);
+ }
+ if (notes != null) {
+ if (notes.length() > EPISODE_NOTES_MAX_LENGTH) {
+ notes = notes.substring(0, EPISODE_NOTES_MAX_LENGTH);
+ }
+ metadata.putString(KEY_EPISODE_NOTES, notes);
}
- //metadata.putString(MediaMetadata.KEY_ARTIST, null);
- metadata.putString(KEY_MEDIA_ID, media.getIdentifier().toString());
+ // This field only identifies the id on the device that has the original version.
+ // Idea is to perhaps, on a first approach, check if the version on the local DB with the
+ // same id matches the remote object, and if not then search for episode and feed identifiers.
+ // This at least should make media recognition for a single device much quicker.
+ metadata.putInt(KEY_MEDIA_ID, ((Long) media.getIdentifier()).intValue());
+ // A way to identify different casting media formats in case we change it in the future and
+ // senders with different versions share a casting device.
+ metadata.putInt(KEY_FORMAT_VERSION, FORMAT_VERSION_VALUE);
return new MediaInfo.Builder(media.getStreamUrl())
.setContentType(media.getMime_type())
@@ -94,5 +152,7 @@ public class CastUtils {
.build();
}
+
+
//TODO Queue handling perhaps
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/playback/Playable.java b/core/src/main/java/de/danoeh/antennapod/core/util/playback/Playable.java
index 6459d86ed..201efbc81 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/util/playback/Playable.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/util/playback/Playable.java
@@ -8,6 +8,7 @@ import android.util.Log;
import java.util.List;
import de.danoeh.antennapod.core.asynctask.ImageResource;
+import de.danoeh.antennapod.core.cast.RemoteMedia;
import de.danoeh.antennapod.core.feed.Chapter;
import de.danoeh.antennapod.core.feed.FeedMedia;
import de.danoeh.antennapod.core.feed.MediaType;
@@ -183,6 +184,9 @@ public interface Playable extends Parcelable,
case ExternalMedia.PLAYABLE_TYPE_EXTERNAL_MEDIA:
result = createExternalMediaInstance(pref);
break;
+ case RemoteMedia.PLAYABLE_TYPE_REMOTE_MEDIA:
+ result = createRemoteMediaInstance(pref);
+ break;
}
if (result == null) {
Log.e(TAG, "Could not restore Playable object from preferences");
@@ -211,6 +215,12 @@ public interface Playable extends Parcelable,
}
return result;
}
+
+ private static Playable createRemoteMediaInstance(SharedPreferences pref) {
+ //TODO there's probably no point in restoring RemoteMedia from preferences, because we
+ //only care about it while it's playing on the cast device.
+ return null;
+ }
}
class PlayableException extends Exception {