diff options
Diffstat (limited to 'core/src/main/java/de/danoeh')
7 files changed, 119 insertions, 44 deletions
diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/ChapterMerger.java b/core/src/main/java/de/danoeh/antennapod/core/feed/ChapterMerger.java new file mode 100644 index 000000000..f33fa7511 --- /dev/null +++ b/core/src/main/java/de/danoeh/antennapod/core/feed/ChapterMerger.java @@ -0,0 +1,55 @@ +package de.danoeh.antennapod.core.feed; + +import android.text.TextUtils; +import android.util.Log; +import androidx.annotation.Nullable; + +import java.util.List; + +public class ChapterMerger { + private static final String TAG = "ChapterMerger"; + + private ChapterMerger() { + + } + + /** + * This method might modify the input data. + */ + @Nullable + public static List<Chapter> merge(@Nullable List<Chapter> chapters1, @Nullable List<Chapter> chapters2) { + Log.d(TAG, "Merging chapters"); + if (chapters1 == null) { + return chapters2; + } else if (chapters2 == null) { + return chapters1; + } else if (chapters2.size() > chapters1.size()) { + return chapters2; + } else if (chapters2.size() < chapters1.size()) { + return chapters1; + } else { + // Merge chapter lists of same length. Store in chapters2 array. + // In case the lists can not be merged, return chapters1 array. + for (int i = 0; i < chapters2.size(); i++) { + Chapter chapterTarget = chapters2.get(i); + Chapter chapterOther = chapters1.get(i); + + if (Math.abs(chapterTarget.start - chapterOther.start) > 1000) { + Log.e(TAG, "Chapter lists are too different. Cancelling merge."); + return chapters1; + } + + if (TextUtils.isEmpty(chapterTarget.imageUrl)) { + chapterTarget.imageUrl = chapterOther.imageUrl; + } + if (TextUtils.isEmpty(chapterTarget.link)) { + chapterTarget.link = chapterOther.link; + } + if (TextUtils.isEmpty(chapterTarget.title)) { + chapterTarget.title = chapterOther.title; + } + } + return chapters2; + } + } +} diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedMedia.java b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedMedia.java index d1c90cfa7..3d2d7f528 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedMedia.java +++ b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedMedia.java @@ -11,6 +11,7 @@ import androidx.annotation.Nullable; import android.support.v4.media.MediaBrowserCompat; import android.support.v4.media.MediaDescriptionCompat; +import java.util.Collections; import java.util.Date; import java.util.List; import java.util.concurrent.Callable; @@ -382,19 +383,30 @@ public class FeedMedia extends FeedFile implements Playable { if (item == null || item.getChapters() != null) { return; } - // check if chapters are stored in db and not loaded yet. + + List<Chapter> chapters = loadChapters(); + if (chapters == null) { + // Do not try loading again. There are no chapters. + item.setChapters(Collections.emptyList()); + } else { + item.setChapters(chapters); + } + } + + private List<Chapter> loadChapters() { + List<Chapter> chaptersFromDatabase = null; if (item.hasChapters()) { - DBReader.loadChaptersOfFeedItem(item); + chaptersFromDatabase = DBReader.loadChaptersOfFeedItem(item); + } + + List<Chapter> chaptersFromMediaFile; + if (localFileAvailable()) { + chaptersFromMediaFile = ChapterUtils.loadChaptersFromFileUrl(this); } else { - if(localFileAvailable()) { - ChapterUtils.loadChaptersFromFileUrl(this); - } else { - ChapterUtils.loadChaptersFromStreamUrl(this); - } - if (item.getChapters() != null) { - DBWriter.setFeedItem(item); - } + chaptersFromMediaFile = ChapterUtils.loadChaptersFromStreamUrl(this); } + + return ChapterMerger.merge(chaptersFromDatabase, chaptersFromMediaFile); } @Override diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/download/handler/MediaDownloadedHandler.java b/core/src/main/java/de/danoeh/antennapod/core/service/download/handler/MediaDownloadedHandler.java index 9e2b69810..501214399 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/download/handler/MediaDownloadedHandler.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/download/handler/MediaDownloadedHandler.java @@ -56,7 +56,7 @@ public class MediaDownloadedHandler implements Runnable { // check if file has chapters if (media.getItem() != null && !media.getItem().hasChapters()) { - ChapterUtils.loadChaptersFromFileUrl(media); + media.setChapters(ChapterUtils.loadChaptersFromFileUrl(media)); } // Get duration diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java index 892254507..b218a73f9 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java @@ -651,29 +651,30 @@ public final class DBReader { * * @param item The FeedItem */ - public static void loadChaptersOfFeedItem(final FeedItem item) { + public static List<Chapter> loadChaptersOfFeedItem(final FeedItem item) { Log.d(TAG, "loadChaptersOfFeedItem() called with: " + "item = [" + item + "]"); PodDBAdapter adapter = PodDBAdapter.getInstance(); adapter.open(); try { - loadChaptersOfFeedItem(adapter, item); + return loadChaptersOfFeedItem(adapter, item); } finally { adapter.close(); } } - private static void loadChaptersOfFeedItem(PodDBAdapter adapter, FeedItem item) { + private static List<Chapter> loadChaptersOfFeedItem(PodDBAdapter adapter, FeedItem item) { try (Cursor cursor = adapter.getSimpleChaptersOfFeedItemCursor(item)) { int chaptersCount = cursor.getCount(); if (chaptersCount == 0) { item.setChapters(null); - return; + return null; } - item.setChapters(new ArrayList<>(chaptersCount)); + ArrayList<Chapter> chapters = new ArrayList<>(); while (cursor.moveToNext()) { - item.getChapters().add(Chapter.fromCursor(cursor)); + chapters.add(Chapter.fromCursor(cursor)); } + return chapters; } } diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/ChapterUtils.java b/core/src/main/java/de/danoeh/antennapod/core/util/ChapterUtils.java index 737f902b7..c24c3b8e7 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/ChapterUtils.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/ChapterUtils.java @@ -52,32 +52,34 @@ public class ChapterUtils { return chapters.size() - 1; } - public static void loadChaptersFromStreamUrl(Playable media) { - ChapterUtils.readID3ChaptersFromPlayableStreamUrl(media); - if (media.getChapters() == null) { - ChapterUtils.readOggChaptersFromPlayableStreamUrl(media); + public static List<Chapter> loadChaptersFromStreamUrl(Playable media) { + List<Chapter> chapters = ChapterUtils.readID3ChaptersFromPlayableStreamUrl(media); + if (chapters == null) { + chapters = ChapterUtils.readOggChaptersFromPlayableStreamUrl(media); } + return chapters; } - public static void loadChaptersFromFileUrl(Playable media) { + public static List<Chapter> loadChaptersFromFileUrl(Playable media) { if (!media.localFileAvailable()) { Log.e(TAG, "Could not load chapters from file url: local file not available"); - return; + return null; } - ChapterUtils.readID3ChaptersFromPlayableFileUrl(media); - if (media.getChapters() == null) { - ChapterUtils.readOggChaptersFromPlayableFileUrl(media); + List<Chapter> chapters = ChapterUtils.readID3ChaptersFromPlayableFileUrl(media); + if (chapters == null) { + chapters = ChapterUtils.readOggChaptersFromPlayableFileUrl(media); } + return chapters; } /** * Uses the download URL of a media object of a feeditem to read its ID3 * chapters. */ - private static void readID3ChaptersFromPlayableStreamUrl(Playable p) { + private static List<Chapter> readID3ChaptersFromPlayableStreamUrl(Playable p) { if (p == null || p.getStreamUrl() == null) { Log.e(TAG, "Unable to read ID3 chapters: media or download URL was null"); - return; + return null; } Log.d(TAG, "Reading id3 chapters from item " + p.getEpisodeTitle()); CountingInputStream in = null; @@ -88,7 +90,7 @@ public class ChapterUtils { in = new CountingInputStream(urlConnection.getInputStream()); List<Chapter> chapters = readChaptersFrom(in); if (!chapters.isEmpty()) { - p.setChapters(chapters); + return chapters; } Log.i(TAG, "Chapters loaded"); } catch (IOException | ID3ReaderException e) { @@ -96,21 +98,22 @@ public class ChapterUtils { } finally { IOUtils.closeQuietly(in); } + return null; } /** * Uses the file URL of a media object of a feeditem to read its ID3 * chapters. */ - private static void readID3ChaptersFromPlayableFileUrl(Playable p) { + private static List<Chapter> readID3ChaptersFromPlayableFileUrl(Playable p) { if (p == null || !p.localFileAvailable() || p.getLocalMediaUrl() == null) { - return; + return null; } Log.d(TAG, "Reading id3 chapters from item " + p.getEpisodeTitle()); File source = new File(p.getLocalMediaUrl()); if (!source.exists()) { Log.e(TAG, "Unable to read id3 chapters: Source doesn't exist"); - return; + return null; } CountingInputStream in = null; @@ -118,7 +121,7 @@ public class ChapterUtils { in = new CountingInputStream(new BufferedInputStream(new FileInputStream(source))); List<Chapter> chapters = readChaptersFrom(in); if (!chapters.isEmpty()) { - p.setChapters(chapters); + return chapters; } Log.i(TAG, "Chapters loaded"); } catch (IOException | ID3ReaderException e) { @@ -126,6 +129,7 @@ public class ChapterUtils { } finally { IOUtils.closeQuietly(in); } + return null; } @NonNull @@ -147,9 +151,9 @@ public class ChapterUtils { return chapters; } - private static void readOggChaptersFromPlayableStreamUrl(Playable media) { + private static List<Chapter> readOggChaptersFromPlayableStreamUrl(Playable media) { if (media == null || !media.streamAvailable()) { - return; + return null; } InputStream input = null; try { @@ -158,34 +162,36 @@ public class ChapterUtils { urlConnection.setRequestProperty("User-Agent", ClientConfig.USER_AGENT); input = urlConnection.getInputStream(); if (input != null) { - readOggChaptersFromInputStream(media, input); + return readOggChaptersFromInputStream(media, input); } } catch (IOException e) { Log.e(TAG, Log.getStackTraceString(e)); } finally { IOUtils.closeQuietly(input); } + return null; } - private static void readOggChaptersFromPlayableFileUrl(Playable media) { + private static List<Chapter> readOggChaptersFromPlayableFileUrl(Playable media) { if (media == null || media.getLocalMediaUrl() == null) { - return; + return null; } File source = new File(media.getLocalMediaUrl()); if (source.exists()) { InputStream input = null; try { input = new BufferedInputStream(new FileInputStream(source)); - readOggChaptersFromInputStream(media, input); + return readOggChaptersFromInputStream(media, input); } catch (FileNotFoundException e) { Log.e(TAG, Log.getStackTraceString(e)); } finally { IOUtils.closeQuietly(input); } } + return null; } - private static void readOggChaptersFromInputStream(Playable p, InputStream input) { + private static List<Chapter> readOggChaptersFromInputStream(Playable p, InputStream input) { Log.d(TAG, "Trying to read chapters from item with title " + p.getEpisodeTitle()); try { VorbisCommentChapterReader reader = new VorbisCommentChapterReader(); @@ -193,19 +199,20 @@ public class ChapterUtils { List<Chapter> chapters = reader.getChapters(); if (chapters == null) { Log.i(TAG, "ChapterReader could not find any Ogg vorbis chapters"); - return; + return null; } Collections.sort(chapters, new ChapterStartTimeComparator()); enumerateEmptyChapterTitles(chapters); if (chaptersValid(chapters)) { - p.setChapters(chapters); Log.i(TAG, "Chapters loaded"); + return chapters; } else { Log.e(TAG, "Chapter data was invalid"); } } catch (VorbisCommentReaderException e) { e.printStackTrace(); } + return null; } /** diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/playback/ExternalMedia.java b/core/src/main/java/de/danoeh/antennapod/core/util/playback/ExternalMedia.java index b55091009..c06003c9d 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/playback/ExternalMedia.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/playback/ExternalMedia.java @@ -99,7 +99,7 @@ public class ExternalMedia implements Playable { e.printStackTrace(); throw new PlayableException("NumberFormatException when reading duration of media file"); } - ChapterUtils.loadChaptersFromFileUrl(this); + setChapters(ChapterUtils.loadChaptersFromFileUrl(this)); } @Override diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/playback/RemoteMedia.java b/core/src/main/java/de/danoeh/antennapod/core/util/playback/RemoteMedia.java index ca09cda4b..2237e99f3 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/playback/RemoteMedia.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/playback/RemoteMedia.java @@ -130,7 +130,7 @@ public class RemoteMedia implements Playable { @Override public void loadChapterMarks() { - ChapterUtils.loadChaptersFromStreamUrl(this); + setChapters(ChapterUtils.loadChaptersFromStreamUrl(this)); } @Override |