adapt FeedMedia class to different flavors

This commit is contained in:
Domingos Lopes 2016-06-06 12:18:37 -04:00
parent bcdcfe0d58
commit 107e5c266f
5 changed files with 23 additions and 1161 deletions

View File

@ -1,567 +0,0 @@
package de.danoeh.antennapod.core.feed;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.database.Cursor;
import android.media.MediaMetadataRetriever;
import android.os.Parcel;
import android.os.Parcelable;
import android.support.annotation.Nullable;
import java.util.Date;
import java.util.List;
import java.util.concurrent.Callable;
import de.danoeh.antennapod.core.preferences.PlaybackPreferences;
import de.danoeh.antennapod.core.preferences.UserPreferences;
import de.danoeh.antennapod.core.storage.DBReader;
import de.danoeh.antennapod.core.storage.DBWriter;
import de.danoeh.antennapod.core.storage.PodDBAdapter;
import de.danoeh.antennapod.core.util.ChapterUtils;
import de.danoeh.antennapod.core.util.playback.Playable;
public class FeedMedia extends FeedFile implements Playable {
private static final String TAG = "FeedMedia";
public static final int FEEDFILETYPE_FEEDMEDIA = 2;
public static final int PLAYABLE_TYPE_FEEDMEDIA = 1;
public static final String PREF_MEDIA_ID = "FeedMedia.PrefMediaId";
public static final String PREF_FEED_ID = "FeedMedia.PrefFeedId";
/**
* Indicates we've checked on the size of the item via the network
* and got an invalid response. Using Integer.MIN_VALUE because
* 1) we'll still check on it in case it gets downloaded (it's <= 0)
* 2) By default all FeedMedia have a size of 0 if we don't know it,
* so this won't conflict with existing practice.
*/
private static final int CHECKED_ON_SIZE_BUT_UNKNOWN = Integer.MIN_VALUE;
private int duration;
private int position; // Current position in file
private long lastPlayedTime; // Last time this media was played (in ms)
private int played_duration; // How many ms of this file have been played (for autoflattring)
private long size; // File size in Byte
private String mime_type;
@Nullable private volatile FeedItem item;
private Date playbackCompletionDate;
// if null: unknown, will be checked
private Boolean hasEmbeddedPicture;
/* Used for loading item when restoring from parcel. */
private long itemID;
public FeedMedia(FeedItem i, String download_url, long size,
String mime_type) {
super(null, download_url, false);
this.item = i;
this.size = size;
this.mime_type = mime_type;
}
public FeedMedia(long id, FeedItem item, int duration, int position,
long size, String mime_type, String file_url, String download_url,
boolean downloaded, Date playbackCompletionDate, int played_duration,
long lastPlayedTime) {
super(file_url, download_url, downloaded);
this.id = id;
this.item = item;
this.duration = duration;
this.position = position;
this.played_duration = played_duration;
this.size = size;
this.mime_type = mime_type;
this.playbackCompletionDate = playbackCompletionDate == null
? null : (Date) playbackCompletionDate.clone();
this.lastPlayedTime = lastPlayedTime;
}
public FeedMedia(long id, FeedItem item, int duration, int position,
long size, String mime_type, String file_url, String download_url,
boolean downloaded, Date playbackCompletionDate, int played_duration,
Boolean hasEmbeddedPicture, long lastPlayedTime) {
this(id, item, duration, position, size, mime_type, file_url, download_url, downloaded,
playbackCompletionDate, played_duration, lastPlayedTime);
this.hasEmbeddedPicture = hasEmbeddedPicture;
}
public static FeedMedia fromCursor(Cursor cursor) {
int indexId = cursor.getColumnIndex(PodDBAdapter.KEY_ID);
int indexPlaybackCompletionDate = cursor.getColumnIndex(PodDBAdapter.KEY_PLAYBACK_COMPLETION_DATE);
int indexDuration = cursor.getColumnIndex(PodDBAdapter.KEY_DURATION);
int indexPosition = cursor.getColumnIndex(PodDBAdapter.KEY_POSITION);
int indexSize = cursor.getColumnIndex(PodDBAdapter.KEY_SIZE);
int indexMimeType = cursor.getColumnIndex(PodDBAdapter.KEY_MIME_TYPE);
int indexFileUrl = cursor.getColumnIndex(PodDBAdapter.KEY_FILE_URL);
int indexDownloadUrl = cursor.getColumnIndex(PodDBAdapter.KEY_DOWNLOAD_URL);
int indexDownloaded = cursor.getColumnIndex(PodDBAdapter.KEY_DOWNLOADED);
int indexPlayedDuration = cursor.getColumnIndex(PodDBAdapter.KEY_PLAYED_DURATION);
int indexLastPlayedTime = cursor.getColumnIndex(PodDBAdapter.KEY_LAST_PLAYED_TIME);
long mediaId = cursor.getLong(indexId);
Date playbackCompletionDate = null;
long playbackCompletionTime = cursor.getLong(indexPlaybackCompletionDate);
if (playbackCompletionTime > 0) {
playbackCompletionDate = new Date(playbackCompletionTime);
}
Boolean hasEmbeddedPicture;
switch(cursor.getInt(cursor.getColumnIndex(PodDBAdapter.KEY_HAS_EMBEDDED_PICTURE))) {
case 1:
hasEmbeddedPicture = Boolean.TRUE;
break;
case 0:
hasEmbeddedPicture = Boolean.FALSE;
break;
default:
hasEmbeddedPicture = null;
break;
}
return new FeedMedia(
mediaId,
null,
cursor.getInt(indexDuration),
cursor.getInt(indexPosition),
cursor.getLong(indexSize),
cursor.getString(indexMimeType),
cursor.getString(indexFileUrl),
cursor.getString(indexDownloadUrl),
cursor.getInt(indexDownloaded) > 0,
playbackCompletionDate,
cursor.getInt(indexPlayedDuration),
hasEmbeddedPicture,
cursor.getLong(indexLastPlayedTime)
);
}
@Override
public String getHumanReadableIdentifier() {
if (item != null && item.getTitle() != null) {
return item.getTitle();
} else {
return download_url;
}
}
/**
* Uses mimetype to determine the type of media.
*/
public MediaType getMediaType() {
return MediaType.fromMimeType(mime_type);
}
public void updateFromOther(FeedMedia other) {
super.updateFromOther(other);
if (other.size > 0) {
size = other.size;
}
if (other.mime_type != null) {
mime_type = other.mime_type;
}
}
public boolean compareWithOther(FeedMedia other) {
if (super.compareWithOther(other)) {
return true;
}
if (other.mime_type != null) {
if (mime_type == null || !mime_type.equals(other.mime_type)) {
return true;
}
}
if (other.size > 0 && other.size != size) {
return true;
}
return false;
}
/**
* Reads playback preferences to determine whether this FeedMedia object is
* currently being played.
*/
public boolean isPlaying() {
return PlaybackPreferences.getCurrentlyPlayingMedia() == FeedMedia.PLAYABLE_TYPE_FEEDMEDIA
&& PlaybackPreferences.getCurrentlyPlayingFeedMediaId() == id;
}
/**
* Reads playback preferences to determine whether this FeedMedia object is
* currently being played and the current player status is playing.
*/
public boolean isCurrentlyPlaying() {
return isPlaying() &&
((PlaybackPreferences.getCurrentPlayerStatus() == PlaybackPreferences.PLAYER_STATUS_PLAYING));
}
/**
* Reads playback preferences to determine whether this FeedMedia object is
* currently being played and the current player status is paused.
*/
public boolean isCurrentlyPaused() {
return isPlaying() &&
((PlaybackPreferences.getCurrentPlayerStatus() == PlaybackPreferences.PLAYER_STATUS_PAUSED));
}
public boolean hasAlmostEnded() {
int smartMarkAsPlayedSecs = UserPreferences.getSmartMarkAsPlayedSecs();
return this.position >= this.duration - smartMarkAsPlayedSecs * 1000;
}
@Override
public int getTypeAsInt() {
return FEEDFILETYPE_FEEDMEDIA;
}
public int getDuration() {
return duration;
}
public void setDuration(int duration) {
this.duration = duration;
}
@Override
public void setLastPlayedTime(long lastPlayedTime) {
this.lastPlayedTime = lastPlayedTime;
}
public int getPlayedDuration() {
return played_duration;
}
public void setPlayedDuration(int played_duration) {
this.played_duration = played_duration;
}
public int getPosition() {
return position;
}
@Override
public long getLastPlayedTime() {
return lastPlayedTime;
}
public void setPosition(int position) {
this.position = position;
if(position > 0 && item != null && item.isNew()) {
this.item.setPlayed(false);
}
}
public long getSize() {
return size;
}
public void setSize(long size) {
this.size = size;
}
/**
* Indicates we asked the service what the size was, but didn't
* get a valid answer and we shoudln't check using the network again.
*/
public void setCheckedOnSizeButUnknown() {
this.size = CHECKED_ON_SIZE_BUT_UNKNOWN;
}
public boolean checkedOnSizeButUnknown() {
return (CHECKED_ON_SIZE_BUT_UNKNOWN == this.size);
}
public String getMime_type() {
return mime_type;
}
public void setMime_type(String mime_type) {
this.mime_type = mime_type;
}
@Nullable
public FeedItem getItem() {
return item;
}
/**
* Sets the item object of this FeedMedia. If the given
* FeedItem object is not null, it's 'media'-attribute value
* will also be set to this media object.
*/
public void setItem(FeedItem item) {
this.item = item;
if (item != null && item.getMedia() != this) {
item.setMedia(this);
}
}
public Date getPlaybackCompletionDate() {
return playbackCompletionDate == null
? null : (Date) playbackCompletionDate.clone();
}
public void setPlaybackCompletionDate(Date playbackCompletionDate) {
this.playbackCompletionDate = playbackCompletionDate == null
? null : (Date) playbackCompletionDate.clone();
}
public boolean isInProgress() {
return (this.position > 0);
}
@Override
public int describeContents() {
return 0;
}
public boolean hasEmbeddedPicture() {
if(hasEmbeddedPicture == null) {
checkEmbeddedPicture();
}
return hasEmbeddedPicture;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeLong(id);
dest.writeLong(item != null ? item.getId() : 0L);
dest.writeInt(duration);
dest.writeInt(position);
dest.writeLong(size);
dest.writeString(mime_type);
dest.writeString(file_url);
dest.writeString(download_url);
dest.writeByte((byte) ((downloaded) ? 1 : 0));
dest.writeLong((playbackCompletionDate != null) ? playbackCompletionDate.getTime() : 0);
dest.writeInt(played_duration);
dest.writeLong(lastPlayedTime);
}
@Override
public void writeToPreferences(Editor prefEditor) {
if(item != null && item.getFeed() != null) {
prefEditor.putLong(PREF_FEED_ID, item.getFeed().getId());
} else {
prefEditor.putLong(PREF_FEED_ID, 0L);
}
prefEditor.putLong(PREF_MEDIA_ID, id);
}
@Override
public void loadMetadata() throws PlayableException {
if (item == null && itemID != 0) {
item = DBReader.getFeedItem(itemID);
}
}
@Override
public void loadChapterMarks() {
if (item == null && itemID != 0) {
item = DBReader.getFeedItem(itemID);
}
// check if chapters are stored in db and not loaded yet.
if (item != null && item.hasChapters() && item.getChapters() == null) {
DBReader.loadChaptersOfFeedItem(item);
} else if (item != null && item.getChapters() == null) {
if(localFileAvailable()) {
ChapterUtils.loadChaptersFromFileUrl(this);
} else {
ChapterUtils.loadChaptersFromStreamUrl(this);
}
if (getChapters() != null && item != null) {
DBWriter.setFeedItem(item);
}
}
}
@Override
public String getEpisodeTitle() {
if (item == null) {
return null;
}
if (item.getTitle() != null) {
return item.getTitle();
} else {
return item.getIdentifyingValue();
}
}
@Override
public List<Chapter> getChapters() {
if (item == null) {
return null;
}
return item.getChapters();
}
@Override
public String getWebsiteLink() {
if (item == null) {
return null;
}
return item.getLink();
}
@Override
public String getFeedTitle() {
if (item == null || item.getFeed() == null) {
return null;
}
return item.getFeed().getTitle();
}
@Override
public Object getIdentifier() {
return id;
}
@Override
public String getLocalMediaUrl() {
return file_url;
}
@Override
public String getStreamUrl() {
return download_url;
}
@Override
public String getPaymentLink() {
if (item == null) {
return null;
}
return item.getPaymentLink();
}
@Override
public boolean localFileAvailable() {
return isDownloaded() && file_url != null;
}
@Override
public boolean streamAvailable() {
return download_url != null;
}
@Override
public void saveCurrentPosition(SharedPreferences pref, int newPosition, long timeStamp) {
if(item != null && item.isNew()) {
DBWriter.markItemPlayed(FeedItem.UNPLAYED, item.getId());
}
setPosition(newPosition);
setLastPlayedTime(timeStamp);
DBWriter.setFeedMediaPlaybackInformation(this);
}
@Override
public void onPlaybackStart() {
}
@Override
public void onPlaybackCompleted() {
}
@Override
public int getPlayableType() {
return PLAYABLE_TYPE_FEEDMEDIA;
}
@Override
public void setChapters(List<Chapter> chapters) {
if(item != null) {
item.setChapters(chapters);
}
}
@Override
public Callable<String> loadShownotes() {
return () -> {
if (item == null) {
item = DBReader.getFeedItem(
itemID);
}
if (item.getContentEncoded() == null || item.getDescription() == null) {
DBReader.loadExtraInformationOfFeedItem(
item);
}
return (item.getContentEncoded() != null) ? item.getContentEncoded() : item.getDescription();
};
}
public static final Parcelable.Creator<FeedMedia> CREATOR = new Parcelable.Creator<FeedMedia>() {
public FeedMedia createFromParcel(Parcel in) {
final long id = in.readLong();
final long itemID = in.readLong();
FeedMedia result = new FeedMedia(id, null, in.readInt(), in.readInt(), in.readLong(), in.readString(), in.readString(),
in.readString(), in.readByte() != 0, new Date(in.readLong()), in.readInt(), in.readLong());
result.itemID = itemID;
return result;
}
public FeedMedia[] newArray(int size) {
return new FeedMedia[size];
}
};
@Override
public String getImageLocation() {
if (hasEmbeddedPicture()) {
return getLocalMediaUrl();
} else if(item != null) {
return item.getImageLocation();
} else {
return null;
}
}
public void setHasEmbeddedPicture(Boolean hasEmbeddedPicture) {
this.hasEmbeddedPicture = hasEmbeddedPicture;
}
@Override
public void setDownloaded(boolean downloaded) {
super.setDownloaded(downloaded);
if(item != null && downloaded) {
item.setPlayed(false);
}
}
@Override
public void setFile_url(String file_url) {
super.setFile_url(file_url);
}
public void checkEmbeddedPicture() {
if (!localFileAvailable()) {
hasEmbeddedPicture = Boolean.FALSE;
return;
}
MediaMetadataRetriever mmr = new MediaMetadataRetriever();
try {
mmr.setDataSource(getLocalMediaUrl());
byte[] image = mmr.getEmbeddedPicture();
if(image != null) {
hasEmbeddedPicture = Boolean.TRUE;
} else {
hasEmbeddedPicture = Boolean.FALSE;
}
} catch (Exception e) {
e.printStackTrace();
hasEmbeddedPicture = Boolean.FALSE;
}
}
// @Override
// public boolean equals(Object o) {
// if (o instanceof RemoteMedia) {
// return o.equals(this);
// }
// return super.equals(o);
// }
}

