use of de.danoeh.antennapod.model.feed.FeedMedia in project AntennaPod by AntennaPod.
the class AtomParserTest method testAtomBasic.
@Test
public void testAtomBasic() throws Exception {
File feedFile = FeedParserTestHelper.getFeedFile("feed-atom-testAtomBasic.xml");
Feed feed = FeedParserTestHelper.runFeedParser(feedFile);
assertEquals(Feed.TYPE_ATOM1, feed.getType());
assertEquals("title", feed.getTitle());
assertEquals("http://example.com/feed", feed.getFeedIdentifier());
assertEquals("http://example.com", feed.getLink());
assertEquals("This is the description", feed.getDescription());
assertEquals("http://example.com/payment", feed.getPaymentLinks().get(0).url);
assertEquals("http://example.com/picture", feed.getImageUrl());
assertEquals(10, feed.getItems().size());
for (int i = 0; i < feed.getItems().size(); i++) {
FeedItem item = feed.getItems().get(i);
assertEquals("http://example.com/item-" + i, item.getItemIdentifier());
assertEquals("item-" + i, item.getTitle());
assertNull(item.getDescription());
assertEquals("http://example.com/items/" + i, item.getLink());
assertEquals(new Date(i * 60000), item.getPubDate());
assertNull(item.getPaymentLink());
assertEquals("http://example.com/picture", item.getImageLocation());
// media
assertTrue(item.hasMedia());
FeedMedia media = item.getMedia();
// noinspection ConstantConditions
assertEquals("http://example.com/media-" + i, media.getDownload_url());
assertEquals(1024 * 1024, media.getSize());
assertEquals("audio/mp3", media.getMime_type());
// chapters
assertNull(item.getChapters());
}
}
use of de.danoeh.antennapod.model.feed.FeedMedia in project AntennaPod by AntennaPod.
the class Media method handleElementStart.
@Override
public SyndElement handleElementStart(String localName, HandlerState state, Attributes attributes) {
if (CONTENT.equals(localName)) {
String url = attributes.getValue(DOWNLOAD_URL);
String type = attributes.getValue(MIME_TYPE);
String defaultStr = attributes.getValue(DEFAULT);
String medium = attributes.getValue(MEDIUM);
boolean validTypeMedia = false;
boolean validTypeImage = false;
boolean isDefault = "true".equals(defaultStr);
String guessedType = SyndTypeUtils.getMimeTypeFromUrl(url);
if (MEDIUM_AUDIO.equals(medium)) {
validTypeMedia = true;
type = "audio/*";
} else if (MEDIUM_VIDEO.equals(medium)) {
validTypeMedia = true;
type = "video/*";
} else if (MEDIUM_IMAGE.equals(medium) && (guessedType == null || (!guessedType.startsWith("audio/") && !guessedType.startsWith("video/")))) {
// Apparently, some publishers explicitly specify the audio file as an image
validTypeImage = true;
type = "image/*";
} else {
if (type == null) {
type = guessedType;
}
if (SyndTypeUtils.enclosureTypeValid(type)) {
validTypeMedia = true;
} else if (SyndTypeUtils.imageTypeValid(type)) {
validTypeImage = true;
}
}
if (state.getCurrentItem() != null && (state.getCurrentItem().getMedia() == null || isDefault) && url != null && validTypeMedia) {
long size = 0;
String sizeStr = attributes.getValue(SIZE);
try {
size = Long.parseLong(sizeStr);
} catch (NumberFormatException e) {
Log.e(TAG, "Size \"" + sizeStr + "\" could not be parsed.");
}
int durationMs = 0;
String durationStr = attributes.getValue(DURATION);
if (!TextUtils.isEmpty(durationStr)) {
try {
long duration = Long.parseLong(durationStr);
durationMs = (int) TimeUnit.MILLISECONDS.convert(duration, TimeUnit.SECONDS);
} catch (NumberFormatException e) {
Log.e(TAG, "Duration \"" + durationStr + "\" could not be parsed");
}
}
FeedMedia media = new FeedMedia(state.getCurrentItem(), url, size, type);
if (durationMs > 0) {
media.setDuration(durationMs);
}
state.getCurrentItem().setMedia(media);
} else if (state.getCurrentItem() != null && url != null && validTypeImage) {
state.getCurrentItem().setImageUrl(url);
}
} else if (IMAGE.equals(localName)) {
String url = attributes.getValue(IMAGE_URL);
if (url != null) {
if (state.getCurrentItem() != null) {
state.getCurrentItem().setImageUrl(url);
} else {
if (state.getFeed().getImageUrl() == null) {
state.getFeed().setImageUrl(url);
}
}
}
} else if (DESCRIPTION.equals(localName)) {
String type = attributes.getValue(DESCRIPTION_TYPE);
return new AtomText(localName, this, type);
}
return new SyndElement(localName, this);
}
use of de.danoeh.antennapod.model.feed.FeedMedia in project AntennaPod by AntennaPod.
the class FeedItemMenuHandler method onMenuItemClicked.
/**
* Default menu handling for the given FeedItem.
*
* A Fragment instance, (rather than the more generic Context), is needed as a parameter
* to support some UI operations, e.g., creating a Snackbar.
*/
public static boolean onMenuItemClicked(@NonNull Fragment fragment, int menuItemId, @NonNull FeedItem selectedItem) {
@NonNull Context context = fragment.requireContext();
if (menuItemId == R.id.skip_episode_item) {
IntentUtils.sendLocalBroadcast(context, PlaybackService.ACTION_SKIP_CURRENT_EPISODE);
} else if (menuItemId == R.id.remove_item) {
DBWriter.deleteFeedMediaOfItem(context, selectedItem.getMedia().getId());
} else if (menuItemId == R.id.remove_new_flag_item) {
removeNewFlagWithUndo(fragment, selectedItem);
} else if (menuItemId == R.id.mark_read_item) {
selectedItem.setPlayed(true);
DBWriter.markItemPlayed(selectedItem, FeedItem.PLAYED, true);
if (SynchronizationSettings.isProviderConnected()) {
FeedMedia media = selectedItem.getMedia();
// not all items have media, Gpodder only cares about those that do
if (media != null) {
EpisodeAction actionPlay = new EpisodeAction.Builder(selectedItem, EpisodeAction.PLAY).currentTimestamp().started(media.getDuration() / 1000).position(media.getDuration() / 1000).total(media.getDuration() / 1000).build();
SynchronizationQueueSink.enqueueEpisodeActionIfSynchronizationIsActive(context, actionPlay);
}
}
} else if (menuItemId == R.id.mark_unread_item) {
selectedItem.setPlayed(false);
DBWriter.markItemPlayed(selectedItem, FeedItem.UNPLAYED, false);
if (selectedItem.getMedia() != null) {
EpisodeAction actionNew = new EpisodeAction.Builder(selectedItem, EpisodeAction.NEW).currentTimestamp().build();
SynchronizationQueueSink.enqueueEpisodeActionIfSynchronizationIsActive(context, actionNew);
}
} else if (menuItemId == R.id.add_to_queue_item) {
DBWriter.addQueueItem(context, selectedItem);
} else if (menuItemId == R.id.remove_from_queue_item) {
DBWriter.removeQueueItem(context, true, selectedItem);
} else if (menuItemId == R.id.add_to_favorites_item) {
DBWriter.addFavoriteItem(selectedItem);
} else if (menuItemId == R.id.remove_from_favorites_item) {
DBWriter.removeFavoriteItem(selectedItem);
} else if (menuItemId == R.id.reset_position) {
selectedItem.getMedia().setPosition(0);
if (PlaybackPreferences.getCurrentlyPlayingFeedMediaId() == selectedItem.getMedia().getId()) {
PlaybackPreferences.writeNoMediaPlaying();
IntentUtils.sendLocalBroadcast(context, PlaybackService.ACTION_SHUTDOWN_PLAYBACK_SERVICE);
}
DBWriter.markItemPlayed(selectedItem, FeedItem.UNPLAYED, true);
} else if (menuItemId == R.id.visit_website_item) {
IntentUtils.openInBrowser(context, FeedItemUtil.getLinkWithFallback(selectedItem));
} else if (menuItemId == R.id.share_item) {
ShareDialog shareDialog = ShareDialog.newInstance(selectedItem);
shareDialog.show((fragment.getActivity().getSupportFragmentManager()), "ShareEpisodeDialog");
} else {
Log.d(TAG, "Unknown menuItemId: " + menuItemId);
return false;
}
return true;
}
use of de.danoeh.antennapod.model.feed.FeedMedia in project AntennaPod by AntennaPod.
the class FeedItemMenuHandler method markReadWithUndo.
/**
* Remove new flag with additional UI logic to allow undo with Snackbar.
*
* Undo is useful for Remove new flag, given there is no UI to undo it otherwise
* ,i.e., there is (context) menu item for add new flag
*/
public static void markReadWithUndo(@NonNull Fragment fragment, FeedItem item, int playState, boolean showSnackbar) {
if (item == null) {
return;
}
Log.d(TAG, "markReadWithUndo(" + item.getId() + ")");
// we're marking it as unplayed since the user didn't actually play it
// but they don't want it considered 'NEW' anymore
DBWriter.markItemPlayed(playState, item.getId());
final Handler h = new Handler(fragment.requireContext().getMainLooper());
final Runnable r = () -> {
FeedMedia media = item.getMedia();
if (media != null && FeedItemUtil.hasAlmostEnded(media) && UserPreferences.isAutoDelete()) {
DBWriter.deleteFeedMediaOfItem(fragment.requireContext(), media.getId());
}
};
int playStateStringRes;
switch(playState) {
default:
case FeedItem.UNPLAYED:
if (item.getPlayState() == FeedItem.NEW) {
// was new
playStateStringRes = R.string.removed_new_flag_label;
} else {
// was played
playStateStringRes = R.string.marked_as_unplayed_label;
}
break;
case FeedItem.PLAYED:
playStateStringRes = R.string.marked_as_played_label;
break;
}
int duration = Snackbar.LENGTH_LONG;
if (showSnackbar) {
((MainActivity) fragment.getActivity()).showSnackbarAbovePlayer(playStateStringRes, duration).setAction(fragment.getString(R.string.undo), v -> {
DBWriter.markItemPlayed(item.getPlayState(), item.getId());
// don't forget to cancel the thing that's going to remove the media
h.removeCallbacks(r);
});
}
h.postDelayed(r, (int) Math.ceil(duration * 1.05f));
}
use of de.danoeh.antennapod.model.feed.FeedMedia in project AntennaPod by AntennaPod.
the class PlaybackSpeedUtils method getCurrentPlaybackSpeed.
/**
* Returns the currently configured playback speed for the specified media.
*/
public static float getCurrentPlaybackSpeed(Playable media) {
float playbackSpeed = SPEED_USE_GLOBAL;
MediaType mediaType = null;
if (media != null) {
mediaType = media.getMediaType();
playbackSpeed = PlaybackPreferences.getCurrentlyPlayingTemporaryPlaybackSpeed();
if (playbackSpeed == SPEED_USE_GLOBAL && media instanceof FeedMedia) {
FeedItem item = ((FeedMedia) media).getItem();
if (item != null) {
Feed feed = item.getFeed();
if (feed != null && feed.getPreferences() != null) {
playbackSpeed = feed.getPreferences().getFeedPlaybackSpeed();
} else {
Log.d(TAG, "Can not get feed specific playback speed: " + feed);
}
}
}
}
if (playbackSpeed == SPEED_USE_GLOBAL) {
playbackSpeed = UserPreferences.getPlaybackSpeed(mediaType);
}
return playbackSpeed;
}
Aggregations