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 com.google.android.gms.cast.MediaInfo;
import com.google.android.gms.cast.MediaMetadata;
import com.google.android.gms.common.images.WebImage;
import java.util.Calendar;
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.Feed;
import de.danoeh.antennapod.core.feed.FeedItem;
import de.danoeh.antennapod.core.feed.FeedMedia;
import de.danoeh.antennapod.core.feed.MediaType;
import de.danoeh.antennapod.core.storage.DBReader;
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} hasn't been found.
*/
public class RemoteMedia implements Playable {
public static final String TAG = "RemoteMedia";
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 feedLink;
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 feedLink, 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.feedLink = feedLink;
this.mime_type = mime_type;
this.pubDate = pubDate;
}
public void setNotes(String notes) {
this.notes = notes;
}
public MediaInfo extractMediaInfo() {
MediaMetadata metadata = new MediaMetadata(MediaMetadata.MEDIA_TYPE_GENERIC);
metadata.putString(MediaMetadata.KEY_TITLE, episodeTitle);
metadata.putString(MediaMetadata.KEY_SUBTITLE, feedTitle);
if (!TextUtils.isEmpty(imageUrl)) {
metadata.addImage(new WebImage(Uri.parse(imageUrl)));
}
Calendar calendar = Calendar.getInstance();
calendar.setTime(pubDate);
metadata.putDate(MediaMetadata.KEY_RELEASE_DATE, calendar);
if (!TextUtils.isEmpty(feedAuthor)) {
metadata.putString(MediaMetadata.KEY_ARTIST, feedAuthor);
}
if (!TextUtils.isEmpty(feedUrl)) {
metadata.putString(CastUtils.KEY_FEED_URL, feedUrl);
}
if (!TextUtils.isEmpty(feedLink)) {
metadata.putString(CastUtils.KEY_FEED_WEBSITE, feedLink);
}
if (!TextUtils.isEmpty(itemIdentifier)) {
metadata.putString(CastUtils.KEY_EPISODE_IDENTIFIER, itemIdentifier);
} else {
metadata.putString(CastUtils.KEY_EPISODE_IDENTIFIER, downloadUrl);
}
if (!TextUtils.isEmpty(episodeLink)) {
metadata.putString(CastUtils.KEY_EPISODE_LINK, episodeLink);
}
String notes = this.notes;
if (notes != null) {
if (notes.length() > CastUtils.EPISODE_NOTES_MAX_LENGTH) {
notes = notes.substring(0, CastUtils.EPISODE_NOTES_MAX_LENGTH);
}
metadata.putString(CastUtils.KEY_EPISODE_NOTES, notes);
}
// Default id value
metadata.putInt(CastUtils.KEY_MEDIA_ID, 0);
metadata.putInt(CastUtils.KEY_FORMAT_VERSION, CastUtils.FORMAT_VERSION_VALUE);
MediaInfo.Builder builder = new MediaInfo.Builder(downloadUrl)
.setContentType(mime_type)
.setStreamType(MediaInfo.STREAM_TYPE_BUFFERED)
.setMetadata(metadata);
if (duration > 0) {
builder.setStreamDuration(duration);
}
return builder.build();
}
public String getEpisodeIdentifier() {
return itemIdentifier;
}
public String getFeedUrl() {
return feedUrl;
}
public FeedMedia lookForFeedMedia() {
FeedItem feedItem = DBReader.getFeedItem(feedUrl, itemIdentifier);
if (feedItem == null) {
return null;
}
return feedItem.getMedia();
}
@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() {
return MediaType.fromMimeType(mime_type);
}
@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(feedLink);
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(), 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];
}
};
@Override
public boolean equals(Object other) {
if (other instanceof RemoteMedia) {
RemoteMedia rm = (RemoteMedia) other;
return TextUtils.equals(downloadUrl, rm.downloadUrl) &&
TextUtils.equals(feedUrl, rm.feedUrl) &&
TextUtils.equals(itemIdentifier, rm.itemIdentifier);
}
if (other instanceof FeedMedia) {
FeedMedia fm = (FeedMedia) other;
if (!TextUtils.equals(downloadUrl, fm.getStreamUrl())) {
return false;
}
FeedItem fi = fm.getItem();
if (fi == null || !TextUtils.equals(itemIdentifier, fi.getItemIdentifier())) {
return false;
}
Feed feed = fi.getFeed();
return feed != null && TextUtils.equals(feedUrl, feed.getDownload_url());
}
return false;
}
}