diff options
author | ByteHamster <info@bytehamster.com> | 2020-02-22 01:09:59 +0100 |
---|---|---|
committer | ByteHamster <info@bytehamster.com> | 2020-03-16 00:19:20 +0100 |
commit | f7411d2d98033ab8bce3be9c4428b18fe5201e74 (patch) | |
tree | 6f96d51eeaa7514639875a5f5ee649684e8a6344 /core/src/play | |
parent | 03d1f41e9bd88e1920be306ef8bcd10642ce5527 (diff) | |
download | AntennaPod-f7411d2d98033ab8bce3be9c4428b18fe5201e74.zip |
Allow to stream episodes from unsubscribed podcast
Diffstat (limited to 'core/src/play')
5 files changed, 65 insertions, 357 deletions
diff --git a/core/src/play/java/de/danoeh/antennapod/core/cast/CastUtils.java b/core/src/play/java/de/danoeh/antennapod/core/cast/CastUtils.java index 88da6a0ec..484904a9a 100644 --- a/core/src/play/java/de/danoeh/antennapod/core/cast/CastUtils.java +++ b/core/src/play/java/de/danoeh/antennapod/core/cast/CastUtils.java @@ -9,6 +9,7 @@ import com.google.android.gms.cast.MediaInfo; import com.google.android.gms.cast.MediaMetadata; import com.google.android.gms.common.images.WebImage; +import de.danoeh.antennapod.core.util.playback.RemoteMedia; import java.util.Calendar; import java.util.List; diff --git a/core/src/play/java/de/danoeh/antennapod/core/cast/MediaInfoCreator.java b/core/src/play/java/de/danoeh/antennapod/core/cast/MediaInfoCreator.java new file mode 100644 index 000000000..91de5418d --- /dev/null +++ b/core/src/play/java/de/danoeh/antennapod/core/cast/MediaInfoCreator.java @@ -0,0 +1,60 @@ +package de.danoeh.antennapod.core.cast; + +import android.net.Uri; +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 de.danoeh.antennapod.core.util.playback.RemoteMedia; +import java.util.Calendar; + +public class MediaInfoCreator { + public static MediaInfo from(RemoteMedia media) { + MediaMetadata metadata = new MediaMetadata(MediaMetadata.MEDIA_TYPE_GENERIC); + + metadata.putString(MediaMetadata.KEY_TITLE, media.getEpisodeTitle()); + metadata.putString(MediaMetadata.KEY_SUBTITLE, media.getFeedTitle()); + if (!TextUtils.isEmpty(media.getImageLocation())) { + metadata.addImage(new WebImage(Uri.parse(media.getImageLocation()))); + } + Calendar calendar = Calendar.getInstance(); + calendar.setTime(media.getPubDate()); + metadata.putDate(MediaMetadata.KEY_RELEASE_DATE, calendar); + if (!TextUtils.isEmpty(media.getFeedAuthor())) { + metadata.putString(MediaMetadata.KEY_ARTIST, media.getFeedAuthor()); + } + if (!TextUtils.isEmpty(media.getFeedUrl())) { + metadata.putString(CastUtils.KEY_FEED_URL, media.getFeedUrl()); + } + if (!TextUtils.isEmpty(media.getFeedLink())) { + metadata.putString(CastUtils.KEY_FEED_WEBSITE, media.getFeedLink()); + } + if (!TextUtils.isEmpty(media.getEpisodeIdentifier())) { + metadata.putString(CastUtils.KEY_EPISODE_IDENTIFIER, media.getEpisodeIdentifier()); + } else { + metadata.putString(CastUtils.KEY_EPISODE_IDENTIFIER, media.getDownloadUrl()); + } + if (!TextUtils.isEmpty(media.getEpisodeLink())) { + metadata.putString(CastUtils.KEY_EPISODE_LINK, media.getEpisodeLink()); + } + String notes = media.getNotes(); + 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(media.getDownloadUrl()) + .setContentType(media.getMimeType()) + .setStreamType(MediaInfo.STREAM_TYPE_BUFFERED) + .setMetadata(metadata); + if (media.getDuration() > 0) { + builder.setStreamDuration(media.getDuration()); + } + return builder.build(); + } +} diff --git a/core/src/play/java/de/danoeh/antennapod/core/cast/RemoteMedia.java b/core/src/play/java/de/danoeh/antennapod/core/cast/RemoteMedia.java deleted file mode 100644 index 0614e5952..000000000 --- a/core/src/play/java/de/danoeh/antennapod/core/cast/RemoteMedia.java +++ /dev/null @@ -1,354 +0,0 @@ -package de.danoeh.antennapod.core.cast; - -import android.content.Context; -import android.content.SharedPreferences; -import android.net.Uri; -import android.os.Parcel; -import android.os.Parcelable; -import androidx.annotation.Nullable; -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 org.apache.commons.lang3.builder.HashCodeBuilder; - -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.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; - } - - @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 onPlaybackPause(Context context) { - // no-op - } - - @Override - public void onPlaybackCompleted(Context context) { - // no-op - } - - @Override - public int getPlayableType() { - return PLAYABLE_TYPE_REMOTE_MEDIA; - } - - @Override - public void setChapters(List<Chapter> chapters) { - this.chapters = chapters; - } - - @Override - @Nullable - public String getImageLocation() { - return imageUrl; - } - - @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; - } - - @Override - public int hashCode() { - return new HashCodeBuilder() - .append(downloadUrl) - .append(feedUrl) - .append(itemIdentifier) - .toHashCode(); - } -} diff --git a/core/src/play/java/de/danoeh/antennapod/core/feed/FeedMediaFlavorHelper.java b/core/src/play/java/de/danoeh/antennapod/core/feed/FeedMediaFlavorHelper.java index fe0f771d6..2502f17c0 100644 --- a/core/src/play/java/de/danoeh/antennapod/core/feed/FeedMediaFlavorHelper.java +++ b/core/src/play/java/de/danoeh/antennapod/core/feed/FeedMediaFlavorHelper.java @@ -1,6 +1,6 @@ package de.danoeh.antennapod.core.feed; -import de.danoeh.antennapod.core.cast.RemoteMedia; +import de.danoeh.antennapod.core.util.playback.RemoteMedia; /** * Implements methods for FeedMedia that are flavor dependent. diff --git a/core/src/play/java/de/danoeh/antennapod/core/service/playback/RemotePSMP.java b/core/src/play/java/de/danoeh/antennapod/core/service/playback/RemotePSMP.java index 7c84437e1..2a75f30a2 100644 --- a/core/src/play/java/de/danoeh/antennapod/core/service/playback/RemotePSMP.java +++ b/core/src/play/java/de/danoeh/antennapod/core/service/playback/RemotePSMP.java @@ -15,6 +15,7 @@ import com.google.android.libraries.cast.companionlibrary.cast.exceptions.CastEx import com.google.android.libraries.cast.companionlibrary.cast.exceptions.NoConnectionException; import com.google.android.libraries.cast.companionlibrary.cast.exceptions.TransientNetworkDisconnectionException; +import de.danoeh.antennapod.core.cast.MediaInfoCreator; import java.util.concurrent.Future; import java.util.concurrent.FutureTask; import java.util.concurrent.atomic.AtomicBoolean; @@ -24,7 +25,7 @@ import de.danoeh.antennapod.core.cast.CastConsumer; import de.danoeh.antennapod.core.cast.CastManager; import de.danoeh.antennapod.core.cast.CastUtils; import de.danoeh.antennapod.core.cast.DefaultCastConsumer; -import de.danoeh.antennapod.core.cast.RemoteMedia; +import de.danoeh.antennapod.core.util.playback.RemoteMedia; import de.danoeh.antennapod.core.feed.FeedMedia; import de.danoeh.antennapod.core.feed.MediaType; import de.danoeh.antennapod.core.preferences.UserPreferences; @@ -165,7 +166,7 @@ public class RemotePSMP extends PlaybackServiceMediaPlayer { return CastUtils.convertFromFeedMedia((FeedMedia) playable); } if (playable instanceof RemoteMedia) { - return ((RemoteMedia) playable).extractMediaInfo(); + return MediaInfoCreator.from((RemoteMedia) playable); } return null; } |