Allow to stream episodes from unsubscribed podcast
This commit is contained in:
parent
03d1f41e9b
commit
f7411d2d98
@ -1,23 +1,29 @@
|
|||||||
package de.danoeh.antennapod.adapter;
|
package de.danoeh.antennapod.adapter;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.os.Build;
|
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.ArrayAdapter;
|
import android.widget.ArrayAdapter;
|
||||||
|
import android.widget.Button;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
import de.danoeh.antennapod.R;
|
||||||
|
import de.danoeh.antennapod.core.util.NetworkUtils;
|
||||||
|
import de.danoeh.antennapod.core.util.playback.RemoteMedia;
|
||||||
|
import de.danoeh.antennapod.core.feed.FeedItem;
|
||||||
|
import de.danoeh.antennapod.core.service.playback.PlaybackService;
|
||||||
|
import de.danoeh.antennapod.core.util.DateUtils;
|
||||||
|
import de.danoeh.antennapod.core.util.playback.Playable;
|
||||||
|
import de.danoeh.antennapod.core.util.playback.PlaybackServiceStarter;
|
||||||
|
import de.danoeh.antennapod.dialog.StreamingConfirmationDialog;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import de.danoeh.antennapod.R;
|
|
||||||
import de.danoeh.antennapod.core.feed.FeedItem;
|
|
||||||
import de.danoeh.antennapod.core.util.DateUtils;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* List adapter for showing a list of FeedItems with their title and description.
|
* List adapter for showing a list of FeedItems with their title and description.
|
||||||
*/
|
*/
|
||||||
public class FeedItemlistDescriptionAdapter extends ArrayAdapter<FeedItem> {
|
public class FeedItemlistDescriptionAdapter extends ArrayAdapter<FeedItem> {
|
||||||
|
private static final int MAX_LINES_COLLAPSED = 3;
|
||||||
|
|
||||||
public FeedItemlistDescriptionAdapter(Context context, int resource, List<FeedItem> objects) {
|
public FeedItemlistDescriptionAdapter(Context context, int resource, List<FeedItem> objects) {
|
||||||
super(context, resource, objects);
|
super(context, resource, objects);
|
||||||
@ -32,12 +38,12 @@ public class FeedItemlistDescriptionAdapter extends ArrayAdapter<FeedItem> {
|
|||||||
// Inflate layout
|
// Inflate layout
|
||||||
if (convertView == null) {
|
if (convertView == null) {
|
||||||
holder = new Holder();
|
holder = new Holder();
|
||||||
LayoutInflater inflater = (LayoutInflater) getContext()
|
LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||||
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
|
||||||
convertView = inflater.inflate(R.layout.itemdescription_listitem, parent, false);
|
convertView = inflater.inflate(R.layout.itemdescription_listitem, parent, false);
|
||||||
holder.title = convertView.findViewById(R.id.txtvTitle);
|
holder.title = convertView.findViewById(R.id.txtvTitle);
|
||||||
holder.pubDate = convertView.findViewById(R.id.txtvPubDate);
|
holder.pubDate = convertView.findViewById(R.id.txtvPubDate);
|
||||||
holder.description = convertView.findViewById(R.id.txtvDescription);
|
holder.description = convertView.findViewById(R.id.txtvDescription);
|
||||||
|
holder.preview = convertView.findViewById(R.id.butPreview);
|
||||||
|
|
||||||
convertView.setTag(holder);
|
convertView.setTag(holder);
|
||||||
} else {
|
} else {
|
||||||
@ -52,18 +58,34 @@ public class FeedItemlistDescriptionAdapter extends ArrayAdapter<FeedItem> {
|
|||||||
.replaceAll("\\s+", " ")
|
.replaceAll("\\s+", " ")
|
||||||
.trim();
|
.trim();
|
||||||
holder.description.setText(description);
|
holder.description.setText(description);
|
||||||
|
|
||||||
final int MAX_LINES_COLLAPSED = 3;
|
|
||||||
holder.description.setMaxLines(MAX_LINES_COLLAPSED);
|
holder.description.setMaxLines(MAX_LINES_COLLAPSED);
|
||||||
holder.description.setOnClickListener(v -> {
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN
|
|
||||||
&& holder.description.getMaxLines() > MAX_LINES_COLLAPSED) {
|
|
||||||
holder.description.setMaxLines(MAX_LINES_COLLAPSED);
|
|
||||||
} else {
|
|
||||||
holder.description.setMaxLines(2000);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
holder.description.setTag(Boolean.FALSE); // not expanded
|
||||||
|
holder.preview.setVisibility(View.GONE);
|
||||||
|
holder.preview.setOnClickListener(v -> {
|
||||||
|
Playable playable = new RemoteMedia(item);
|
||||||
|
if (!NetworkUtils.isStreamingAllowed()) {
|
||||||
|
new StreamingConfirmationDialog(getContext(), playable).show();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
new PlaybackServiceStarter(getContext(), playable)
|
||||||
|
.shouldStream(true)
|
||||||
|
.startWhenPrepared(true)
|
||||||
|
.callEvenIfRunning(true)
|
||||||
|
.start();
|
||||||
|
getContext().startActivity(PlaybackService.getPlayerActivityIntent(getContext(), playable));
|
||||||
|
});
|
||||||
|
convertView.setOnClickListener(v -> {
|
||||||
|
if (holder.description.getTag() == Boolean.TRUE) {
|
||||||
|
holder.description.setMaxLines(MAX_LINES_COLLAPSED);
|
||||||
|
holder.preview.setVisibility(View.GONE);
|
||||||
|
holder.description.setTag(Boolean.FALSE);
|
||||||
|
} else {
|
||||||
|
holder.description.setMaxLines(2000);
|
||||||
|
holder.preview.setVisibility(View.VISIBLE);
|
||||||
|
holder.description.setTag(Boolean.TRUE);
|
||||||
|
}
|
||||||
|
});
|
||||||
return convertView;
|
return convertView;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -71,5 +93,6 @@ public class FeedItemlistDescriptionAdapter extends ArrayAdapter<FeedItem> {
|
|||||||
TextView title;
|
TextView title;
|
||||||
TextView pubDate;
|
TextView pubDate;
|
||||||
TextView description;
|
TextView description;
|
||||||
|
Button preview;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,17 +5,17 @@ import android.view.View;
|
|||||||
import android.widget.CheckBox;
|
import android.widget.CheckBox;
|
||||||
import androidx.appcompat.app.AlertDialog;
|
import androidx.appcompat.app.AlertDialog;
|
||||||
import de.danoeh.antennapod.R;
|
import de.danoeh.antennapod.R;
|
||||||
import de.danoeh.antennapod.core.feed.FeedMedia;
|
|
||||||
import de.danoeh.antennapod.core.preferences.UserPreferences;
|
import de.danoeh.antennapod.core.preferences.UserPreferences;
|
||||||
|
import de.danoeh.antennapod.core.util.playback.Playable;
|
||||||
import de.danoeh.antennapod.core.util.playback.PlaybackServiceStarter;
|
import de.danoeh.antennapod.core.util.playback.PlaybackServiceStarter;
|
||||||
|
|
||||||
public class StreamingConfirmationDialog {
|
public class StreamingConfirmationDialog {
|
||||||
private final Context context;
|
private final Context context;
|
||||||
private final FeedMedia media;
|
private final Playable playable;
|
||||||
|
|
||||||
public StreamingConfirmationDialog(Context context, FeedMedia media) {
|
public StreamingConfirmationDialog(Context context, Playable playable) {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
this.media = media;
|
this.playable = playable;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void show() {
|
public void show() {
|
||||||
@ -30,7 +30,7 @@ public class StreamingConfirmationDialog {
|
|||||||
if (checkDoNotShowAgain.isChecked()) {
|
if (checkDoNotShowAgain.isChecked()) {
|
||||||
UserPreferences.setAllowMobileStreaming(true);
|
UserPreferences.setAllowMobileStreaming(true);
|
||||||
}
|
}
|
||||||
new PlaybackServiceStarter(context, media)
|
new PlaybackServiceStarter(context, playable)
|
||||||
.callEvenIfRunning(true)
|
.callEvenIfRunning(true)
|
||||||
.startWhenPrepared(true)
|
.startWhenPrepared(true)
|
||||||
.shouldStream(true)
|
.shouldStream(true)
|
||||||
|
@ -56,4 +56,14 @@
|
|||||||
tools:text="Feed item description"
|
tools:text="Feed item description"
|
||||||
tools:background="@android:color/holo_green_dark" />
|
tools:background="@android:color/holo_green_dark" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/butPreview"
|
||||||
|
android:layout_below="@id/txtvDescription"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_alignParentStart="true"
|
||||||
|
android:layout_alignParentLeft="true"
|
||||||
|
style="?android:attr/buttonBarButtonStyle"
|
||||||
|
android:text="@string/preview_episode"/>
|
||||||
|
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
@ -1,35 +1,26 @@
|
|||||||
package de.danoeh.antennapod.core.cast;
|
package de.danoeh.antennapod.core.util.playback;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.net.Uri;
|
|
||||||
import android.os.Parcel;
|
import android.os.Parcel;
|
||||||
import android.os.Parcelable;
|
import android.os.Parcelable;
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
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.Chapter;
|
||||||
import de.danoeh.antennapod.core.feed.Feed;
|
import de.danoeh.antennapod.core.feed.Feed;
|
||||||
import de.danoeh.antennapod.core.feed.FeedItem;
|
import de.danoeh.antennapod.core.feed.FeedItem;
|
||||||
import de.danoeh.antennapod.core.feed.FeedMedia;
|
import de.danoeh.antennapod.core.feed.FeedMedia;
|
||||||
import de.danoeh.antennapod.core.feed.MediaType;
|
import de.danoeh.antennapod.core.feed.MediaType;
|
||||||
import de.danoeh.antennapod.core.util.ChapterUtils;
|
import de.danoeh.antennapod.core.util.ChapterUtils;
|
||||||
import de.danoeh.antennapod.core.util.playback.Playable;
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.Callable;
|
||||||
|
import org.apache.commons.lang3.builder.HashCodeBuilder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Playable implementation for media on a Cast Device for which a local version of
|
* Playable implementation for media for which a local version of
|
||||||
* {@link de.danoeh.antennapod.core.feed.FeedMedia} hasn't been found.
|
* {@link de.danoeh.antennapod.core.feed.FeedMedia} hasn't been found.
|
||||||
|
* Used for Casting and for previewing unsubscribed feeds.
|
||||||
*/
|
*/
|
||||||
public class RemoteMedia implements Playable {
|
public class RemoteMedia implements Playable {
|
||||||
public static final String TAG = "RemoteMedia";
|
public static final String TAG = "RemoteMedia";
|
||||||
@ -45,7 +36,7 @@ public class RemoteMedia implements Playable {
|
|||||||
private String feedAuthor;
|
private String feedAuthor;
|
||||||
private String imageUrl;
|
private String imageUrl;
|
||||||
private String feedLink;
|
private String feedLink;
|
||||||
private String mime_type;
|
private String mimeType;
|
||||||
private Date pubDate;
|
private Date pubDate;
|
||||||
private String notes;
|
private String notes;
|
||||||
private List<Chapter> chapters;
|
private List<Chapter> chapters;
|
||||||
@ -55,7 +46,7 @@ public class RemoteMedia implements Playable {
|
|||||||
|
|
||||||
public RemoteMedia(String downloadUrl, String itemId, String feedUrl, String feedTitle,
|
public RemoteMedia(String downloadUrl, String itemId, String feedUrl, String feedTitle,
|
||||||
String episodeTitle, String episodeLink, String feedAuthor,
|
String episodeTitle, String episodeLink, String feedAuthor,
|
||||||
String imageUrl, String feedLink, String mime_type, Date pubDate) {
|
String imageUrl, String feedLink, String mimeType, Date pubDate) {
|
||||||
this.downloadUrl = downloadUrl;
|
this.downloadUrl = downloadUrl;
|
||||||
this.itemIdentifier = itemId;
|
this.itemIdentifier = itemId;
|
||||||
this.feedUrl = feedUrl;
|
this.feedUrl = feedUrl;
|
||||||
@ -65,63 +56,28 @@ public class RemoteMedia implements Playable {
|
|||||||
this.feedAuthor = feedAuthor;
|
this.feedAuthor = feedAuthor;
|
||||||
this.imageUrl = imageUrl;
|
this.imageUrl = imageUrl;
|
||||||
this.feedLink = feedLink;
|
this.feedLink = feedLink;
|
||||||
this.mime_type = mime_type;
|
this.mimeType = mimeType;
|
||||||
this.pubDate = pubDate;
|
this.pubDate = pubDate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public RemoteMedia(FeedItem item) {
|
||||||
|
this.downloadUrl = item.getMedia().getDownload_url();
|
||||||
|
this.itemIdentifier = item.getItemIdentifier();
|
||||||
|
this.feedUrl = item.getFeed().getDownload_url();
|
||||||
|
this.feedTitle = item.getFeed().getTitle();
|
||||||
|
this.episodeTitle = item.getTitle();
|
||||||
|
this.episodeLink = item.getLink();
|
||||||
|
this.feedAuthor = item.getFeed().getAuthor();
|
||||||
|
this.imageUrl = item.getImageUrl();
|
||||||
|
this.feedLink = item.getFeed().getLink();
|
||||||
|
this.mimeType = item.getMedia().getMime_type();
|
||||||
|
this.pubDate = item.getPubDate();
|
||||||
|
}
|
||||||
|
|
||||||
public void setNotes(String notes) {
|
public void setNotes(String notes) {
|
||||||
this.notes = 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() {
|
public String getEpisodeIdentifier() {
|
||||||
return itemIdentifier;
|
return itemIdentifier;
|
||||||
}
|
}
|
||||||
@ -130,6 +86,38 @@ public class RemoteMedia implements Playable {
|
|||||||
return feedUrl;
|
return feedUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getDownloadUrl() {
|
||||||
|
return downloadUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getEpisodeLink() {
|
||||||
|
return episodeLink;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFeedAuthor() {
|
||||||
|
return feedAuthor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getImageUrl() {
|
||||||
|
return imageUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFeedLink() {
|
||||||
|
return feedLink;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMimeType() {
|
||||||
|
return mimeType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date getPubDate() {
|
||||||
|
return pubDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getNotes() {
|
||||||
|
return notes;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void writeToPreferences(SharedPreferences.Editor prefEditor) {
|
public void writeToPreferences(SharedPreferences.Editor prefEditor) {
|
||||||
//it seems pointless to do it, since the session should be kept by the remote device.
|
//it seems pointless to do it, since the session should be kept by the remote device.
|
||||||
@ -196,7 +184,7 @@ public class RemoteMedia implements Playable {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MediaType getMediaType() {
|
public MediaType getMediaType() {
|
||||||
return MediaType.fromMimeType(mime_type);
|
return MediaType.fromMimeType(mimeType);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -293,7 +281,7 @@ public class RemoteMedia implements Playable {
|
|||||||
dest.writeString(feedAuthor);
|
dest.writeString(feedAuthor);
|
||||||
dest.writeString(imageUrl);
|
dest.writeString(imageUrl);
|
||||||
dest.writeString(feedLink);
|
dest.writeString(feedLink);
|
||||||
dest.writeString(mime_type);
|
dest.writeString(mimeType);
|
||||||
dest.writeLong(pubDate.getTime());
|
dest.writeLong(pubDate.getTime());
|
||||||
dest.writeString(notes);
|
dest.writeString(notes);
|
||||||
dest.writeInt(duration);
|
dest.writeInt(duration);
|
||||||
@ -324,9 +312,9 @@ public class RemoteMedia implements Playable {
|
|||||||
public boolean equals(Object other) {
|
public boolean equals(Object other) {
|
||||||
if (other instanceof RemoteMedia) {
|
if (other instanceof RemoteMedia) {
|
||||||
RemoteMedia rm = (RemoteMedia) other;
|
RemoteMedia rm = (RemoteMedia) other;
|
||||||
return TextUtils.equals(downloadUrl, rm.downloadUrl) &&
|
return TextUtils.equals(downloadUrl, rm.downloadUrl)
|
||||||
TextUtils.equals(feedUrl, rm.feedUrl) &&
|
&& TextUtils.equals(feedUrl, rm.feedUrl)
|
||||||
TextUtils.equals(itemIdentifier, rm.itemIdentifier);
|
&& TextUtils.equals(itemIdentifier, rm.itemIdentifier);
|
||||||
}
|
}
|
||||||
if (other instanceof FeedMedia) {
|
if (other instanceof FeedMedia) {
|
||||||
FeedMedia fm = (FeedMedia) other;
|
FeedMedia fm = (FeedMedia) other;
|
@ -657,6 +657,7 @@
|
|||||||
<!-- Online feed view -->
|
<!-- Online feed view -->
|
||||||
<string name="subscribe_label">Subscribe</string>
|
<string name="subscribe_label">Subscribe</string>
|
||||||
<string name="subscribing_label">Subscribing…</string>
|
<string name="subscribing_label">Subscribing…</string>
|
||||||
|
<string name="preview_episode">Preview</string>
|
||||||
|
|
||||||
<!-- Content descriptions for image buttons -->
|
<!-- Content descriptions for image buttons -->
|
||||||
<string name="rewind_label">Rewind</string>
|
<string name="rewind_label">Rewind</string>
|
||||||
|
@ -9,6 +9,7 @@ import com.google.android.gms.cast.MediaInfo;
|
|||||||
import com.google.android.gms.cast.MediaMetadata;
|
import com.google.android.gms.cast.MediaMetadata;
|
||||||
import com.google.android.gms.common.images.WebImage;
|
import com.google.android.gms.common.images.WebImage;
|
||||||
|
|
||||||
|
import de.danoeh.antennapod.core.util.playback.RemoteMedia;
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,6 @@
|
|||||||
package de.danoeh.antennapod.core.feed;
|
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.
|
* Implements methods for FeedMedia that are flavor dependent.
|
||||||
|
@ -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.NoConnectionException;
|
||||||
import com.google.android.libraries.cast.companionlibrary.cast.exceptions.TransientNetworkDisconnectionException;
|
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.Future;
|
||||||
import java.util.concurrent.FutureTask;
|
import java.util.concurrent.FutureTask;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
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.CastManager;
|
||||||
import de.danoeh.antennapod.core.cast.CastUtils;
|
import de.danoeh.antennapod.core.cast.CastUtils;
|
||||||
import de.danoeh.antennapod.core.cast.DefaultCastConsumer;
|
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.FeedMedia;
|
||||||
import de.danoeh.antennapod.core.feed.MediaType;
|
import de.danoeh.antennapod.core.feed.MediaType;
|
||||||
import de.danoeh.antennapod.core.preferences.UserPreferences;
|
import de.danoeh.antennapod.core.preferences.UserPreferences;
|
||||||
@ -165,7 +166,7 @@ public class RemotePSMP extends PlaybackServiceMediaPlayer {
|
|||||||
return CastUtils.convertFromFeedMedia((FeedMedia) playable);
|
return CastUtils.convertFromFeedMedia((FeedMedia) playable);
|
||||||
}
|
}
|
||||||
if (playable instanceof RemoteMedia) {
|
if (playable instanceof RemoteMedia) {
|
||||||
return ((RemoteMedia) playable).extractMediaInfo();
|
return MediaInfoCreator.from((RemoteMedia) playable);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user