Search in sources :

Example 21 with FeedItem

use of de.danoeh.antennapod.model.feed.FeedItem in project AntennaPod by AntennaPod.

the class DBReader method getQueue.

@NonNull
static List<FeedItem> getQueue(PodDBAdapter adapter) {
    Log.d(TAG, "getQueue()");
    try (Cursor cursor = adapter.getQueueCursor()) {
        List<FeedItem> items = extractItemlistFromCursor(adapter, cursor);
        loadAdditionalFeedItemListData(items);
        return items;
    }
}
Also used : FeedItem(de.danoeh.antennapod.model.feed.FeedItem) Cursor(android.database.Cursor) NonNull(androidx.annotation.NonNull)

Example 22 with FeedItem

use of de.danoeh.antennapod.model.feed.FeedItem in project AntennaPod by AntennaPod.

the class DBReader method getNextInQueue.

/**
 * Get next feed item in queue following a particular feeditem
 *
 * @param item The FeedItem
 * @return The FeedItem next in queue or null if the FeedItem could not be found.
 */
@Nullable
public static FeedItem getNextInQueue(FeedItem item) {
    Log.d(TAG, "getNextInQueue() called with: " + "itemId = [" + item.getId() + "]");
    PodDBAdapter adapter = PodDBAdapter.getInstance();
    adapter.open();
    try {
        FeedItem nextItem = null;
        try (Cursor cursor = adapter.getNextInQueue(item)) {
            List<FeedItem> list = extractItemlistFromCursor(adapter, cursor);
            if (!list.isEmpty()) {
                nextItem = list.get(0);
                loadAdditionalFeedItemListData(list);
            }
            return nextItem;
        } catch (Exception e) {
            return null;
        }
    } finally {
        adapter.close();
    }
}
Also used : FeedItem(de.danoeh.antennapod.model.feed.FeedItem) Cursor(android.database.Cursor) Nullable(androidx.annotation.Nullable)

Example 23 with FeedItem

use of de.danoeh.antennapod.model.feed.FeedItem in project AntennaPod by AntennaPod.

the class DBTasks method enqueueFeedItemsToDownload.

public static List<FeedItem> enqueueFeedItemsToDownload(final Context context, List<FeedItem> items) throws InterruptedException, ExecutionException {
    List<FeedItem> itemsToEnqueue = new ArrayList<>();
    if (UserPreferences.enqueueDownloadedEpisodes()) {
        LongList queueIDList = DBReader.getQueueIDList();
        for (FeedItem item : items) {
            if (!queueIDList.contains(item.getId())) {
                itemsToEnqueue.add(item);
            }
        }
        DBWriter.addQueueItem(context, false, itemsToEnqueue.toArray(new FeedItem[0])).get();
    }
    return itemsToEnqueue;
}
Also used : FeedItem(de.danoeh.antennapod.model.feed.FeedItem) ArrayList(java.util.ArrayList) LongList(de.danoeh.antennapod.core.util.LongList)

Example 24 with FeedItem

use of de.danoeh.antennapod.model.feed.FeedItem in project AntennaPod by AntennaPod.

the class DBTasks method updateFeed.

/**
 * Adds new Feeds to the database or updates the old versions if they already exists. If another Feed with the same
 * identifying value already exists, this method will add new FeedItems from the new Feed to the existing Feed.
 * These FeedItems will be marked as unread with the exception of the most recent FeedItem.
 * <p/>
 * This method can update multiple feeds at once. Submitting a feed twice in the same method call can result in undefined behavior.
 * <p/>
 * This method should NOT be executed on the GUI thread.
 *
 * @param context Used for accessing the DB.
 * @param newFeed The new Feed object.
 * @param removeUnlistedItems The item list in the new Feed object is considered to be exhaustive.
 *                            I.e. items are removed from the database if they are not in this item list.
 * @return The updated Feed from the database if it already existed, or the new Feed from the parameters otherwise.
 */