View File

@ -0,0 +1,10 @@
package de.danoeh.antennapod.core.feed;
/**
* Implements methods for FeedMedia that are flavor dependent.
*/
public class FeedMediaHelper {
static boolean instanceOfRemoteMedia(Object o) {
return false;
}
}

View File

@ -1,592 +0,0 @@
//package de.danoeh.antennapod.core.service.playback;
//
//import android.content.Context;
//import android.media.MediaPlayer;
//import android.support.annotation.NonNull;
//import android.util.Log;
//import android.util.Pair;
//import android.view.SurfaceHolder;
//
//import com.google.android.gms.cast.Cast;
//import com.google.android.gms.cast.CastStatusCodes;
//import com.google.android.gms.cast.MediaInfo;
//import com.google.android.gms.cast.MediaStatus;
//import com.google.android.libraries.cast.companionlibrary.cast.exceptions.CastException;
//import com.google.android.libraries.cast.companionlibrary.cast.exceptions.NoConnectionException;
//import com.google.android.libraries.cast.companionlibrary.cast.exceptions.TransientNetworkDisconnectionException;
//
//import java.util.concurrent.atomic.AtomicBoolean;
//
//import de.danoeh.antennapod.core.R;
//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.feed.FeedMedia;
//import de.danoeh.antennapod.core.feed.MediaType;
//import de.danoeh.antennapod.core.util.RewindAfterPauseUtils;
//import de.danoeh.antennapod.core.util.playback.Playable;
//
///**
// * Implementation of PlaybackServiceMediaPlayer suitable for remote playback on Cast Devices.
// */
//public class RemotePSMP extends PlaybackServiceMediaPlayer {
//
// public static final String TAG = "RemotePSMP";
//
// public static final int CAST_ERROR = 3001;
//
// public static final int CAST_ERROR_PRIORITY_HIGH = 3005;
//
// private final CastManager castMgr;
//
// private volatile Playable media;
// private volatile MediaInfo remoteMedia;
// private volatile MediaType mediaType;
//
// private final AtomicBoolean isBuffering;
//
// private final AtomicBoolean startWhenPrepared;
//
// public RemotePSMP(@NonNull Context context, @NonNull PSMPCallback callback) {
// super(context, callback);
//
// castMgr = CastManager.getInstance();
// media = null;
// mediaType = null;
// startWhenPrepared = new AtomicBoolean(false);
// isBuffering = new AtomicBoolean(false);
//
// try {
// if (castMgr.isConnected() && castMgr.isRemoteMediaLoaded()) {
// // updates the state, but does not start playing new media if it was going to
// onRemoteMediaPlayerStatusUpdated(
// ((p, playNextEpisode, wasSkipped, switchingPlayers) ->
// this.callback.endPlayback(p, false, wasSkipped, switchingPlayers)));
// }
// } catch (TransientNetworkDisconnectionException | NoConnectionException e) {
// Log.e(TAG, "Unable to do initial check for loaded media", e);
// }
//
// castMgr.addCastConsumer(castConsumer);
// //TODO
// }
//
// private CastConsumer castConsumer = new DefaultCastConsumer() {
// @Override
// public void onRemoteMediaPlayerMetadataUpdated() {
// RemotePSMP.this.onRemoteMediaPlayerStatusUpdated(callback::endPlayback);
// }
//
// @Override
// public void onRemoteMediaPlayerStatusUpdated() {
// RemotePSMP.this.onRemoteMediaPlayerStatusUpdated(callback::endPlayback);
// }
//
// @Override
// public void onMediaLoadResult(int statusCode) {
// if (playerStatus == PlayerStatus.PREPARING) {
// if (statusCode == CastStatusCodes.SUCCESS) {
// setPlayerStatus(PlayerStatus.PREPARED, media);
// if (media.getDuration() == 0) {
// Log.d(TAG, "Setting duration of media");
// try {
// media.setDuration((int) castMgr.getMediaDuration());
// } catch (TransientNetworkDisconnectionException | NoConnectionException e) {
// Log.e(TAG, "Unable to get remote media's duration");
// }
// }
// } else if (statusCode != CastStatusCodes.REPLACED){
// Log.d(TAG, "Remote media failed to load");
// setPlayerStatus(PlayerStatus.INITIALIZED, media);
// }
// } else {
// Log.d(TAG, "onMediaLoadResult called, but Player Status wasn't in preparing state, so we ignore the result");
// }
// }
//
// @Override
// public void onApplicationStatusChanged(String appStatus) {
// if (playerStatus != PlayerStatus.PLAYING) {
// Log.d(TAG, "onApplicationStatusChanged, but no media was playing");
// return;
// }
// boolean playbackEnded = false;
// try {
// int standbyState = castMgr.getApplicationStandbyState();
// Log.d(TAG, "standbyState: " + standbyState);
// playbackEnded = standbyState == Cast.STANDBY_STATE_YES;
// } catch (IllegalStateException e) {
// Log.d(TAG, "unable to get standbyState on onApplicationStatusChanged()");
// }
// if (playbackEnded) {
// setPlayerStatus(PlayerStatus.INDETERMINATE, media);
// callback.endPlayback(media, true, false, false);
// }
// }
//
// @Override
// public void onFailed(int resourceId, int statusCode) {
// callback.onMediaPlayerInfo(CAST_ERROR, resourceId);
// }
// };
//
// private void setBuffering(boolean buffering) {
// if (buffering && isBuffering.compareAndSet(false, true)) {
// callback.onMediaPlayerInfo(MediaPlayer.MEDIA_INFO_BUFFERING_START, 0);
// } else if (!buffering && isBuffering.compareAndSet(true, false)) {
// callback.onMediaPlayerInfo(MediaPlayer.MEDIA_INFO_BUFFERING_END, 0);
// }
// }
//
// private Playable localVersion(MediaInfo info){
// if (info == null) {
// return null;
// }
// if (CastUtils.matches(info, media)) {
// return media;
// }
// return CastUtils.getPlayable(info, true);
// }
//
// private MediaInfo remoteVersion(Playable playable) {
// if (playable == null) {
// return null;
// }
// if (CastUtils.matches(remoteMedia, playable)) {
// return remoteMedia;
// }
// if (playable instanceof FeedMedia) {
// return CastUtils.convertFromFeedMedia((FeedMedia) playable);
// }
// if (playable instanceof RemoteMedia) {
// return ((RemoteMedia) playable).extractMediaInfo();
// }
// return null;
// }
//
// private void onRemoteMediaPlayerStatusUpdated(@NonNull EndPlaybackCall endPlaybackCall) {
// MediaStatus status = castMgr.getMediaStatus();
// if (status == null) {
// Log.d(TAG, "Received null MediaStatus");
// //setBuffering(false);
// //setPlayerStatus(PlayerStatus.INDETERMINATE, null);
// return;
// } else {
// Log.d(TAG, "Received remote status/media update. New state=" + status.getPlayerState());
// }
// Playable currentMedia = localVersion(status.getMediaInfo());
// boolean updateUI = currentMedia != media;
// if (currentMedia != null) {
// long position = status.getStreamPosition();
// if (position > 0 && currentMedia.getPosition() == 0) {
// currentMedia.setPosition((int) position);
// }
// }
// int state = status.getPlayerState();
// setBuffering(state == MediaStatus.PLAYER_STATE_BUFFERING);
// switch (state) {
// case MediaStatus.PLAYER_STATE_PLAYING:
// setPlayerStatus(PlayerStatus.PLAYING, currentMedia);
// break;
// case MediaStatus.PLAYER_STATE_PAUSED:
// setPlayerStatus(PlayerStatus.PAUSED, currentMedia);
// break;
// case MediaStatus.PLAYER_STATE_BUFFERING:
// setPlayerStatus(playerStatus, currentMedia);
// break;
// case MediaStatus.PLAYER_STATE_IDLE:
// int reason = status.getIdleReason();
// switch (reason) {
// case MediaStatus.IDLE_REASON_CANCELED:
// // check if we're already loading something else
// if (!updateUI || media == null) {
// setPlayerStatus(PlayerStatus.STOPPED, currentMedia);
// } else {
// updateUI = false;
// }
// break;
// case MediaStatus.IDLE_REASON_INTERRUPTED:
// // check if we're already loading something else
// if (!updateUI || media == null) {
// setPlayerStatus(PlayerStatus.PREPARING, currentMedia);
// } else {
// updateUI = false;
// }
// break;
// case MediaStatus.IDLE_REASON_NONE:
// setPlayerStatus(PlayerStatus.INITIALIZED, currentMedia);
// break;
// case MediaStatus.IDLE_REASON_FINISHED:
// boolean playing = playerStatus == PlayerStatus.PLAYING;
// setPlayerStatus(PlayerStatus.INDETERMINATE, currentMedia);
// endPlaybackCall.endPlayback(currentMedia,playing, false, false);
// // endPlayback already updates the UI, so no need to trigger it ourselves
// updateUI = false;
// break;
// case MediaStatus.IDLE_REASON_ERROR:
// Log.w(TAG, "Got an error status from the Chromecast. Skipping, if possible, to the next episode...");
// setPlayerStatus(PlayerStatus.INDETERMINATE, currentMedia);
// callback.onMediaPlayerInfo(CAST_ERROR_PRIORITY_HIGH,
// R.string.cast_failed_media_error_skipping);
// endPlaybackCall.endPlayback(currentMedia, startWhenPrepared.get(), true, false);
// // endPlayback already updates the UI, so no need to trigger it ourselves
// updateUI = false;
// }
// break;
// case MediaStatus.PLAYER_STATE_UNKNOWN:
// //is this right?
// setPlayerStatus(PlayerStatus.INDETERMINATE, currentMedia);
// break;
// default:
// Log.e(TAG, "Remote media state undetermined!");
// setPlayerStatus(PlayerStatus.INDETERMINATE, currentMedia);
// }
// if (updateUI) {
// callback.onMediaChanged(true);
// }
// }
//
// @Override
// public void playMediaObject(@NonNull final Playable playable, final boolean stream, final boolean startWhenPrepared, final boolean prepareImmediately) {
// Log.d(TAG, "playMediaObject() called");
// playMediaObject(playable, false, stream, startWhenPrepared, prepareImmediately);
// }
//
// /**
// * Internal implementation of playMediaObject. This method has an additional parameter that allows the caller to force a media player reset even if
// * the given playable parameter is the same object as the currently playing media.
// *
// * @see #playMediaObject(de.danoeh.antennapod.core.util.playback.Playable, boolean, boolean, boolean)
// */
// private void playMediaObject(@NonNull final Playable playable, final boolean forceReset, final boolean stream, final boolean startWhenPrepared, final boolean prepareImmediately) {
// if (!CastUtils.isCastable(playable)) {
// Log.d(TAG, "media provided is not compatible with cast device");
// callback.onMediaPlayerInfo(CAST_ERROR_PRIORITY_HIGH, R.string.cast_not_castable);
// try {
// playable.loadMetadata();
// } catch (Playable.PlayableException e) {
// Log.e(TAG, "Unable to load metadata of playable", e);
// }
// callback.endPlayback(playable, startWhenPrepared, true, false);
// return;
// }
//
// if (media != null) {
// if (!forceReset && media.getIdentifier().equals(playable.getIdentifier())
// && playerStatus == PlayerStatus.PLAYING) {
// // episode is already playing -> ignore method call
// Log.d(TAG, "Method call to playMediaObject was ignored: media file already playing.");
// return;
// } else {
// // set temporarily to pause in order to update list with current position
// try {
// if (castMgr.isRemoteMediaPlaying()) {
// setPlayerStatus(PlayerStatus.PAUSED, media);
// }
// } catch (TransientNetworkDisconnectionException | NoConnectionException e) {
// Log.e(TAG, "Unable to determine whether media was playing, falling back to stored player status", e);
// // this might end up just being pointless if we need to query the remote device for the position
// if (playerStatus == PlayerStatus.PLAYING) {
// setPlayerStatus(PlayerStatus.PAUSED, media);
// }
// }
// smartMarkAsPlayed(media);
//
//
// setPlayerStatus(PlayerStatus.INDETERMINATE, null);
// }
// }
//
// this.media = playable;
// remoteMedia = remoteVersion(playable);
// //this.stream = stream;
// this.mediaType = media.getMediaType();
// this.startWhenPrepared.set(startWhenPrepared);
// setPlayerStatus(PlayerStatus.INITIALIZING, media);
// try {
// media.loadMetadata();
// callback.onMediaChanged(true);
// setPlayerStatus(PlayerStatus.INITIALIZED, media);
// if (prepareImmediately) {
// prepare();
// }
// } catch (Playable.PlayableException e) {
// Log.e(TAG, "Error while loading media metadata", e);
// setPlayerStatus(PlayerStatus.STOPPED, null);
// }
// }
//
// @Override
// public void resume() {
// try {
// // TODO see comment on prepare()
// // setVolume(UserPreferences.getLeftVolume(), UserPreferences.getRightVolume());
// if (playerStatus == PlayerStatus.PREPARED && media.getPosition() > 0) {
// int newPosition = RewindAfterPauseUtils.calculatePositionWithRewind(
// media.getPosition(),
// media.getLastPlayedTime());
// castMgr.play(newPosition);
// }
// castMgr.play();
// } catch (CastException | TransientNetworkDisconnectionException | NoConnectionException e) {
// Log.e(TAG, "Unable to resume remote playback", e);
// }
// }
//
// @Override
// public void pause(boolean abandonFocus, boolean reinit) {
// try {
// if (castMgr.isRemoteMediaPlaying()) {
// castMgr.pause();
// }
// } catch (CastException | TransientNetworkDisconnectionException | NoConnectionException e) {
// Log.e(TAG, "Unable to pause", e);
// }
// }
//
// @Override
// public void prepare() {
// if (playerStatus == PlayerStatus.INITIALIZED) {
// Log.d(TAG, "Preparing media player");
// setPlayerStatus(PlayerStatus.PREPARING, media);
// try {
// int position = media.getPosition();
// if (position > 0) {
// position = RewindAfterPauseUtils.calculatePositionWithRewind(
// position,
// media.getLastPlayedTime());
// }
// // TODO We're not supporting user set stream volume yet, as we need to make a UI
// // that doesn't allow changing playback speed or have different values for left/right
// //setVolume(UserPreferences.getLeftVolume(), UserPreferences.getRightVolume());
// castMgr.loadMedia(remoteMedia, startWhenPrepared.get(), position);
// } catch (TransientNetworkDisconnectionException | NoConnectionException e) {
// Log.e(TAG, "Error loading media", e);
// setPlayerStatus(PlayerStatus.INITIALIZED, media);
// }
// }
// }
//
// @Override
// public void reinit() {
// Log.d(TAG, "reinit() called");
// if (media != null) {
// playMediaObject(media, true, false, startWhenPrepared.get(), false);
// } else {
// Log.d(TAG, "Call to reinit was ignored: media was null");
// }
// }
//
// @Override
// public void seekTo(int t) {
// //TODO check other seek implementations and see if there's no issue with sending too many seek commands to the remote media player
// try {
// if (castMgr.isRemoteMediaLoaded()) {
// setPlayerStatus(PlayerStatus.SEEKING, media);
// castMgr.seek(t);
// } else if (media != null && playerStatus == PlayerStatus.INITIALIZED){
// media.setPosition(t);
// startWhenPrepared.set(false);
// prepare();
// }
// } catch (TransientNetworkDisconnectionException | NoConnectionException e) {
// Log.e(TAG, "Unable to seek", e);
// }
// }
//
// @Override
// public void seekDelta(int d) {
// int position = getPosition();
// if (position != INVALID_TIME) {
// seekTo(position + d);
// } else {
// Log.e(TAG, "getPosition() returned INVALID_TIME in seekDelta");
// }
// }
//
// @Override
// public int getDuration() {
// int retVal = INVALID_TIME;
// boolean prepared;
// try {
// prepared = castMgr.isRemoteMediaLoaded();
// } catch (TransientNetworkDisconnectionException | NoConnectionException e) {
// Log.e(TAG, "Unable to check if remote media is loaded", e);
// prepared = playerStatus.isAtLeast(PlayerStatus.PREPARED);
// }
// if (prepared) {
// try {
// retVal = (int) castMgr.getMediaDuration();
// } catch (TransientNetworkDisconnectionException | NoConnectionException e) {
// Log.e(TAG, "Unable to determine remote media's duration", e);
// }
// }
// if(retVal == INVALID_TIME && media != null && media.getDuration() > 0) {
// retVal = media.getDuration();
// }
// Log.d(TAG, "getDuration() -> " + retVal);
// return retVal;
// }
//
// @Override
// public int getPosition() {
// int retVal = INVALID_TIME;
// boolean prepared;
// try {
// prepared = castMgr.isRemoteMediaLoaded();
// } catch (TransientNetworkDisconnectionException | NoConnectionException e) {
// Log.e(TAG, "Unable to check if remote media is loaded", e);
// prepared = playerStatus.isAtLeast(PlayerStatus.PREPARED);
// }
// if (prepared) {
// try {
// retVal = (int) castMgr.getCurrentMediaPosition();
// } catch (TransientNetworkDisconnectionException | NoConnectionException e) {
// Log.e(TAG, "Unable to determine remote media's position", e);
// }
// }
// if(retVal <= 0 && media != null && media.getPosition() >= 0) {
// retVal = media.getPosition();
// }
// Log.d(TAG, "getPosition() -> " + retVal);
// return retVal;
// }
//
// @Override
// public boolean isStartWhenPrepared() {
// return startWhenPrepared.get();
// }
//
// @Override
// public void setStartWhenPrepared(boolean startWhenPrepared) {
// this.startWhenPrepared.set(startWhenPrepared);
// }
//
// //TODO I believe some parts of the code make the same decision skipping this check, so that
// //should be changed as well
// @Override
// public boolean canSetSpeed() {
// return false;
// }
//
// @Override
// public void setSpeed(float speed) {
// throw new UnsupportedOperationException("Setting playback speed unsupported for Remote Playback");
// }
//
// @Override
// public float getPlaybackSpeed() {
// return 1;
// }
//
// @Override
// public void setVolume(float volumeLeft, float volumeRight) {
// Log.d(TAG, "Setting the Stream volume on Remote Media Player");
// double volume = (volumeLeft+volumeRight)/2;
// if (volume > 1.0) {
// volume = 1.0;
// }
// if (volume < 0.0) {
// volume = 0.0;
// }
// try {
// castMgr.setStreamVolume(volume);
// } catch (TransientNetworkDisconnectionException | NoConnectionException | CastException e) {
// Log.e(TAG, "Unable to set the volume", e);
// }
// }
//
// @Override
// public boolean canDownmix() {
// return false;
// }
//
// @Override
// public void setDownmix(boolean enable) {
// throw new UnsupportedOperationException("Setting downmix unsupported in Remote Media Player");
// }
//
// @Override
// public MediaType getCurrentMediaType() {
// return mediaType;
// }
//
// @Override
// public boolean isStreaming() {
// return true;
// }
//
// @Override
// public void shutdown() {
// castMgr.removeCastConsumer(castConsumer);
// }
//
// @Override
// public void shutdownQuietly() {
// shutdown();
// }
//
// @Override
// public void setVideoSurface(SurfaceHolder surface) {
// throw new UnsupportedOperationException("Setting Video Surface unsupported in Remote Media Player");
// }
//
// @Override
// public void resetVideoSurface() {
// Log.e(TAG, "Resetting Video Surface unsupported in Remote Media Player");
// }
//
// @Override
// public Pair<Integer, Integer> getVideoSize() {
// return null;
// }
//
// @Override
// public Playable getPlayable() {
// return media;
// }
//
// @Override
// protected void setPlayable(Playable playable) {
// if (playable != media) {
// media = playable;
// remoteMedia = remoteVersion(playable);
// }
// }
//
// @Override
// public void endPlayback(boolean wasSkipped, boolean switchingPlayers) {
// Log.d(TAG, "endPlayback() called");
// boolean isPlaying = playerStatus == PlayerStatus.PLAYING;
// try {
// isPlaying = castMgr.isRemoteMediaPlaying();
// } catch (TransientNetworkDisconnectionException | NoConnectionException e) {
// Log.e(TAG, "Could not determine if media is playing", e);
// }
// // TODO make sure we stop playback whenever there's no next episode.
// if (playerStatus != PlayerStatus.INDETERMINATE) {
// setPlayerStatus(PlayerStatus.INDETERMINATE, media);
// }
// callback.endPlayback(media, isPlaying, wasSkipped, switchingPlayers);
// }
//
// @Override
// public void stop() {
// if (playerStatus == PlayerStatus.INDETERMINATE) {
// setPlayerStatus(PlayerStatus.STOPPED, null);
// } else {
// Log.d(TAG, "Ignored call to stop: Current player state is: " + playerStatus);
// }
// }
//
// @Override
// protected boolean shouldLockWifi() {
// return false;
// }
//
// private interface EndPlaybackCall {
// boolean endPlayback(Playable media, boolean playNextEpisode, boolean wasSkipped, boolean switchingPlayers);
// }
//}

View File

@ -12,7 +12,6 @@ import java.util.Date;
import java.util.List;
import java.util.concurrent.Callable;
import de.danoeh.antennapod.core.cast.RemoteMedia;
import de.danoeh.antennapod.core.preferences.PlaybackPreferences;
import de.danoeh.antennapod.core.preferences.UserPreferences;
import de.danoeh.antennapod.core.storage.DBReader;
@ -560,7 +559,7 @@ public class FeedMedia extends FeedFile implements Playable {
@Override
public boolean equals(Object o) {
if (o instanceof RemoteMedia) {
if (FeedMediaHelper.instanceOfRemoteMedia(o)) {
return o.equals(this);
}
return super.equals(o);

View File

@ -0,0 +1,12 @@
package de.danoeh.antennapod.core.feed;
import de.danoeh.antennapod.core.cast.RemoteMedia;
/**
* Implements methods for FeedMedia that are flavor dependent.
*/
public class FeedMediaHelper {
static boolean instanceOfRemoteMedia(Object o) {
return o instanceof RemoteMedia;
}
}