Search in sources :

Example 1 with FeedMedia

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());
    }
}
Also used : FeedItem(de.danoeh.antennapod.model.feed.FeedItem) FeedMedia(de.danoeh.antennapod.model.feed.FeedMedia) File(java.io.File) Date(java.util.Date) Feed(de.danoeh.antennapod.model.feed.Feed) Test(org.junit.Test)

Example 2 with FeedMedia

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);
}
Also used : FeedMedia(de.danoeh.antennapod.model.feed.FeedMedia) SyndElement(de.danoeh.antennapod.parser.feed.element.SyndElement) AtomText(de.danoeh.antennapod.parser.feed.element.AtomText)

Example 3 with FeedMedia

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;
}
Also used : Context(android.content.Context) ShareDialog(de.danoeh.antennapod.dialog.ShareDialog) FeedMedia(de.danoeh.antennapod.model.feed.FeedMedia) NonNull(androidx.annotation.NonNull) EpisodeAction(de.danoeh.antennapod.net.sync.model.EpisodeAction)

Example 4 with FeedMedia

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));
}
Also used : FeedMedia(de.danoeh.antennapod.model.feed.FeedMedia) Handler(android.os.Handler)

Example 5 with FeedMedia

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;
}
Also used : FeedItem(de.danoeh.antennapod.model.feed.FeedItem) FeedMedia(de.danoeh.antennapod.model.feed.FeedMedia) MediaType(de.danoeh.antennapod.model.playback.MediaType) Feed(de.danoeh.antennapod.model.feed.Feed)

Aggregations

FeedMedia (de.danoeh.antennapod.model.feed.FeedMedia)91 FeedItem (de.danoeh.antennapod.model.feed.FeedItem)46 Test (org.junit.Test)28 Feed (de.danoeh.antennapod.model.feed.Feed)26 Date (java.util.Date)25 ArrayList (java.util.ArrayList)18 FeedPreferences (de.danoeh.antennapod.model.feed.FeedPreferences)15 File (java.io.File)15 Playable (de.danoeh.antennapod.model.playback.Playable)8 View (android.view.View)6 NonNull (androidx.annotation.NonNull)6 Context (android.content.Context)5 Log (android.util.Log)5 PlaybackServiceStarter (de.danoeh.antennapod.core.util.playback.PlaybackServiceStarter)5 Cursor (android.database.Cursor)4 Nullable (androidx.annotation.Nullable)4 R (de.danoeh.antennapod.R)4 DownloadRequest (de.danoeh.antennapod.core.service.download.DownloadRequest)4 DownloadService (de.danoeh.antennapod.core.service.download.DownloadService)4 Intent (android.content.Intent)3