public static synchronized Feed updateFeed(Context context, Feed newFeed, boolean removeUnlistedItems) {
    Feed resultFeed;
    List<FeedItem> unlistedItems = new ArrayList<>();
    PodDBAdapter adapter = PodDBAdapter.getInstance();
    adapter.open();
    // Look up feed in the feedslist
    final Feed savedFeed = searchFeedByIdentifyingValueOrID(adapter, newFeed);
    if (savedFeed == null) {
        Log.d(TAG, "Found no existing Feed with title " + newFeed.getTitle() + ". Adding as new one.");
        // Add a new Feed
        // all new feeds will have the most recent item marked as unplayed
        FeedItem mostRecent = newFeed.getMostRecentItem();
        if (mostRecent != null) {
            mostRecent.setNew();
        }
        resultFeed = newFeed;
    } else {
        Log.d(TAG, "Feed with title " + newFeed.getTitle() + " already exists. Syncing new with existing one.");
        Collections.sort(newFeed.getItems(), new FeedItemPubdateComparator());
        if (newFeed.getPageNr() == savedFeed.getPageNr()) {
            if (savedFeed.compareWithOther(newFeed)) {
                Log.d(TAG, "Feed has updated attribute values. Updating old feed's attributes");
                savedFeed.updateFromOther(newFeed);
            }
        } else {
            Log.d(TAG, "New feed has a higher page number.");
            savedFeed.setNextPageLink(newFeed.getNextPageLink());
        }
        if (savedFeed.getPreferences().compareWithOther(newFeed.getPreferences())) {
            Log.d(TAG, "Feed has updated preferences. Updating old feed's preferences");
            savedFeed.getPreferences().updateFromOther(newFeed.getPreferences());
        }
        // get the most recent date now, before we start changing the list
        FeedItem priorMostRecent = savedFeed.getMostRecentItem();
        Date priorMostRecentDate = null;
        if (priorMostRecent != null) {
            priorMostRecentDate = priorMostRecent.getPubDate();
        }
        // Look for new or updated Items
        for (int idx = 0; idx < newFeed.getItems().size(); idx++) {
            final FeedItem item = newFeed.getItems().get(idx);
            FeedItem possibleDuplicate = searchFeedItemGuessDuplicate(newFeed.getItems(), item);
            if (!newFeed.isLocalFeed() && possibleDuplicate != null && item != possibleDuplicate) {
                // Canonical episode is the first one returned (usually oldest)
                DBWriter.addDownloadStatus(new DownloadStatus(savedFeed, item.getTitle(), DownloadError.ERROR_PARSER_EXCEPTION_DUPLICATE, false, "The podcast host appears to have added the same episode twice. " + "AntennaPod still refreshed the feed and attempted to repair it." + "\n\nOriginal episode:\n" + duplicateEpisodeDetails(item) + "\n\nSecond episode that is also in the feed:\n" + duplicateEpisodeDetails(possibleDuplicate), false));
                continue;
            }
            FeedItem oldItem = searchFeedItemByIdentifyingValue(savedFeed.getItems(), item);
            if (!newFeed.isLocalFeed() && oldItem == null) {
                oldItem = searchFeedItemGuessDuplicate(savedFeed.getItems(), item);
                if (oldItem != null) {
                    Log.d(TAG, "Repaired duplicate: " + oldItem + ", " + item);
                    DBWriter.addDownloadStatus(new DownloadStatus(savedFeed, item.getTitle(), DownloadError.ERROR_PARSER_EXCEPTION_DUPLICATE, false, "The podcast host changed the ID of an existing episode instead of just " + "updating the episode itself. AntennaPod still refreshed the feed and " + "attempted to repair it." + "\n\nOriginal episode:\n" + duplicateEpisodeDetails(oldItem) + "\n\nNow the feed contains:\n" + duplicateEpisodeDetails(item), false));
                    oldItem.setItemIdentifier(item.getItemIdentifier());
                    if (oldItem.isPlayed() && oldItem.getMedia() != null) {
                        EpisodeAction action = new EpisodeAction.Builder(oldItem, EpisodeAction.PLAY).currentTimestamp().started(oldItem.getMedia().getDuration() / 1000).position(oldItem.getMedia().getDuration() / 1000).total(oldItem.getMedia().getDuration() / 1000).build();
                        SynchronizationQueueSink.enqueueEpisodeActionIfSynchronizationIsActive(context, action);
                    }
                }
            }
            if (oldItem != null) {
                oldItem.updateFromOther(item);
            } else {
                // item is new
                item.setFeed(savedFeed);
                if (idx >= savedFeed.getItems().size()) {
                    savedFeed.getItems().add(item);
                } else {
                    savedFeed.getItems().add(idx, item);
                }
                // New items that do not have a pubDate set are always marked as new
                if (item.getPubDate() == null || priorMostRecentDate == null || priorMostRecentDate.before(item.getPubDate()) || priorMostRecentDate.equals(item.getPubDate())) {
                    Log.d(TAG, "Marking item published on " + item.getPubDate() + " new, prior most recent date = " + priorMostRecentDate);
                    item.setNew();
                }
            }
        }
        // identify items to be removed
        if (removeUnlistedItems) {
            Iterator<FeedItem> it = savedFeed.getItems().iterator();
            while (it.hasNext()) {
                FeedItem feedItem = it.next();
                if (searchFeedItemByIdentifyingValue(newFeed.getItems(), feedItem) == null) {
                    unlistedItems.add(feedItem);
                    it.remove();
                }
            }
        }
        // update attributes
        savedFeed.setLastUpdate(newFeed.getLastUpdate());
        savedFeed.setType(newFeed.getType());
        savedFeed.setLastUpdateFailed(false);
        resultFeed = savedFeed;
    }
    try {
        if (savedFeed == null) {
            DBWriter.addNewFeed(context, newFeed).get();
            // Update with default values that are set in database
            resultFeed = searchFeedByIdentifyingValueOrID(adapter, newFeed);
        } else {
            DBWriter.setCompleteFeed(savedFeed).get();
        }
        if (removeUnlistedItems) {
            DBWriter.deleteFeedItems(context, unlistedItems).get();
        }
    } catch (InterruptedException | ExecutionException e) {
        e.printStackTrace();
    }
    adapter.close();
    if (savedFeed != null) {
        EventBus.getDefault().post(new FeedListUpdateEvent(savedFeed));
    } else {
        EventBus.getDefault().post(new FeedListUpdateEvent(Collections.emptyList()));
    }
    return resultFeed;
}
Also used : ArrayList(java.util.ArrayList) Date(java.util.Date) EpisodeAction(de.danoeh.antennapod.net.sync.model.EpisodeAction) FeedItemPubdateComparator(de.danoeh.antennapod.core.util.comparator.FeedItemPubdateComparator) FeedItem(de.danoeh.antennapod.model.feed.FeedItem) DownloadStatus(de.danoeh.antennapod.core.service.download.DownloadStatus) ExecutionException(java.util.concurrent.ExecutionException) FeedListUpdateEvent(de.danoeh.antennapod.event.FeedListUpdateEvent) Feed(de.danoeh.antennapod.model.feed.Feed)

Example 25 with FeedItem

use of de.danoeh.antennapod.model.feed.FeedItem in project AntennaPod by AntennaPod.

the class DBWriter method addQueueItem.

/**
 * Appends FeedItem objects to the end of the queue. The 'read'-attribute of all items will be set to true.
 * If a FeedItem is already in the queue, the FeedItem will not change its position in the queue.
 *
 * @param context             A context that is used for opening a database connection.
 * @param performAutoDownload true if an auto-download process should be started after the operation.
 * @param markAsUnplayed      true if the items should be marked as unplayed when enqueueing
 * @param itemIds             IDs of the FeedItem objects that should be added to the queue.
 */
public static Future<?> addQueueItem(final Context context, final boolean performAutoDownload, final boolean markAsUnplayed, final long... itemIds) {
    return dbExec.submit(() -> {
        if (itemIds.length < 1) {
            return;
        }
        final PodDBAdapter adapter = PodDBAdapter.getInstance();
        adapter.open();
        final List<FeedItem> queue = DBReader.getQueue(adapter);
        boolean queueModified = false;
        LongList markAsUnplayedIds = new LongList();
        List<QueueEvent> events = new ArrayList<>();
        List<FeedItem> updatedItems = new ArrayList<>();
        ItemEnqueuePositionCalculator positionCalculator = new ItemEnqueuePositionCalculator(UserPreferences.getEnqueueLocation());
        Playable currentlyPlaying = PlayableUtils.createInstanceFromPreferences(context);
        int insertPosition = positionCalculator.calcPosition(queue, currentlyPlaying);
        for (long itemId : itemIds) {
            if (!itemListContains(queue, itemId)) {
                final FeedItem item = DBReader.getFeedItem(itemId);
                if (item != null) {
                    queue.add(insertPosition, item);
                    events.add(QueueEvent.added(item, insertPosition));
                    item.addTag(FeedItem.TAG_QUEUE);
                    updatedItems.add(item);
                    queueModified = true;
                    if (item.isNew()) {
                        markAsUnplayedIds.add(item.getId());
                    }
                    insertPosition++;
                }
            }
        }
        if (queueModified) {
            applySortOrder(queue, events);
            adapter.setQueue(queue);
            for (QueueEvent event : events) {
                EventBus.getDefault().post(event);
            }
            EventBus.getDefault().post(FeedItemEvent.updated(updatedItems));
            if (markAsUnplayed && markAsUnplayedIds.size() > 0) {
                DBWriter.markItemPlayed(FeedItem.UNPLAYED, markAsUnplayedIds.toArray());
            }
        }
        adapter.close();
        if (performAutoDownload) {
            DBTasks.autodownloadUndownloadedItems(context);
        }
    });
}
Also used : FeedItem(de.danoeh.antennapod.model.feed.FeedItem) Playable(de.danoeh.antennapod.model.playback.Playable) ArrayList(java.util.ArrayList) QueueEvent(de.danoeh.antennapod.event.QueueEvent) LongList(de.danoeh.antennapod.core.util.LongList)

Aggregations

FeedItem (de.danoeh.antennapod.model.feed.FeedItem)178 Feed (de.danoeh.antennapod.model.feed.Feed)74 Test (org.junit.Test)64 ArrayList (java.util.ArrayList)48 Date (java.util.Date)47 FeedMedia (de.danoeh.antennapod.model.feed.FeedMedia)46 File (java.io.File)26 Cursor (android.database.Cursor)20 NonNull (androidx.annotation.NonNull)15 Nullable (androidx.annotation.Nullable)11 Subscribe (org.greenrobot.eventbus.Subscribe)9 Intent (android.content.Intent)7 FeedFilter (de.danoeh.antennapod.model.feed.FeedFilter)7 View (android.view.View)6 LongList (de.danoeh.antennapod.core.util.LongList)6 SQLException (android.database.SQLException)5 Playable (de.danoeh.antennapod.model.playback.Playable)5 EpisodeAction (de.danoeh.antennapod.net.sync.model.EpisodeAction)5 ExecutionException (java.util.concurrent.ExecutionException)5 FeedItemPubdateComparator (de.danoeh.antennapod.core.util.comparator.FeedItemPubdateComparator)4