From 0bd3b7265203aec5678400341e1b3ede55ba6024 Mon Sep 17 00:00:00 2001 From: Max Bechtold Date: Thu, 27 Jun 2019 19:33:11 +0200 Subject: Mark entry point to allow volume adjustment per feed --- .../danoeh/antennapod/core/service/playback/LocalPSMP.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'core/src') diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java index 9a8353806..9c24e2f76 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java @@ -25,6 +25,8 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.locks.ReentrantLock; +import de.danoeh.antennapod.core.feed.FeedMedia; +import de.danoeh.antennapod.core.feed.FeedPreferences; import de.danoeh.antennapod.core.feed.MediaType; import de.danoeh.antennapod.core.preferences.UserPreferences; import de.danoeh.antennapod.core.util.RewindAfterPauseUtils; @@ -311,6 +313,17 @@ public class LocalPSMP extends PlaybackServiceMediaPlayer { UserPreferences.setPlaybackSpeed(String.valueOf(speed)); } setPlaybackParams(speed, UserPreferences.isSkipSilence()); + // TODO MAX Here and everywhere else volume is adapted + Playable playable = getPlayable(); + if (playable instanceof FeedMedia) { + FeedMedia feedMedia = (FeedMedia) playable; + FeedPreferences preferences = feedMedia.getItem().getFeed().getPreferences(); + + // TODO MAX Check if this feed should have volume adjusted (e.g. louder than others) + + + } + setVolume(UserPreferences.getLeftVolume(), UserPreferences.getRightVolume()); if (playerStatus == PlayerStatus.PREPARED && media.getPosition() > 0) { -- cgit v1.2.3 From c628fdfcfde1960d21cbbd5f3f6eb604827e0d47 Mon Sep 17 00:00:00 2001 From: Max Bechtold Date: Sat, 29 Jun 2019 11:55:59 +0200 Subject: Draft volume reduction settings per feed --- .../java/de/danoeh/antennapod/core/feed/Feed.java | 2 +- .../antennapod/core/feed/FeedPreferences.java | 28 +++++++++++++--- .../core/service/download/DownloadService.java | 2 +- .../core/service/playback/LocalPSMP.java | 37 +++++++++++++++------- .../danoeh/antennapod/core/storage/DBUpgrader.java | 1 + .../antennapod/core/storage/PodDBAdapter.java | 6 +++- core/src/main/res/values/arrays.xml | 12 +++++++ core/src/main/res/values/strings.xml | 4 +++ 8 files changed, 73 insertions(+), 19 deletions(-) (limited to 'core/src') diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/Feed.java b/core/src/main/java/de/danoeh/antennapod/core/feed/Feed.java index 5718c06c2..e01c35d0e 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/feed/Feed.java +++ b/core/src/main/java/de/danoeh/antennapod/core/feed/Feed.java @@ -160,7 +160,7 @@ public class Feed extends FeedFile implements ImageResource { */ public Feed(String url, String lastUpdate, String title, String username, String password) { this(url, lastUpdate, title); - preferences = new FeedPreferences(0, true, FeedPreferences.AutoDeleteAction.GLOBAL, username, password); + preferences = new FeedPreferences(0, true, FeedPreferences.AutoDeleteAction.GLOBAL, FeedPreferences.VolumeReductionSetting.OFF, username, password); } public static Feed fromCursor(Cursor cursor) { diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedPreferences.java b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedPreferences.java index 3285ad7cb..62fb28100 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedPreferences.java +++ b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedPreferences.java @@ -26,18 +26,27 @@ public class FeedPreferences { NO } private AutoDeleteAction auto_delete_action; + + public enum VolumeReductionSetting { + OFF, + LIGHT, + HEAVY + } + private VolumeReductionSetting volumeReductionSetting; + private String username; private String password; - public FeedPreferences(long feedID, boolean autoDownload, AutoDeleteAction auto_delete_action, String username, String password) { - this(feedID, autoDownload, true, auto_delete_action, username, password, new FeedFilter()); + public FeedPreferences(long feedID, boolean autoDownload, AutoDeleteAction auto_delete_action, VolumeReductionSetting volumeReductionSetting, String username, String password) { + this(feedID, autoDownload, true, auto_delete_action, volumeReductionSetting, username, password, new FeedFilter()); } - private FeedPreferences(long feedID, boolean autoDownload, boolean keepUpdated, AutoDeleteAction auto_delete_action, String username, String password, @NonNull FeedFilter filter) { + private FeedPreferences(long feedID, boolean autoDownload, boolean keepUpdated, AutoDeleteAction auto_delete_action, VolumeReductionSetting volumeReductionSetting, String username, String password, @NonNull FeedFilter filter) { this.feedID = feedID; this.autoDownload = autoDownload; this.keepUpdated = keepUpdated; this.auto_delete_action = auto_delete_action; + this.volumeReductionSetting = volumeReductionSetting; this.username = username; this.password = password; this.filter = filter; @@ -48,6 +57,7 @@ public class FeedPreferences { int indexAutoDownload = cursor.getColumnIndex(PodDBAdapter.KEY_AUTO_DOWNLOAD); int indexAutoRefresh = cursor.getColumnIndex(PodDBAdapter.KEY_KEEP_UPDATED); int indexAutoDeleteAction = cursor.getColumnIndex(PodDBAdapter.KEY_AUTO_DELETE_ACTION); + int indexVolumeReduction = cursor.getColumnIndex(PodDBAdapter.KEY_FEED_VOLUME_REDUCTION); int indexUsername = cursor.getColumnIndex(PodDBAdapter.KEY_USERNAME); int indexPassword = cursor.getColumnIndex(PodDBAdapter.KEY_PASSWORD); int indexIncludeFilter = cursor.getColumnIndex(PodDBAdapter.KEY_INCLUDE_FILTER); @@ -58,11 +68,13 @@ public class FeedPreferences { boolean autoRefresh = cursor.getInt(indexAutoRefresh) > 0; int autoDeleteActionIndex = cursor.getInt(indexAutoDeleteAction); AutoDeleteAction autoDeleteAction = AutoDeleteAction.values()[autoDeleteActionIndex]; + int volumeReductionIndex = cursor.getInt(indexVolumeReduction); + VolumeReductionSetting volumeReductionSetting = VolumeReductionSetting.values()[volumeReductionIndex]; String username = cursor.getString(indexUsername); String password = cursor.getString(indexPassword); String includeFilter = cursor.getString(indexIncludeFilter); String excludeFilter = cursor.getString(indexExcludeFilter); - return new FeedPreferences(feedId, autoDownload, autoRefresh, autoDeleteAction, username, password, new FeedFilter(includeFilter, excludeFilter)); + return new FeedPreferences(feedId, autoDownload, autoRefresh, autoDeleteAction, volumeReductionSetting, username, password, new FeedFilter(includeFilter, excludeFilter)); } /** @@ -138,10 +150,18 @@ public class FeedPreferences { return auto_delete_action; } + public VolumeReductionSetting getVolumeReductionSetting() { + return volumeReductionSetting; + } + public void setAutoDeleteAction(AutoDeleteAction auto_delete_action) { this.auto_delete_action = auto_delete_action; } + public void setVolumeReductionSetting(VolumeReductionSetting volumeReductionSetting) { + this.volumeReductionSetting = volumeReductionSetting; + } + public boolean getCurrentAutoDelete() { switch (auto_delete_action) { case GLOBAL: diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java b/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java index 787d465d8..1b94bb3c3 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java @@ -764,7 +764,7 @@ public class DownloadService extends Service { feed.setId(request.getFeedfileId()); feed.setDownloaded(true); feed.setPreferences(new FeedPreferences(0, true, FeedPreferences.AutoDeleteAction.GLOBAL, - request.getUsername(), request.getPassword())); + FeedPreferences.VolumeReductionSetting.OFF, request.getUsername(), request.getPassword())); feed.setPageNr(request.getArguments().getInt(DownloadRequester.REQUEST_ARG_PAGE_NR, 0)); DownloadError reason = null; diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java index 9c24e2f76..03704229b 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java @@ -313,18 +313,10 @@ public class LocalPSMP extends PlaybackServiceMediaPlayer { UserPreferences.setPlaybackSpeed(String.valueOf(speed)); } setPlaybackParams(speed, UserPreferences.isSkipSilence()); - // TODO MAX Here and everywhere else volume is adapted - Playable playable = getPlayable(); - if (playable instanceof FeedMedia) { - FeedMedia feedMedia = (FeedMedia) playable; - FeedPreferences preferences = feedMedia.getItem().getFeed().getPreferences(); - // TODO MAX Check if this feed should have volume adjusted (e.g. louder than others) - - - } - - setVolume(UserPreferences.getLeftVolume(), UserPreferences.getRightVolume()); + float leftVolume = UserPreferences.getLeftVolume(); + float rightVolume = UserPreferences.getRightVolume(); + setVolume(leftVolume, rightVolume); if (playerStatus == PlayerStatus.PREPARED && media.getPosition() > 0) { int newPosition = RewindAfterPauseUtils.calculatePositionWithRewind( @@ -344,8 +336,25 @@ public class LocalPSMP extends PlaybackServiceMediaPlayer { } } + private float getVolumeReductionFactor() { + Playable playable = getPlayable(); + if (playable instanceof FeedMedia) { + FeedMedia feedMedia = (FeedMedia) playable; + FeedPreferences preferences = feedMedia.getItem().getFeed().getPreferences(); + FeedPreferences.VolumeReductionSetting volumeReductionSetting = preferences.getVolumeReductionSetting(); + + // TODO maxbechtold These numbers should be tested + if (volumeReductionSetting == FeedPreferences.VolumeReductionSetting.LIGHT) { + return 0.4f; + } else if (volumeReductionSetting == FeedPreferences.VolumeReductionSetting.HEAVY) { + return 0.2f; + } + } + return 1.0f; + } + - /** + /** * Saves the current position and pauses playback. Note that, if audiofocus * is abandoned, the lockscreen controls will also disapear. *

@@ -681,6 +690,10 @@ public class LocalPSMP extends PlaybackServiceMediaPlayer { private void setVolumeSync(float volumeLeft, float volumeRight) { playerLock.lock(); if (media != null && media.getMediaType() == MediaType.AUDIO) { + // TODO maxbechtold does not apply to currently playing episode + float reductionFactor = getVolumeReductionFactor(); + volumeLeft *= reductionFactor; + volumeRight *= reductionFactor; mediaPlayer.setVolume(volumeLeft, volumeRight); Log.d(TAG, "Media player volume was set to " + volumeLeft + " " + volumeRight); } diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DBUpgrader.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DBUpgrader.java index 306f8d104..1f6b430e0 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/DBUpgrader.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DBUpgrader.java @@ -193,6 +193,7 @@ class DBUpgrader { db.execSQL(sql); } if (oldVersion <= 17) { + // TODO maxbechtold Something like this for volume reduction db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS + " ADD COLUMN " + PodDBAdapter.KEY_AUTO_DELETE_ACTION + " INTEGER DEFAULT 0"); } diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java b/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java index f7956372b..5fe18c3b4 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java @@ -103,6 +103,7 @@ public class PodDBAdapter { public static final String KEY_AUTO_DOWNLOAD = "auto_download"; public static final String KEY_KEEP_UPDATED = "keep_updated"; public static final String KEY_AUTO_DELETE_ACTION = "auto_delete_action"; + public static final String KEY_FEED_VOLUME_REDUCTION = "feed_volume_reduction"; public static final String KEY_PLAYED_DURATION = "played_duration"; public static final String KEY_USERNAME = "username"; public static final String KEY_PASSWORD = "password"; @@ -146,7 +147,8 @@ public class PodDBAdapter { + KEY_NEXT_PAGE_LINK + " TEXT," + KEY_HIDE + " TEXT," + KEY_LAST_UPDATE_FAILED + " INTEGER DEFAULT 0," - + KEY_AUTO_DELETE_ACTION + " INTEGER DEFAULT 0)"; + + KEY_AUTO_DELETE_ACTION + " INTEGER DEFAULT 0," + + KEY_FEED_VOLUME_REDUCTION + " INTEGER DEFAULT 0)"; private static final String CREATE_TABLE_FEED_ITEMS = "CREATE TABLE " + TABLE_NAME_FEED_ITEMS + " (" + TABLE_PRIMARY_KEY + KEY_TITLE @@ -242,6 +244,7 @@ public class PodDBAdapter { TABLE_NAME_FEEDS + "." + KEY_HIDE, TABLE_NAME_FEEDS + "." + KEY_LAST_UPDATE_FAILED, TABLE_NAME_FEEDS + "." + KEY_AUTO_DELETE_ACTION, + TABLE_NAME_FEEDS + "." + KEY_FEED_VOLUME_REDUCTION, TABLE_NAME_FEEDS + "." + KEY_INCLUDE_FILTER, TABLE_NAME_FEEDS + "." + KEY_EXCLUDE_FILTER }; @@ -404,6 +407,7 @@ public class PodDBAdapter { values.put(KEY_AUTO_DOWNLOAD, prefs.getAutoDownload()); values.put(KEY_KEEP_UPDATED, prefs.getKeepUpdated()); values.put(KEY_AUTO_DELETE_ACTION, prefs.getAutoDeleteAction().ordinal()); + values.put(KEY_FEED_VOLUME_REDUCTION, prefs.getVolumeReductionSetting().ordinal()); values.put(KEY_USERNAME, prefs.getUsername()); values.put(KEY_PASSWORD, prefs.getPassword()); values.put(KEY_INCLUDE_FILTER, prefs.getFilter().getIncludeFilter()); diff --git a/core/src/main/res/values/arrays.xml b/core/src/main/res/values/arrays.xml index 0eaf0e5e7..8190a39e2 100644 --- a/core/src/main/res/values/arrays.xml +++ b/core/src/main/res/values/arrays.xml @@ -13,6 +13,18 @@ never + + @string/feed_volume_reduction_off + @string/feed_volume_reduction_light + @string/feed_volume_reduction_heavy + + + + off + light + heavy + + 0 15 diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index a4084b76b..717d2302d 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -97,6 +97,10 @@ Apply to Previous Episodes The new Auto Download setting will automatically be applied to new episodes.\nDo you also want to apply it to previously published episodes? Auto Delete Episode + Volume Reduction + Off + Light + Heavy \u0020parallel downloads Global default Always -- cgit v1.2.3 From cd7f0245a51d11409fba012664bd1e63a1d86f68 Mon Sep 17 00:00:00 2001 From: Max Bechtold Date: Fri, 5 Jul 2019 13:36:13 +0200 Subject: #3248 Slightly lessen light reduction --- .../java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'core/src') diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java index 03704229b..b4cd4b0d9 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java @@ -343,9 +343,10 @@ public class LocalPSMP extends PlaybackServiceMediaPlayer { FeedPreferences preferences = feedMedia.getItem().getFeed().getPreferences(); FeedPreferences.VolumeReductionSetting volumeReductionSetting = preferences.getVolumeReductionSetting(); + // TODO maxbechtold Move this logic out of this class // TODO maxbechtold These numbers should be tested if (volumeReductionSetting == FeedPreferences.VolumeReductionSetting.LIGHT) { - return 0.4f; + return 0.5f; } else if (volumeReductionSetting == FeedPreferences.VolumeReductionSetting.HEAVY) { return 0.2f; } -- cgit v1.2.3 From 03074168ce7432d8c439e87241d151e6dbbc9bd6 Mon Sep 17 00:00:00 2001 From: Max Bechtold Date: Sun, 7 Jul 2019 11:42:52 +0200 Subject: #3248 Add unit test --- .../core/service/playback/FeedVolumeReduction.java | 16 +++++++++ .../core/service/playback/LocalPSMP.java | 39 ++++++++-------------- .../service/playback/FeedVolumeReductionTest.java | 35 +++++++++++++++++++ 3 files changed, 65 insertions(+), 25 deletions(-) create mode 100644 core/src/main/java/de/danoeh/antennapod/core/service/playback/FeedVolumeReduction.java create mode 100644 core/src/test/java/de/danoeh/antennapod/core/service/playback/FeedVolumeReductionTest.java (limited to 'core/src') diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/FeedVolumeReduction.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/FeedVolumeReduction.java new file mode 100644 index 000000000..c9e10efc3 --- /dev/null +++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/FeedVolumeReduction.java @@ -0,0 +1,16 @@ +package de.danoeh.antennapod.core.service.playback; + +import de.danoeh.antennapod.core.feed.FeedPreferences; + +public class FeedVolumeReduction { + float getReductionFactor(FeedPreferences preferences) { + FeedPreferences.VolumeReductionSetting volumeReductionSetting = preferences.getVolumeReductionSetting(); + // TODO maxbechtold These numbers should be tested + if (volumeReductionSetting == FeedPreferences.VolumeReductionSetting.LIGHT) { + return 0.5f; + } else if (volumeReductionSetting == FeedPreferences.VolumeReductionSetting.HEAVY) { + return 0.2f; + } + return 1.0f; + } +} diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java index b4cd4b0d9..5153dcddb 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java @@ -12,6 +12,8 @@ import android.util.Log; import android.util.Pair; import android.view.SurfaceHolder; +import de.danoeh.antennapod.core.feed.FeedMedia; +import de.danoeh.antennapod.core.feed.FeedPreferences; import org.antennapod.audio.MediaPlayer; import java.io.File; @@ -25,8 +27,6 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.locks.ReentrantLock; -import de.danoeh.antennapod.core.feed.FeedMedia; -import de.danoeh.antennapod.core.feed.FeedPreferences; import de.danoeh.antennapod.core.feed.MediaType; import de.danoeh.antennapod.core.preferences.UserPreferences; import de.danoeh.antennapod.core.util.RewindAfterPauseUtils; @@ -53,6 +53,8 @@ public class LocalPSMP extends PlaybackServiceMediaPlayer { private volatile boolean pausedBecauseOfTransientAudiofocusLoss; private volatile Pair videoSize; + private final FeedVolumeReduction feedVolumeReduction; + /** * Some asynchronous calls might change the state of the MediaPlayer object. Therefore calls in other threads * have to wait until these operations have finished. @@ -138,6 +140,7 @@ public class LocalPSMP extends PlaybackServiceMediaPlayer { super(context, callback); this.audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); this.playerLock = new PlayerLock(); + this.feedVolumeReduction = new FeedVolumeReduction(); this.startWhenPrepared = new AtomicBoolean(false); executor = new PlayerExecutor(); @@ -336,26 +339,8 @@ public class LocalPSMP extends PlaybackServiceMediaPlayer { } } - private float getVolumeReductionFactor() { - Playable playable = getPlayable(); - if (playable instanceof FeedMedia) { - FeedMedia feedMedia = (FeedMedia) playable; - FeedPreferences preferences = feedMedia.getItem().getFeed().getPreferences(); - FeedPreferences.VolumeReductionSetting volumeReductionSetting = preferences.getVolumeReductionSetting(); - - // TODO maxbechtold Move this logic out of this class - // TODO maxbechtold These numbers should be tested - if (volumeReductionSetting == FeedPreferences.VolumeReductionSetting.LIGHT) { - return 0.5f; - } else if (volumeReductionSetting == FeedPreferences.VolumeReductionSetting.HEAVY) { - return 0.2f; - } - } - return 1.0f; - } - - /** + /** * Saves the current position and pauses playback. Note that, if audiofocus * is abandoned, the lockscreen controls will also disapear. *

@@ -691,10 +676,14 @@ public class LocalPSMP extends PlaybackServiceMediaPlayer { private void setVolumeSync(float volumeLeft, float volumeRight) { playerLock.lock(); if (media != null && media.getMediaType() == MediaType.AUDIO) { - // TODO maxbechtold does not apply to currently playing episode - float reductionFactor = getVolumeReductionFactor(); - volumeLeft *= reductionFactor; - volumeRight *= reductionFactor; + Playable playable = getPlayable(); + if (playable instanceof FeedMedia) { + FeedMedia feedMedia = (FeedMedia) playable; + FeedPreferences preferences = feedMedia.getItem().getFeed().getPreferences(); + float reductionFactor = feedVolumeReduction.getReductionFactor(preferences); + volumeLeft *= reductionFactor; + volumeRight *= reductionFactor; + } mediaPlayer.setVolume(volumeLeft, volumeRight); Log.d(TAG, "Media player volume was set to " + volumeLeft + " " + volumeRight); } diff --git a/core/src/test/java/de/danoeh/antennapod/core/service/playback/FeedVolumeReductionTest.java b/core/src/test/java/de/danoeh/antennapod/core/service/playback/FeedVolumeReductionTest.java new file mode 100644 index 000000000..e8a2af413 --- /dev/null +++ b/core/src/test/java/de/danoeh/antennapod/core/service/playback/FeedVolumeReductionTest.java @@ -0,0 +1,35 @@ +package de.danoeh.antennapod.core.service.playback; + +import de.danoeh.antennapod.core.feed.FeedPreferences; +import org.junit.Test; + +import static org.junit.Assert.*; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class FeedVolumeReductionTest { + + @Test + public void noReductionIfTurnedOff() { + FeedPreferences feedPreferences = mock(FeedPreferences.class); + when(feedPreferences.getVolumeReductionSetting()).thenReturn(FeedPreferences.VolumeReductionSetting.OFF); + + FeedVolumeReduction feedVolumeReduction = new FeedVolumeReduction(); + float reductionFactor = feedVolumeReduction.getReductionFactor(feedPreferences); + assertEquals(1.0f, reductionFactor, 0.01f ); + } + + @Test + public void lightReductionYieldsHigherValueThanHeavyReduction() { + FeedPreferences feedPreferences = mock(FeedPreferences.class); + FeedVolumeReduction feedVolumeReduction = new FeedVolumeReduction(); + + when(feedPreferences.getVolumeReductionSetting()).thenReturn(FeedPreferences.VolumeReductionSetting.LIGHT); + float lightReductionFactor = feedVolumeReduction.getReductionFactor(feedPreferences); + + when(feedPreferences.getVolumeReductionSetting()).thenReturn(FeedPreferences.VolumeReductionSetting.HEAVY); + float heavyReductionFactor = feedVolumeReduction.getReductionFactor(feedPreferences); + + assertTrue("Light reduction must have higher factor than heavy reduction", lightReductionFactor > heavyReductionFactor); + } +} \ No newline at end of file -- cgit v1.2.3 From fdf7ba25125f132b1e032f58836a62e0f8e92add Mon Sep 17 00:00:00 2001 From: Max Bechtold Date: Sun, 7 Jul 2019 11:55:11 +0200 Subject: #3248 Add migration path --- core/src/main/java/de/danoeh/antennapod/core/storage/DBUpgrader.java | 5 ++++- .../main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) (limited to 'core/src') diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DBUpgrader.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DBUpgrader.java index 1f6b430e0..d9aec8649 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/DBUpgrader.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DBUpgrader.java @@ -193,7 +193,6 @@ class DBUpgrader { db.execSQL(sql); } if (oldVersion <= 17) { - // TODO maxbechtold Something like this for volume reduction db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS + " ADD COLUMN " + PodDBAdapter.KEY_AUTO_DELETE_ACTION + " INTEGER DEFAULT 0"); } @@ -289,6 +288,10 @@ class DBUpgrader { db.execSQL("DROP TABLE " + PodDBAdapter.TABLE_NAME_FEED_IMAGES); } + if (oldVersion < 1070296) { + db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS + + " ADD COLUMN " + PodDBAdapter.KEY_FEED_VOLUME_REDUCTION + " INTEGER DEFAULT 0"); + } } } diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java b/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java index 5fe18c3b4..6f8aaf06e 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java @@ -1456,7 +1456,7 @@ public class PodDBAdapter { */ private static class PodDBHelper extends SQLiteOpenHelper { - private static final int VERSION = 1060596; + private static final int VERSION = 1070296; private final Context context; -- cgit v1.2.3 From 7f0e642069ef3c6cf6844d1a8f0c50d0fbe925f2 Mon Sep 17 00:00:00 2001 From: Max Bechtold Date: Mon, 15 Jul 2019 11:56:06 +0200 Subject: #3248 Review findings --- .../antennapod/core/service/playback/FeedVolumeReductionTest.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'core/src') diff --git a/core/src/test/java/de/danoeh/antennapod/core/service/playback/FeedVolumeReductionTest.java b/core/src/test/java/de/danoeh/antennapod/core/service/playback/FeedVolumeReductionTest.java index e8a2af413..3f2f9d597 100644 --- a/core/src/test/java/de/danoeh/antennapod/core/service/playback/FeedVolumeReductionTest.java +++ b/core/src/test/java/de/danoeh/antennapod/core/service/playback/FeedVolumeReductionTest.java @@ -3,7 +3,8 @@ package de.danoeh.antennapod.core.service.playback; import de.danoeh.antennapod.core.feed.FeedPreferences; import org.junit.Test; -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; -- cgit v1.2.3 From 759ce1b3574587b7045368c1ae476032b8b79942 Mon Sep 17 00:00:00 2001 From: Max Bechtold Date: Sat, 17 Aug 2019 15:46:08 +0200 Subject: #3248 Adapt volume for playing media if its volume reduction setting is changed --- .../service/playback/PlaybackVolumeAdaptor.java | 49 +++++ .../core/service/playback/PlaybackService.java | 28 ++- .../playback/PlaybackVolumeAdaptorTest.java | 230 +++++++++++++++++++++ 3 files changed, 305 insertions(+), 2 deletions(-) create mode 100644 core/src/free/java/de/danoeh/antennapod/core/service/playback/PlaybackVolumeAdaptor.java create mode 100644 core/src/test/java/de/danoeh/antennapod/core/service/playback/PlaybackVolumeAdaptorTest.java (limited to 'core/src') diff --git a/core/src/free/java/de/danoeh/antennapod/core/service/playback/PlaybackVolumeAdaptor.java b/core/src/free/java/de/danoeh/antennapod/core/service/playback/PlaybackVolumeAdaptor.java new file mode 100644 index 000000000..949f8c8cc --- /dev/null +++ b/core/src/free/java/de/danoeh/antennapod/core/service/playback/PlaybackVolumeAdaptor.java @@ -0,0 +1,49 @@ +package de.danoeh.antennapod.core.service.playback; + +import de.danoeh.antennapod.core.feed.FeedMedia; +import de.danoeh.antennapod.core.feed.FeedPreferences; +import de.danoeh.antennapod.core.util.playback.Playable; + +class PlaybackVolumeAdaptor { + + public void adaptVolumeIfNecessary(PlaybackServiceMediaPlayer mediaPlayer, String affectedFeedIdentifier, FeedPreferences.VolumeReductionSetting volumeReductionSetting) { + Playable playable = mediaPlayer.getPlayable(); + boolean isFeedMedia = playable instanceof FeedMedia; + boolean isPlayableLoaded = isPlayableLoaded(mediaPlayer.getPlayerStatus()); + + if (isPlayableLoaded && isFeedMedia) { + adaptFeedMediaVolumeIfNecessary(mediaPlayer, affectedFeedIdentifier, volumeReductionSetting, (FeedMedia) playable); + } + } + + private void adaptFeedMediaVolumeIfNecessary(PlaybackServiceMediaPlayer mediaPlayer, String affectedFeedIdentifier, FeedPreferences.VolumeReductionSetting volumeReductionSetting, FeedMedia feedMedia) { + if (mediaBelongsToAffectedFeed(feedMedia, affectedFeedIdentifier)) { + FeedPreferences preferences = feedMedia.getItem().getFeed().getPreferences(); + preferences.setVolumeReductionSetting(volumeReductionSetting); + + if (mediaPlayer.getPlayerStatus() == PlayerStatus.PLAYING) { + forceAdaptVolume(mediaPlayer); + } + } + } + + private static boolean isPlayableLoaded(PlayerStatus playerStatus) { + return playerStatus == PlayerStatus.PLAYING + || playerStatus == PlayerStatus.PAUSED + || playerStatus == PlayerStatus.SEEKING + || playerStatus == PlayerStatus.PREPARING + || playerStatus == PlayerStatus.PREPARED + || playerStatus == PlayerStatus.INITIALIZING; + } + + private static boolean mediaBelongsToAffectedFeed(FeedMedia feedMedia, String affectedFeedIdentifier) { + return affectedFeedIdentifier != null + && affectedFeedIdentifier.equals(feedMedia.getItem().getFeed().getIdentifyingValue()); + } + + private static void forceAdaptVolume(PlaybackServiceMediaPlayer mediaPlayer) { + mediaPlayer.pause(false, false); + mediaPlayer.resume(); + } + +} diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java index ab1edc8e9..632dfd50e 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java @@ -12,7 +12,6 @@ import android.content.Intent; import android.content.IntentFilter; import android.content.SharedPreferences; import android.graphics.Bitmap; -import android.graphics.BitmapFactory; import android.media.AudioManager; import android.media.MediaPlayer; import android.net.Uri; @@ -43,6 +42,7 @@ import com.bumptech.glide.Glide; import com.bumptech.glide.request.RequestOptions; import com.bumptech.glide.request.target.Target; +import java.io.Serializable; import java.util.ArrayList; import java.util.List; @@ -54,6 +54,7 @@ import de.danoeh.antennapod.core.feed.Chapter; import de.danoeh.antennapod.core.feed.Feed; import de.danoeh.antennapod.core.feed.FeedItem; import de.danoeh.antennapod.core.feed.FeedMedia; +import de.danoeh.antennapod.core.feed.FeedPreferences; import de.danoeh.antennapod.core.feed.MediaType; import de.danoeh.antennapod.core.feed.SearchResult; import de.danoeh.antennapod.core.glide.ApGlideSettings; @@ -66,7 +67,6 @@ import de.danoeh.antennapod.core.storage.DBReader; import de.danoeh.antennapod.core.storage.DBTasks; import de.danoeh.antennapod.core.storage.DBWriter; import de.danoeh.antennapod.core.storage.FeedSearcher; -import de.danoeh.antennapod.core.util.IntList; import de.danoeh.antennapod.core.util.IntentUtils; import de.danoeh.antennapod.core.util.NetworkUtils; import de.danoeh.antennapod.core.util.QueueAccess; @@ -80,6 +80,7 @@ import org.greenrobot.eventbus.EventBus; * Controls the MediaPlayer that plays a FeedMedia-file */ public class PlaybackService extends MediaBrowserServiceCompat { + /** * Logging tag */ @@ -131,6 +132,12 @@ public class PlaybackService extends MediaBrowserServiceCompat { */ public static final String ACTION_PAUSE_PLAY_CURRENT_EPISODE = "action.de.danoeh.antennapod.core.service.pausePlayCurrentEpisode"; + /** + * If the PlaybackService receives this action, it will try to apply the supplied volume reduction setting. + */ + public static final String ACTION_VOLUME_REDUCTION_CHANGED = "action.de.danoeh.antennapod.core.service.volumedReductionChanged"; + public static final String EXTRA_VOLUME_REDUCTION_SETTING = "PlaybackService.VolumeReductionSettingExtra"; + public static final String EXTRA_VOLUME_REDUCTION_AFFECTED_FEED = "PlaybackService.VolumeReductionSettingAffectedFeed"; /** * If the PlaybackService receives this action, it will resume playback. @@ -279,6 +286,7 @@ public class PlaybackService extends MediaBrowserServiceCompat { registerReceiver(skipCurrentEpisodeReceiver, new IntentFilter(ACTION_SKIP_CURRENT_EPISODE)); registerReceiver(pausePlayCurrentEpisodeReceiver, new IntentFilter(ACTION_PAUSE_PLAY_CURRENT_EPISODE)); registerReceiver(pauseResumeCurrentEpisodeReceiver, new IntentFilter(ACTION_RESUME_PLAY_CURRENT_EPISODE)); + registerReceiver(volumeReductionChangedReceiver, new IntentFilter(ACTION_VOLUME_REDUCTION_CHANGED)); taskManager = new PlaybackServiceTaskManager(this, taskManagerCallback); flavorHelper = new PlaybackServiceFlavorHelper(PlaybackService.this, flavorHelperCallback); @@ -1517,6 +1525,22 @@ public class PlaybackService extends MediaBrowserServiceCompat { } }; + private final BroadcastReceiver volumeReductionChangedReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + if (TextUtils.equals(intent.getAction(), ACTION_VOLUME_REDUCTION_CHANGED)) { + Log.d(TAG, "Received ACTION_VOLUME_REDUCTION_CHANGED intent"); + + String affectedFeed = intent.getStringExtra(EXTRA_VOLUME_REDUCTION_AFFECTED_FEED); + Serializable volumeReductionExtra = intent.getSerializableExtra(EXTRA_VOLUME_REDUCTION_SETTING); + FeedPreferences.VolumeReductionSetting volumeReductionSetting = (FeedPreferences.VolumeReductionSetting) volumeReductionExtra; + + PlaybackVolumeAdaptor playbackVolumeAdaptor = new PlaybackVolumeAdaptor(); + playbackVolumeAdaptor.adaptVolumeIfNecessary(mediaPlayer, affectedFeed, volumeReductionSetting); + } + } + }; + public static MediaType getCurrentMediaType() { return currentMediaType; } diff --git a/core/src/test/java/de/danoeh/antennapod/core/service/playback/PlaybackVolumeAdaptorTest.java b/core/src/test/java/de/danoeh/antennapod/core/service/playback/PlaybackVolumeAdaptorTest.java new file mode 100644 index 000000000..9036624d8 --- /dev/null +++ b/core/src/test/java/de/danoeh/antennapod/core/service/playback/PlaybackVolumeAdaptorTest.java @@ -0,0 +1,230 @@ +package de.danoeh.antennapod.core.service.playback; + +import de.danoeh.antennapod.core.feed.Feed; +import de.danoeh.antennapod.core.feed.FeedItem; +import de.danoeh.antennapod.core.feed.FeedMedia; +import de.danoeh.antennapod.core.feed.FeedPreferences; +import de.danoeh.antennapod.core.feed.FeedPreferences.VolumeReductionSetting; +import de.danoeh.antennapod.core.util.playback.Playable; +import org.junit.Before; +import org.junit.Test; + +import static org.mockito.Mockito.anyBoolean; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +public class PlaybackVolumeAdaptorTest { + + private static final String FEED_ID = "feedId"; + + private PlaybackServiceMediaPlayer mediaPlayer; + + @Before + public void setUp() throws Exception { + mediaPlayer = mock(PlaybackServiceMediaPlayer.class); + } + + @Test + public void noChangeIfNoFeedMediaPlaying() { + PlaybackVolumeAdaptor playbackVolumeAdaptor = new PlaybackVolumeAdaptor(); + + when(mediaPlayer.getPlayerStatus()).thenReturn(PlayerStatus.PAUSED); + + Playable noFeedMedia = mock(Playable.class); + when(mediaPlayer.getPlayable()).thenReturn(noFeedMedia); + + playbackVolumeAdaptor.adaptVolumeIfNecessary(mediaPlayer, FEED_ID, VolumeReductionSetting.OFF); + + verify(mediaPlayer, never()).pause(anyBoolean(), anyBoolean()); + verify(mediaPlayer, never()).resume(); + } + + @Test + public void noChangeIfPlayerStatusIsError() { + PlaybackVolumeAdaptor playbackVolumeAdaptor = new PlaybackVolumeAdaptor(); + + when(mediaPlayer.getPlayerStatus()).thenReturn(PlayerStatus.ERROR); + + FeedMedia feedMedia = mock(FeedMedia.class); + when(mediaPlayer.getPlayable()).thenReturn(feedMedia); + + playbackVolumeAdaptor.adaptVolumeIfNecessary(mediaPlayer, FEED_ID, VolumeReductionSetting.OFF); + + verify(mediaPlayer, never()).pause(anyBoolean(), anyBoolean()); + verify(mediaPlayer, never()).resume(); + } + + @Test + public void noChangeIfPlayerStatusIsIndeterminate() { + PlaybackVolumeAdaptor playbackVolumeAdaptor = new PlaybackVolumeAdaptor(); + + when(mediaPlayer.getPlayerStatus()).thenReturn(PlayerStatus.INDETERMINATE); + + FeedMedia feedMedia = mock(FeedMedia.class); + when(mediaPlayer.getPlayable()).thenReturn(feedMedia); + + playbackVolumeAdaptor.adaptVolumeIfNecessary(mediaPlayer, FEED_ID, VolumeReductionSetting.OFF); + + verify(mediaPlayer, never()).pause(anyBoolean(), anyBoolean()); + verify(mediaPlayer, never()).resume(); + } + + @Test + public void noChangeIfPlayerStatusIsStopped() { + PlaybackVolumeAdaptor playbackVolumeAdaptor = new PlaybackVolumeAdaptor(); + + when(mediaPlayer.getPlayerStatus()).thenReturn(PlayerStatus.STOPPED); + + FeedMedia feedMedia = mock(FeedMedia.class); + when(mediaPlayer.getPlayable()).thenReturn(feedMedia); + + playbackVolumeAdaptor.adaptVolumeIfNecessary(mediaPlayer, FEED_ID, VolumeReductionSetting.OFF); + + verify(mediaPlayer, never()).pause(anyBoolean(), anyBoolean()); + verify(mediaPlayer, never()).resume(); + } + + @Test + public void noChangeIfPlayableIsNoItemOfAffectedFeed() { + PlaybackVolumeAdaptor playbackVolumeAdaptor = new PlaybackVolumeAdaptor(); + + when(mediaPlayer.getPlayerStatus()).thenReturn(PlayerStatus.PLAYING); + + FeedMedia feedMedia = mock(FeedMedia.class); + when(mediaPlayer.getPlayable()).thenReturn(feedMedia); + Feed feed = mockFeed(feedMedia, FEED_ID); + when(feed.getIdentifyingValue()).thenReturn("wrongFeedId"); + + playbackVolumeAdaptor.adaptVolumeIfNecessary(mediaPlayer, FEED_ID, VolumeReductionSetting.OFF); + + verify(mediaPlayer, never()).pause(anyBoolean(), anyBoolean()); + verify(mediaPlayer, never()).resume(); + } + + @Test + public void adaptsPreferencesForLoadedFeedMediaIfPlayerStatusIsPaused() { + PlaybackVolumeAdaptor playbackVolumeAdaptor = new PlaybackVolumeAdaptor(); + + when(mediaPlayer.getPlayerStatus()).thenReturn(PlayerStatus.PAUSED); + + FeedMedia feedMedia = mock(FeedMedia.class); + when(mediaPlayer.getPlayable()).thenReturn(feedMedia); + FeedPreferences feedPreferences = mockFeedPreferences(feedMedia, FEED_ID); + + playbackVolumeAdaptor.adaptVolumeIfNecessary(mediaPlayer, FEED_ID, VolumeReductionSetting.LIGHT); + + verify(feedPreferences, times(1)).setVolumeReductionSetting(VolumeReductionSetting.LIGHT); + + verify(mediaPlayer, never()).pause(anyBoolean(), anyBoolean()); + verify(mediaPlayer, never()).resume(); + } + + @Test + public void adaptsPreferencesForLoadedFeedMediaIfPlayerStatusIsPrepared() { + PlaybackVolumeAdaptor playbackVolumeAdaptor = new PlaybackVolumeAdaptor(); + + when(mediaPlayer.getPlayerStatus()).thenReturn(PlayerStatus.PREPARED); + + FeedMedia feedMedia = mock(FeedMedia.class); + when(mediaPlayer.getPlayable()).thenReturn(feedMedia); + FeedPreferences feedPreferences = mockFeedPreferences(feedMedia, FEED_ID); + + playbackVolumeAdaptor.adaptVolumeIfNecessary(mediaPlayer, FEED_ID, VolumeReductionSetting.LIGHT); + + verify(feedPreferences, times(1)).setVolumeReductionSetting(VolumeReductionSetting.LIGHT); + + verify(mediaPlayer, never()).pause(anyBoolean(), anyBoolean()); + verify(mediaPlayer, never()).resume(); + } + + @Test + public void adaptsPreferencesForLoadedFeedMediaIfPlayerStatusIsInitializing() { + PlaybackVolumeAdaptor playbackVolumeAdaptor = new PlaybackVolumeAdaptor(); + + when(mediaPlayer.getPlayerStatus()).thenReturn(PlayerStatus.INITIALIZING); + + FeedMedia feedMedia = mock(FeedMedia.class); + when(mediaPlayer.getPlayable()).thenReturn(feedMedia); + FeedPreferences feedPreferences = mockFeedPreferences(feedMedia, FEED_ID); + + playbackVolumeAdaptor.adaptVolumeIfNecessary(mediaPlayer, FEED_ID, VolumeReductionSetting.LIGHT); + + verify(feedPreferences, times(1)).setVolumeReductionSetting(VolumeReductionSetting.LIGHT); + + verify(mediaPlayer, never()).pause(anyBoolean(), anyBoolean()); + verify(mediaPlayer, never()).resume(); + } + + @Test + public void adaptsPreferencesForLoadedFeedMediaIfPlayerStatusIsPreparing() { + PlaybackVolumeAdaptor playbackVolumeAdaptor = new PlaybackVolumeAdaptor(); + + when(mediaPlayer.getPlayerStatus()).thenReturn(PlayerStatus.PREPARING); + + FeedMedia feedMedia = mock(FeedMedia.class); + when(mediaPlayer.getPlayable()).thenReturn(feedMedia); + FeedPreferences feedPreferences = mockFeedPreferences(feedMedia, FEED_ID); + + playbackVolumeAdaptor.adaptVolumeIfNecessary(mediaPlayer, FEED_ID, VolumeReductionSetting.LIGHT); + + verify(feedPreferences, times(1)).setVolumeReductionSetting(VolumeReductionSetting.LIGHT); + + verify(mediaPlayer, never()).pause(anyBoolean(), anyBoolean()); + verify(mediaPlayer, never()).resume(); + } + + @Test + public void adaptsPreferencesForLoadedFeedMediaIfPlayerStatusIsSeeking() { + PlaybackVolumeAdaptor playbackVolumeAdaptor = new PlaybackVolumeAdaptor(); + + when(mediaPlayer.getPlayerStatus()).thenReturn(PlayerStatus.SEEKING); + + FeedMedia feedMedia = mock(FeedMedia.class); + when(mediaPlayer.getPlayable()).thenReturn(feedMedia); + FeedPreferences feedPreferences = mockFeedPreferences(feedMedia, FEED_ID); + + playbackVolumeAdaptor.adaptVolumeIfNecessary(mediaPlayer, FEED_ID, VolumeReductionSetting.LIGHT); + + verify(feedPreferences, times(1)).setVolumeReductionSetting(VolumeReductionSetting.LIGHT); + + verify(mediaPlayer, never()).pause(anyBoolean(), anyBoolean()); + verify(mediaPlayer, never()).resume(); + } + + @Test + public void adaptsPreferencesAndForcesVolumeChangeForLoadedFeedMediaIfPlayerStatusIsPlaying() { + PlaybackVolumeAdaptor playbackVolumeAdaptor = new PlaybackVolumeAdaptor(); + + when(mediaPlayer.getPlayerStatus()).thenReturn(PlayerStatus.PLAYING); + + FeedMedia feedMedia = mock(FeedMedia.class); + when(mediaPlayer.getPlayable()).thenReturn(feedMedia); + FeedPreferences feedPreferences = mockFeedPreferences(feedMedia, FEED_ID); + + playbackVolumeAdaptor.adaptVolumeIfNecessary(mediaPlayer, FEED_ID, VolumeReductionSetting.HEAVY); + + verify(feedPreferences, times(1)).setVolumeReductionSetting(VolumeReductionSetting.HEAVY); + + verify(mediaPlayer, times(1)).pause(false, false); + verify(mediaPlayer, times(1)).resume(); + } + + private FeedPreferences mockFeedPreferences(FeedMedia feedMedia, String feedId) { + Feed feed = mockFeed(feedMedia, feedId); + FeedPreferences feedPreferences = mock(FeedPreferences.class); + when(feed.getPreferences()).thenReturn(feedPreferences); + return feedPreferences; + } + + private Feed mockFeed(FeedMedia feedMedia, String feedId) { + FeedItem feedItem = mock(FeedItem.class); + when(feedMedia.getItem()).thenReturn(feedItem); + Feed feed = mock(Feed.class); + when(feed.getIdentifyingValue()).thenReturn(feedId); + when(feedItem.getFeed()).thenReturn(feed); + return feed; + } +} -- cgit v1.2.3 From 5f43acbffe7d717442a8c2c8f6bfc63e6466430a Mon Sep 17 00:00:00 2001 From: Max Bechtold Date: Sun, 18 Aug 2019 14:25:10 +0200 Subject: Attempt to fix circle-ci build to allow assembling play flavor --- .../service/playback/PlaybackVolumeAdaptor.java | 49 ---------------------- .../service/playback/PlaybackVolumeAdaptor.java | 49 ++++++++++++++++++++++ 2 files changed, 49 insertions(+), 49 deletions(-) delete mode 100644 core/src/free/java/de/danoeh/antennapod/core/service/playback/PlaybackVolumeAdaptor.java create mode 100644 core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackVolumeAdaptor.java (limited to 'core/src') diff --git a/core/src/free/java/de/danoeh/antennapod/core/service/playback/PlaybackVolumeAdaptor.java b/core/src/free/java/de/danoeh/antennapod/core/service/playback/PlaybackVolumeAdaptor.java deleted file mode 100644 index 949f8c8cc..000000000 --- a/core/src/free/java/de/danoeh/antennapod/core/service/playback/PlaybackVolumeAdaptor.java +++ /dev/null @@ -1,49 +0,0 @@ -package de.danoeh.antennapod.core.service.playback; - -import de.danoeh.antennapod.core.feed.FeedMedia; -import de.danoeh.antennapod.core.feed.FeedPreferences; -import de.danoeh.antennapod.core.util.playback.Playable; - -class PlaybackVolumeAdaptor { - - public void adaptVolumeIfNecessary(PlaybackServiceMediaPlayer mediaPlayer, String affectedFeedIdentifier, FeedPreferences.VolumeReductionSetting volumeReductionSetting) { - Playable playable = mediaPlayer.getPlayable(); - boolean isFeedMedia = playable instanceof FeedMedia; - boolean isPlayableLoaded = isPlayableLoaded(mediaPlayer.getPlayerStatus()); - - if (isPlayableLoaded && isFeedMedia) { - adaptFeedMediaVolumeIfNecessary(mediaPlayer, affectedFeedIdentifier, volumeReductionSetting, (FeedMedia) playable); - } - } - - private void adaptFeedMediaVolumeIfNecessary(PlaybackServiceMediaPlayer mediaPlayer, String affectedFeedIdentifier, FeedPreferences.VolumeReductionSetting volumeReductionSetting, FeedMedia feedMedia) { - if (mediaBelongsToAffectedFeed(feedMedia, affectedFeedIdentifier)) { - FeedPreferences preferences = feedMedia.getItem().getFeed().getPreferences(); - preferences.setVolumeReductionSetting(volumeReductionSetting); - - if (mediaPlayer.getPlayerStatus() == PlayerStatus.PLAYING) { - forceAdaptVolume(mediaPlayer); - } - } - } - - private static boolean isPlayableLoaded(PlayerStatus playerStatus) { - return playerStatus == PlayerStatus.PLAYING - || playerStatus == PlayerStatus.PAUSED - || playerStatus == PlayerStatus.SEEKING - || playerStatus == PlayerStatus.PREPARING - || playerStatus == PlayerStatus.PREPARED - || playerStatus == PlayerStatus.INITIALIZING; - } - - private static boolean mediaBelongsToAffectedFeed(FeedMedia feedMedia, String affectedFeedIdentifier) { - return affectedFeedIdentifier != null - && affectedFeedIdentifier.equals(feedMedia.getItem().getFeed().getIdentifyingValue()); - } - - private static void forceAdaptVolume(PlaybackServiceMediaPlayer mediaPlayer) { - mediaPlayer.pause(false, false); - mediaPlayer.resume(); - } - -} diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackVolumeAdaptor.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackVolumeAdaptor.java new file mode 100644 index 000000000..949f8c8cc --- /dev/null +++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackVolumeAdaptor.java @@ -0,0 +1,49 @@ +package de.danoeh.antennapod.core.service.playback; + +import de.danoeh.antennapod.core.feed.FeedMedia; +import de.danoeh.antennapod.core.feed.FeedPreferences; +import de.danoeh.antennapod.core.util.playback.Playable; + +class PlaybackVolumeAdaptor { + + public void adaptVolumeIfNecessary(PlaybackServiceMediaPlayer mediaPlayer, String affectedFeedIdentifier, FeedPreferences.VolumeReductionSetting volumeReductionSetting) { + Playable playable = mediaPlayer.getPlayable(); + boolean isFeedMedia = playable instanceof FeedMedia; + boolean isPlayableLoaded = isPlayableLoaded(mediaPlayer.getPlayerStatus()); + + if (isPlayableLoaded && isFeedMedia) { + adaptFeedMediaVolumeIfNecessary(mediaPlayer, affectedFeedIdentifier, volumeReductionSetting, (FeedMedia) playable); + } + } + + private void adaptFeedMediaVolumeIfNecessary(PlaybackServiceMediaPlayer mediaPlayer, String affectedFeedIdentifier, FeedPreferences.VolumeReductionSetting volumeReductionSetting, FeedMedia feedMedia) { + if (mediaBelongsToAffectedFeed(feedMedia, affectedFeedIdentifier)) { + FeedPreferences preferences = feedMedia.getItem().getFeed().getPreferences(); + preferences.setVolumeReductionSetting(volumeReductionSetting); + + if (mediaPlayer.getPlayerStatus() == PlayerStatus.PLAYING) { + forceAdaptVolume(mediaPlayer); + } + } + } + + private static boolean isPlayableLoaded(PlayerStatus playerStatus) { + return playerStatus == PlayerStatus.PLAYING + || playerStatus == PlayerStatus.PAUSED + || playerStatus == PlayerStatus.SEEKING + || playerStatus == PlayerStatus.PREPARING + || playerStatus == PlayerStatus.PREPARED + || playerStatus == PlayerStatus.INITIALIZING; + } + + private static boolean mediaBelongsToAffectedFeed(FeedMedia feedMedia, String affectedFeedIdentifier) { + return affectedFeedIdentifier != null + && affectedFeedIdentifier.equals(feedMedia.getItem().getFeed().getIdentifyingValue()); + } + + private static void forceAdaptVolume(PlaybackServiceMediaPlayer mediaPlayer) { + mediaPlayer.pause(false, false); + mediaPlayer.resume(); + } + +} -- cgit v1.2.3 From b6fc27fe12e48f4de5c170e7edeb06ccb5bf6419 Mon Sep 17 00:00:00 2001 From: Max Bechtold Date: Mon, 26 Aug 2019 11:09:39 +0200 Subject: #3248 Refactor enum mapping for more refactoring safety --- .../java/de/danoeh/antennapod/core/feed/Feed.java | 2 +- .../antennapod/core/feed/FeedPreferences.java | 9 +--- .../core/feed/VolumeReductionSetting.java | 26 ++++++++++++ .../core/service/download/DownloadService.java | 3 +- .../core/service/playback/FeedVolumeReduction.java | 8 ++-- .../core/service/playback/PlaybackService.java | 4 +- .../service/playback/PlaybackVolumeAdaptor.java | 5 ++- .../antennapod/core/storage/PodDBAdapter.java | 2 +- .../core/feed/VolumeReductionSettingTest.java | 48 ++++++++++++++++++++++ .../service/playback/FeedVolumeReductionTest.java | 7 ++-- .../playback/PlaybackVolumeAdaptorTest.java | 2 +- 11 files changed, 94 insertions(+), 22 deletions(-) create mode 100644 core/src/main/java/de/danoeh/antennapod/core/feed/VolumeReductionSetting.java create mode 100644 core/src/test/java/de/danoeh/antennapod/core/feed/VolumeReductionSettingTest.java (limited to 'core/src') diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/Feed.java b/core/src/main/java/de/danoeh/antennapod/core/feed/Feed.java index e01c35d0e..2a535b2c4 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/feed/Feed.java +++ b/core/src/main/java/de/danoeh/antennapod/core/feed/Feed.java @@ -160,7 +160,7 @@ public class Feed extends FeedFile implements ImageResource { */ public Feed(String url, String lastUpdate, String title, String username, String password) { this(url, lastUpdate, title); - preferences = new FeedPreferences(0, true, FeedPreferences.AutoDeleteAction.GLOBAL, FeedPreferences.VolumeReductionSetting.OFF, username, password); + preferences = new FeedPreferences(0, true, FeedPreferences.AutoDeleteAction.GLOBAL, VolumeReductionSetting.OFF, username, password); } public static Feed fromCursor(Cursor cursor) { diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedPreferences.java b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedPreferences.java index 62fb28100..eaafab322 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedPreferences.java +++ b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedPreferences.java @@ -27,11 +27,6 @@ public class FeedPreferences { } private AutoDeleteAction auto_delete_action; - public enum VolumeReductionSetting { - OFF, - LIGHT, - HEAVY - } private VolumeReductionSetting volumeReductionSetting; private String username; @@ -68,8 +63,8 @@ public class FeedPreferences { boolean autoRefresh = cursor.getInt(indexAutoRefresh) > 0; int autoDeleteActionIndex = cursor.getInt(indexAutoDeleteAction); AutoDeleteAction autoDeleteAction = AutoDeleteAction.values()[autoDeleteActionIndex]; - int volumeReductionIndex = cursor.getInt(indexVolumeReduction); - VolumeReductionSetting volumeReductionSetting = VolumeReductionSetting.values()[volumeReductionIndex]; + int volumeReductionValue = cursor.getInt(indexVolumeReduction); + VolumeReductionSetting volumeReductionSetting = VolumeReductionSetting.fromInteger(volumeReductionValue); String username = cursor.getString(indexUsername); String password = cursor.getString(indexPassword); String includeFilter = cursor.getString(indexIncludeFilter); diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/VolumeReductionSetting.java b/core/src/main/java/de/danoeh/antennapod/core/feed/VolumeReductionSetting.java new file mode 100644 index 000000000..ec6db4872 --- /dev/null +++ b/core/src/main/java/de/danoeh/antennapod/core/feed/VolumeReductionSetting.java @@ -0,0 +1,26 @@ +package de.danoeh.antennapod.core.feed; + +public enum VolumeReductionSetting { + OFF(0), + LIGHT(1), + HEAVY(2); + + private final int value; + + VolumeReductionSetting(int value) { + this.value = value; + } + + public static VolumeReductionSetting fromInteger(int value) { + for (VolumeReductionSetting setting : values()) { + if (setting.value == value) { + return setting; + } + } + throw new IllegalArgumentException("Cannot map value to VolumeReductionSetting: " + value); + } + + public int toInteger() { + return value; + } +} diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java b/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java index 1b94bb3c3..59222aa11 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java @@ -19,6 +19,7 @@ import android.util.Log; import android.util.Pair; import android.webkit.URLUtil; +import de.danoeh.antennapod.core.feed.VolumeReductionSetting; import org.apache.commons.io.FileUtils; import org.greenrobot.eventbus.EventBus; import org.xml.sax.SAXException; @@ -764,7 +765,7 @@ public class DownloadService extends Service { feed.setId(request.getFeedfileId()); feed.setDownloaded(true); feed.setPreferences(new FeedPreferences(0, true, FeedPreferences.AutoDeleteAction.GLOBAL, - FeedPreferences.VolumeReductionSetting.OFF, request.getUsername(), request.getPassword())); + VolumeReductionSetting.OFF, request.getUsername(), request.getPassword())); feed.setPageNr(request.getArguments().getInt(DownloadRequester.REQUEST_ARG_PAGE_NR, 0)); DownloadError reason = null; diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/FeedVolumeReduction.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/FeedVolumeReduction.java index c9e10efc3..608e8375b 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/FeedVolumeReduction.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/FeedVolumeReduction.java @@ -1,14 +1,14 @@ package de.danoeh.antennapod.core.service.playback; import de.danoeh.antennapod.core.feed.FeedPreferences; +import de.danoeh.antennapod.core.feed.VolumeReductionSetting; public class FeedVolumeReduction { float getReductionFactor(FeedPreferences preferences) { - FeedPreferences.VolumeReductionSetting volumeReductionSetting = preferences.getVolumeReductionSetting(); - // TODO maxbechtold These numbers should be tested - if (volumeReductionSetting == FeedPreferences.VolumeReductionSetting.LIGHT) { + VolumeReductionSetting volumeReductionSetting = preferences.getVolumeReductionSetting(); + if (volumeReductionSetting == VolumeReductionSetting.LIGHT) { return 0.5f; - } else if (volumeReductionSetting == FeedPreferences.VolumeReductionSetting.HEAVY) { + } else if (volumeReductionSetting == VolumeReductionSetting.HEAVY) { return 0.2f; } return 1.0f; diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java index 632dfd50e..d90a86bab 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java @@ -54,9 +54,9 @@ import de.danoeh.antennapod.core.feed.Chapter; import de.danoeh.antennapod.core.feed.Feed; import de.danoeh.antennapod.core.feed.FeedItem; import de.danoeh.antennapod.core.feed.FeedMedia; -import de.danoeh.antennapod.core.feed.FeedPreferences; import de.danoeh.antennapod.core.feed.MediaType; import de.danoeh.antennapod.core.feed.SearchResult; +import de.danoeh.antennapod.core.feed.VolumeReductionSetting; import de.danoeh.antennapod.core.glide.ApGlideSettings; import de.danoeh.antennapod.core.preferences.PlaybackPreferences; import de.danoeh.antennapod.core.preferences.SleepTimerPreferences; @@ -1533,7 +1533,7 @@ public class PlaybackService extends MediaBrowserServiceCompat { String affectedFeed = intent.getStringExtra(EXTRA_VOLUME_REDUCTION_AFFECTED_FEED); Serializable volumeReductionExtra = intent.getSerializableExtra(EXTRA_VOLUME_REDUCTION_SETTING); - FeedPreferences.VolumeReductionSetting volumeReductionSetting = (FeedPreferences.VolumeReductionSetting) volumeReductionExtra; + VolumeReductionSetting volumeReductionSetting = (VolumeReductionSetting) volumeReductionExtra; PlaybackVolumeAdaptor playbackVolumeAdaptor = new PlaybackVolumeAdaptor(); playbackVolumeAdaptor.adaptVolumeIfNecessary(mediaPlayer, affectedFeed, volumeReductionSetting); diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackVolumeAdaptor.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackVolumeAdaptor.java index 949f8c8cc..970abff33 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackVolumeAdaptor.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackVolumeAdaptor.java @@ -2,11 +2,12 @@ package de.danoeh.antennapod.core.service.playback; import de.danoeh.antennapod.core.feed.FeedMedia; import de.danoeh.antennapod.core.feed.FeedPreferences; +import de.danoeh.antennapod.core.feed.VolumeReductionSetting; import de.danoeh.antennapod.core.util.playback.Playable; class PlaybackVolumeAdaptor { - public void adaptVolumeIfNecessary(PlaybackServiceMediaPlayer mediaPlayer, String affectedFeedIdentifier, FeedPreferences.VolumeReductionSetting volumeReductionSetting) { + public void adaptVolumeIfNecessary(PlaybackServiceMediaPlayer mediaPlayer, String affectedFeedIdentifier, VolumeReductionSetting volumeReductionSetting) { Playable playable = mediaPlayer.getPlayable(); boolean isFeedMedia = playable instanceof FeedMedia; boolean isPlayableLoaded = isPlayableLoaded(mediaPlayer.getPlayerStatus()); @@ -16,7 +17,7 @@ class PlaybackVolumeAdaptor { } } - private void adaptFeedMediaVolumeIfNecessary(PlaybackServiceMediaPlayer mediaPlayer, String affectedFeedIdentifier, FeedPreferences.VolumeReductionSetting volumeReductionSetting, FeedMedia feedMedia) { + private void adaptFeedMediaVolumeIfNecessary(PlaybackServiceMediaPlayer mediaPlayer, String affectedFeedIdentifier, VolumeReductionSetting volumeReductionSetting, FeedMedia feedMedia) { if (mediaBelongsToAffectedFeed(feedMedia, affectedFeedIdentifier)) { FeedPreferences preferences = feedMedia.getItem().getFeed().getPreferences(); preferences.setVolumeReductionSetting(volumeReductionSetting); diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java b/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java index 6f8aaf06e..566c280eb 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java @@ -407,7 +407,7 @@ public class PodDBAdapter { values.put(KEY_AUTO_DOWNLOAD, prefs.getAutoDownload()); values.put(KEY_KEEP_UPDATED, prefs.getKeepUpdated()); values.put(KEY_AUTO_DELETE_ACTION, prefs.getAutoDeleteAction().ordinal()); - values.put(KEY_FEED_VOLUME_REDUCTION, prefs.getVolumeReductionSetting().ordinal()); + values.put(KEY_FEED_VOLUME_REDUCTION, prefs.getVolumeReductionSetting().toInteger()); values.put(KEY_USERNAME, prefs.getUsername()); values.put(KEY_PASSWORD, prefs.getPassword()); values.put(KEY_INCLUDE_FILTER, prefs.getFilter().getIncludeFilter()); diff --git a/core/src/test/java/de/danoeh/antennapod/core/feed/VolumeReductionSettingTest.java b/core/src/test/java/de/danoeh/antennapod/core/feed/VolumeReductionSettingTest.java new file mode 100644 index 000000000..26c2132fe --- /dev/null +++ b/core/src/test/java/de/danoeh/antennapod/core/feed/VolumeReductionSettingTest.java @@ -0,0 +1,48 @@ +package de.danoeh.antennapod.core.feed; + + +import org.junit.Test; + +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertThat; + +public class VolumeReductionSettingTest { + + @Test + public void mapOffToInteger() { + VolumeReductionSetting setting = VolumeReductionSetting.OFF; + assertThat(setting.toInteger(), is(equalTo(0))); + } + + @Test + public void mapLightToInteger() { + VolumeReductionSetting setting = VolumeReductionSetting.LIGHT; + + assertThat(setting.toInteger(), is(equalTo(1))); + } + + @Test + public void mapHeavyToInteger() { + VolumeReductionSetting setting = VolumeReductionSetting.HEAVY; + + assertThat(setting.toInteger(), is(equalTo(2))); + } + + @Test + public void mapIntegerToVolumeReductionSetting() { + assertThat(VolumeReductionSetting.fromInteger(0), is(equalTo(VolumeReductionSetting.OFF))); + assertThat(VolumeReductionSetting.fromInteger(1), is(equalTo(VolumeReductionSetting.LIGHT))); + assertThat(VolumeReductionSetting.fromInteger(2), is(equalTo(VolumeReductionSetting.HEAVY))); + } + + @Test(expected = IllegalArgumentException.class) + public void cannotMapNegativeValues() { + VolumeReductionSetting.fromInteger(-1); + } + + @Test(expected = IllegalArgumentException.class) + public void cannotMapValuesOutOfRange() { + VolumeReductionSetting.fromInteger(3); + } +} \ No newline at end of file diff --git a/core/src/test/java/de/danoeh/antennapod/core/service/playback/FeedVolumeReductionTest.java b/core/src/test/java/de/danoeh/antennapod/core/service/playback/FeedVolumeReductionTest.java index 3f2f9d597..109b361fe 100644 --- a/core/src/test/java/de/danoeh/antennapod/core/service/playback/FeedVolumeReductionTest.java +++ b/core/src/test/java/de/danoeh/antennapod/core/service/playback/FeedVolumeReductionTest.java @@ -1,6 +1,7 @@ package de.danoeh.antennapod.core.service.playback; import de.danoeh.antennapod.core.feed.FeedPreferences; +import de.danoeh.antennapod.core.feed.VolumeReductionSetting; import org.junit.Test; import static org.junit.Assert.assertEquals; @@ -13,7 +14,7 @@ public class FeedVolumeReductionTest { @Test public void noReductionIfTurnedOff() { FeedPreferences feedPreferences = mock(FeedPreferences.class); - when(feedPreferences.getVolumeReductionSetting()).thenReturn(FeedPreferences.VolumeReductionSetting.OFF); + when(feedPreferences.getVolumeReductionSetting()).thenReturn(VolumeReductionSetting.OFF); FeedVolumeReduction feedVolumeReduction = new FeedVolumeReduction(); float reductionFactor = feedVolumeReduction.getReductionFactor(feedPreferences); @@ -25,10 +26,10 @@ public class FeedVolumeReductionTest { FeedPreferences feedPreferences = mock(FeedPreferences.class); FeedVolumeReduction feedVolumeReduction = new FeedVolumeReduction(); - when(feedPreferences.getVolumeReductionSetting()).thenReturn(FeedPreferences.VolumeReductionSetting.LIGHT); + when(feedPreferences.getVolumeReductionSetting()).thenReturn(VolumeReductionSetting.LIGHT); float lightReductionFactor = feedVolumeReduction.getReductionFactor(feedPreferences); - when(feedPreferences.getVolumeReductionSetting()).thenReturn(FeedPreferences.VolumeReductionSetting.HEAVY); + when(feedPreferences.getVolumeReductionSetting()).thenReturn(VolumeReductionSetting.HEAVY); float heavyReductionFactor = feedVolumeReduction.getReductionFactor(feedPreferences); assertTrue("Light reduction must have higher factor than heavy reduction", lightReductionFactor > heavyReductionFactor); diff --git a/core/src/test/java/de/danoeh/antennapod/core/service/playback/PlaybackVolumeAdaptorTest.java b/core/src/test/java/de/danoeh/antennapod/core/service/playback/PlaybackVolumeAdaptorTest.java index 9036624d8..501719ebe 100644 --- a/core/src/test/java/de/danoeh/antennapod/core/service/playback/PlaybackVolumeAdaptorTest.java +++ b/core/src/test/java/de/danoeh/antennapod/core/service/playback/PlaybackVolumeAdaptorTest.java @@ -4,7 +4,7 @@ import de.danoeh.antennapod.core.feed.Feed; import de.danoeh.antennapod.core.feed.FeedItem; import de.danoeh.antennapod.core.feed.FeedMedia; import de.danoeh.antennapod.core.feed.FeedPreferences; -import de.danoeh.antennapod.core.feed.FeedPreferences.VolumeReductionSetting; +import de.danoeh.antennapod.core.feed.VolumeReductionSetting; import de.danoeh.antennapod.core.util.playback.Playable; import org.junit.Before; import org.junit.Test; -- cgit v1.2.3 From f9cf013b16dc98b5b1ff333c363317d350c8dc24 Mon Sep 17 00:00:00 2001 From: Max Bechtold Date: Thu, 17 Oct 2019 09:40:18 +0200 Subject: #3248 Enable volume reduction for video media --- .../java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'core/src') diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java index a4c9ba31c..a09d6cb19 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java @@ -16,6 +16,7 @@ import org.antennapod.audio.MediaPlayer; import java.io.File; import java.io.IOException; +import java.util.EnumSet; import java.util.concurrent.CountDownLatch; import java.util.concurrent.Future; import java.util.concurrent.FutureTask; @@ -670,7 +671,7 @@ public class LocalPSMP extends PlaybackServiceMediaPlayer { */ private void setVolumeSync(float volumeLeft, float volumeRight) { playerLock.lock(); - if (media != null && media.getMediaType() == MediaType.AUDIO) { + if (media != null && EnumSet.of(MediaType.AUDIO, MediaType.VIDEO).contains(media.getMediaType())) { Playable playable = getPlayable(); if (playable instanceof FeedMedia) { FeedMedia feedMedia = (FeedMedia) playable; -- cgit v1.2.3 From 3bc55a09b1371fbb6086e290369cfe048e1df25e Mon Sep 17 00:00:00 2001 From: Max Bechtold Date: Thu, 17 Oct 2019 09:56:04 +0200 Subject: #3248 Rename PlaybackVolumeAdaptor -> ..Updater --- .../core/service/playback/PlaybackService.java | 4 +- .../service/playback/PlaybackVolumeAdaptor.java | 50 ----- .../service/playback/PlaybackVolumeUpdater.java | 50 +++++ .../playback/PlaybackVolumeAdaptorTest.java | 230 --------------------- .../playback/PlaybackVolumeUpdaterTest.java | 230 +++++++++++++++++++++ 5 files changed, 282 insertions(+), 282 deletions(-) delete mode 100644 core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackVolumeAdaptor.java create mode 100644 core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackVolumeUpdater.java delete mode 100644 core/src/test/java/de/danoeh/antennapod/core/service/playback/PlaybackVolumeAdaptorTest.java create mode 100644 core/src/test/java/de/danoeh/antennapod/core/service/playback/PlaybackVolumeUpdaterTest.java (limited to 'core/src') diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java index f8990328f..d444875ad 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java @@ -1482,8 +1482,8 @@ public class PlaybackService extends MediaBrowserServiceCompat { Serializable volumeReductionExtra = intent.getSerializableExtra(EXTRA_VOLUME_REDUCTION_SETTING); VolumeReductionSetting volumeReductionSetting = (VolumeReductionSetting) volumeReductionExtra; - PlaybackVolumeAdaptor playbackVolumeAdaptor = new PlaybackVolumeAdaptor(); - playbackVolumeAdaptor.adaptVolumeIfNecessary(mediaPlayer, affectedFeed, volumeReductionSetting); + PlaybackVolumeUpdater playbackVolumeUpdater = new PlaybackVolumeUpdater(); + playbackVolumeUpdater.updateVolumeIfNecessary(mediaPlayer, affectedFeed, volumeReductionSetting); } } }; diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackVolumeAdaptor.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackVolumeAdaptor.java deleted file mode 100644 index 970abff33..000000000 --- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackVolumeAdaptor.java +++ /dev/null @@ -1,50 +0,0 @@ -package de.danoeh.antennapod.core.service.playback; - -import de.danoeh.antennapod.core.feed.FeedMedia; -import de.danoeh.antennapod.core.feed.FeedPreferences; -import de.danoeh.antennapod.core.feed.VolumeReductionSetting; -import de.danoeh.antennapod.core.util.playback.Playable; - -class PlaybackVolumeAdaptor { - - public void adaptVolumeIfNecessary(PlaybackServiceMediaPlayer mediaPlayer, String affectedFeedIdentifier, VolumeReductionSetting volumeReductionSetting) { - Playable playable = mediaPlayer.getPlayable(); - boolean isFeedMedia = playable instanceof FeedMedia; - boolean isPlayableLoaded = isPlayableLoaded(mediaPlayer.getPlayerStatus()); - - if (isPlayableLoaded && isFeedMedia) { - adaptFeedMediaVolumeIfNecessary(mediaPlayer, affectedFeedIdentifier, volumeReductionSetting, (FeedMedia) playable); - } - } - - private void adaptFeedMediaVolumeIfNecessary(PlaybackServiceMediaPlayer mediaPlayer, String affectedFeedIdentifier, VolumeReductionSetting volumeReductionSetting, FeedMedia feedMedia) { - if (mediaBelongsToAffectedFeed(feedMedia, affectedFeedIdentifier)) { - FeedPreferences preferences = feedMedia.getItem().getFeed().getPreferences(); - preferences.setVolumeReductionSetting(volumeReductionSetting); - - if (mediaPlayer.getPlayerStatus() == PlayerStatus.PLAYING) { - forceAdaptVolume(mediaPlayer); - } - } - } - - private static boolean isPlayableLoaded(PlayerStatus playerStatus) { - return playerStatus == PlayerStatus.PLAYING - || playerStatus == PlayerStatus.PAUSED - || playerStatus == PlayerStatus.SEEKING - || playerStatus == PlayerStatus.PREPARING - || playerStatus == PlayerStatus.PREPARED - || playerStatus == PlayerStatus.INITIALIZING; - } - - private static boolean mediaBelongsToAffectedFeed(FeedMedia feedMedia, String affectedFeedIdentifier) { - return affectedFeedIdentifier != null - && affectedFeedIdentifier.equals(feedMedia.getItem().getFeed().getIdentifyingValue()); - } - - private static void forceAdaptVolume(PlaybackServiceMediaPlayer mediaPlayer) { - mediaPlayer.pause(false, false); - mediaPlayer.resume(); - } - -} diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackVolumeUpdater.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackVolumeUpdater.java new file mode 100644 index 000000000..aff742105 --- /dev/null +++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackVolumeUpdater.java @@ -0,0 +1,50 @@ +package de.danoeh.antennapod.core.service.playback; + +import de.danoeh.antennapod.core.feed.FeedMedia; +import de.danoeh.antennapod.core.feed.FeedPreferences; +import de.danoeh.antennapod.core.feed.VolumeReductionSetting; +import de.danoeh.antennapod.core.util.playback.Playable; + +class PlaybackVolumeUpdater { + + public void updateVolumeIfNecessary(PlaybackServiceMediaPlayer mediaPlayer, String affectedFeedIdentifier, VolumeReductionSetting volumeReductionSetting) { + Playable playable = mediaPlayer.getPlayable(); + boolean isFeedMedia = playable instanceof FeedMedia; + boolean isPlayableLoaded = isPlayableLoaded(mediaPlayer.getPlayerStatus()); + + if (isFeedMedia && isPlayableLoaded) { + updateFeedMediaVolumeIfNecessary(mediaPlayer, affectedFeedIdentifier, volumeReductionSetting, (FeedMedia) playable); + } + } + + private void updateFeedMediaVolumeIfNecessary(PlaybackServiceMediaPlayer mediaPlayer, String affectedFeedIdentifier, VolumeReductionSetting volumeReductionSetting, FeedMedia feedMedia) { + if (mediaBelongsToAffectedFeed(feedMedia, affectedFeedIdentifier)) { + FeedPreferences preferences = feedMedia.getItem().getFeed().getPreferences(); + preferences.setVolumeReductionSetting(volumeReductionSetting); + + if (mediaPlayer.getPlayerStatus() == PlayerStatus.PLAYING) { + forceUpdateVolume(mediaPlayer); + } + } + } + + private static boolean isPlayableLoaded(PlayerStatus playerStatus) { + return playerStatus == PlayerStatus.PLAYING + || playerStatus == PlayerStatus.PAUSED + || playerStatus == PlayerStatus.SEEKING + || playerStatus == PlayerStatus.PREPARING + || playerStatus == PlayerStatus.PREPARED + || playerStatus == PlayerStatus.INITIALIZING; + } + + private static boolean mediaBelongsToAffectedFeed(FeedMedia feedMedia, String affectedFeedIdentifier) { + return affectedFeedIdentifier != null + && affectedFeedIdentifier.equals(feedMedia.getItem().getFeed().getIdentifyingValue()); + } + + private void forceUpdateVolume(PlaybackServiceMediaPlayer mediaPlayer) { + mediaPlayer.pause(false, false); + mediaPlayer.resume(); + } + +} diff --git a/core/src/test/java/de/danoeh/antennapod/core/service/playback/PlaybackVolumeAdaptorTest.java b/core/src/test/java/de/danoeh/antennapod/core/service/playback/PlaybackVolumeAdaptorTest.java deleted file mode 100644 index 501719ebe..000000000 --- a/core/src/test/java/de/danoeh/antennapod/core/service/playback/PlaybackVolumeAdaptorTest.java +++ /dev/null @@ -1,230 +0,0 @@ -package de.danoeh.antennapod.core.service.playback; - -import de.danoeh.antennapod.core.feed.Feed; -import de.danoeh.antennapod.core.feed.FeedItem; -import de.danoeh.antennapod.core.feed.FeedMedia; -import de.danoeh.antennapod.core.feed.FeedPreferences; -import de.danoeh.antennapod.core.feed.VolumeReductionSetting; -import de.danoeh.antennapod.core.util.playback.Playable; -import org.junit.Before; -import org.junit.Test; - -import static org.mockito.Mockito.anyBoolean; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -public class PlaybackVolumeAdaptorTest { - - private static final String FEED_ID = "feedId"; - - private PlaybackServiceMediaPlayer mediaPlayer; - - @Before - public void setUp() throws Exception { - mediaPlayer = mock(PlaybackServiceMediaPlayer.class); - } - - @Test - public void noChangeIfNoFeedMediaPlaying() { - PlaybackVolumeAdaptor playbackVolumeAdaptor = new PlaybackVolumeAdaptor(); - - when(mediaPlayer.getPlayerStatus()).thenReturn(PlayerStatus.PAUSED); - - Playable noFeedMedia = mock(Playable.class); - when(mediaPlayer.getPlayable()).thenReturn(noFeedMedia); - - playbackVolumeAdaptor.adaptVolumeIfNecessary(mediaPlayer, FEED_ID, VolumeReductionSetting.OFF); - - verify(mediaPlayer, never()).pause(anyBoolean(), anyBoolean()); - verify(mediaPlayer, never()).resume(); - } - - @Test - public void noChangeIfPlayerStatusIsError() { - PlaybackVolumeAdaptor playbackVolumeAdaptor = new PlaybackVolumeAdaptor(); - - when(mediaPlayer.getPlayerStatus()).thenReturn(PlayerStatus.ERROR); - - FeedMedia feedMedia = mock(FeedMedia.class); - when(mediaPlayer.getPlayable()).thenReturn(feedMedia); - - playbackVolumeAdaptor.adaptVolumeIfNecessary(mediaPlayer, FEED_ID, VolumeReductionSetting.OFF); - - verify(mediaPlayer, never()).pause(anyBoolean(), anyBoolean()); - verify(mediaPlayer, never()).resume(); - } - - @Test - public void noChangeIfPlayerStatusIsIndeterminate() { - PlaybackVolumeAdaptor playbackVolumeAdaptor = new PlaybackVolumeAdaptor(); - - when(mediaPlayer.getPlayerStatus()).thenReturn(PlayerStatus.INDETERMINATE); - - FeedMedia feedMedia = mock(FeedMedia.class); - when(mediaPlayer.getPlayable()).thenReturn(feedMedia); - - playbackVolumeAdaptor.adaptVolumeIfNecessary(mediaPlayer, FEED_ID, VolumeReductionSetting.OFF); - - verify(mediaPlayer, never()).pause(anyBoolean(), anyBoolean()); - verify(mediaPlayer, never()).resume(); - } - - @Test - public void noChangeIfPlayerStatusIsStopped() { - PlaybackVolumeAdaptor playbackVolumeAdaptor = new PlaybackVolumeAdaptor(); - - when(mediaPlayer.getPlayerStatus()).thenReturn(PlayerStatus.STOPPED); - - FeedMedia feedMedia = mock(FeedMedia.class); - when(mediaPlayer.getPlayable()).thenReturn(feedMedia); - - playbackVolumeAdaptor.adaptVolumeIfNecessary(mediaPlayer, FEED_ID, VolumeReductionSetting.OFF); - - verify(mediaPlayer, never()).pause(anyBoolean(), anyBoolean()); - verify(mediaPlayer, never()).resume(); - } - - @Test - public void noChangeIfPlayableIsNoItemOfAffectedFeed() { - PlaybackVolumeAdaptor playbackVolumeAdaptor = new PlaybackVolumeAdaptor(); - - when(mediaPlayer.getPlayerStatus()).thenReturn(PlayerStatus.PLAYING); - - FeedMedia feedMedia = mock(FeedMedia.class); - when(mediaPlayer.getPlayable()).thenReturn(feedMedia); - Feed feed = mockFeed(feedMedia, FEED_ID); - when(feed.getIdentifyingValue()).thenReturn("wrongFeedId"); - - playbackVolumeAdaptor.adaptVolumeIfNecessary(mediaPlayer, FEED_ID, VolumeReductionSetting.OFF); - - verify(mediaPlayer, never()).pause(anyBoolean(), anyBoolean()); - verify(mediaPlayer, never()).resume(); - } - - @Test - public void adaptsPreferencesForLoadedFeedMediaIfPlayerStatusIsPaused() { - PlaybackVolumeAdaptor playbackVolumeAdaptor = new PlaybackVolumeAdaptor(); - - when(mediaPlayer.getPlayerStatus()).thenReturn(PlayerStatus.PAUSED); - - FeedMedia feedMedia = mock(FeedMedia.class); - when(mediaPlayer.getPlayable()).thenReturn(feedMedia); - FeedPreferences feedPreferences = mockFeedPreferences(feedMedia, FEED_ID); - - playbackVolumeAdaptor.adaptVolumeIfNecessary(mediaPlayer, FEED_ID, VolumeReductionSetting.LIGHT); - - verify(feedPreferences, times(1)).setVolumeReductionSetting(VolumeReductionSetting.LIGHT); - - verify(mediaPlayer, never()).pause(anyBoolean(), anyBoolean()); - verify(mediaPlayer, never()).resume(); - } - - @Test - public void adaptsPreferencesForLoadedFeedMediaIfPlayerStatusIsPrepared() { - PlaybackVolumeAdaptor playbackVolumeAdaptor = new PlaybackVolumeAdaptor(); - - when(mediaPlayer.getPlayerStatus()).thenReturn(PlayerStatus.PREPARED); - - FeedMedia feedMedia = mock(FeedMedia.class); - when(mediaPlayer.getPlayable()).thenReturn(feedMedia); - FeedPreferences feedPreferences = mockFeedPreferences(feedMedia, FEED_ID); - - playbackVolumeAdaptor.adaptVolumeIfNecessary(mediaPlayer, FEED_ID, VolumeReductionSetting.LIGHT); - - verify(feedPreferences, times(1)).setVolumeReductionSetting(VolumeReductionSetting.LIGHT); - - verify(mediaPlayer, never()).pause(anyBoolean(), anyBoolean()); - verify(mediaPlayer, never()).resume(); - } - - @Test - public void adaptsPreferencesForLoadedFeedMediaIfPlayerStatusIsInitializing() { - PlaybackVolumeAdaptor playbackVolumeAdaptor = new PlaybackVolumeAdaptor(); - - when(mediaPlayer.getPlayerStatus()).thenReturn(PlayerStatus.INITIALIZING); - - FeedMedia feedMedia = mock(FeedMedia.class); - when(mediaPlayer.getPlayable()).thenReturn(feedMedia); - FeedPreferences feedPreferences = mockFeedPreferences(feedMedia, FEED_ID); - - playbackVolumeAdaptor.adaptVolumeIfNecessary(mediaPlayer, FEED_ID, VolumeReductionSetting.LIGHT); - - verify(feedPreferences, times(1)).setVolumeReductionSetting(VolumeReductionSetting.LIGHT); - - verify(mediaPlayer, never()).pause(anyBoolean(), anyBoolean()); - verify(mediaPlayer, never()).resume(); - } - - @Test - public void adaptsPreferencesForLoadedFeedMediaIfPlayerStatusIsPreparing() { - PlaybackVolumeAdaptor playbackVolumeAdaptor = new PlaybackVolumeAdaptor(); - - when(mediaPlayer.getPlayerStatus()).thenReturn(PlayerStatus.PREPARING); - - FeedMedia feedMedia = mock(FeedMedia.class); - when(mediaPlayer.getPlayable()).thenReturn(feedMedia); - FeedPreferences feedPreferences = mockFeedPreferences(feedMedia, FEED_ID); - - playbackVolumeAdaptor.adaptVolumeIfNecessary(mediaPlayer, FEED_ID, VolumeReductionSetting.LIGHT); - - verify(feedPreferences, times(1)).setVolumeReductionSetting(VolumeReductionSetting.LIGHT); - - verify(mediaPlayer, never()).pause(anyBoolean(), anyBoolean()); - verify(mediaPlayer, never()).resume(); - } - - @Test - public void adaptsPreferencesForLoadedFeedMediaIfPlayerStatusIsSeeking() { - PlaybackVolumeAdaptor playbackVolumeAdaptor = new PlaybackVolumeAdaptor(); - - when(mediaPlayer.getPlayerStatus()).thenReturn(PlayerStatus.SEEKING); - - FeedMedia feedMedia = mock(FeedMedia.class); - when(mediaPlayer.getPlayable()).thenReturn(feedMedia); - FeedPreferences feedPreferences = mockFeedPreferences(feedMedia, FEED_ID); - - playbackVolumeAdaptor.adaptVolumeIfNecessary(mediaPlayer, FEED_ID, VolumeReductionSetting.LIGHT); - - verify(feedPreferences, times(1)).setVolumeReductionSetting(VolumeReductionSetting.LIGHT); - - verify(mediaPlayer, never()).pause(anyBoolean(), anyBoolean()); - verify(mediaPlayer, never()).resume(); - } - - @Test - public void adaptsPreferencesAndForcesVolumeChangeForLoadedFeedMediaIfPlayerStatusIsPlaying() { - PlaybackVolumeAdaptor playbackVolumeAdaptor = new PlaybackVolumeAdaptor(); - - when(mediaPlayer.getPlayerStatus()).thenReturn(PlayerStatus.PLAYING); - - FeedMedia feedMedia = mock(FeedMedia.class); - when(mediaPlayer.getPlayable()).thenReturn(feedMedia); - FeedPreferences feedPreferences = mockFeedPreferences(feedMedia, FEED_ID); - - playbackVolumeAdaptor.adaptVolumeIfNecessary(mediaPlayer, FEED_ID, VolumeReductionSetting.HEAVY); - - verify(feedPreferences, times(1)).setVolumeReductionSetting(VolumeReductionSetting.HEAVY); - - verify(mediaPlayer, times(1)).pause(false, false); - verify(mediaPlayer, times(1)).resume(); - } - - private FeedPreferences mockFeedPreferences(FeedMedia feedMedia, String feedId) { - Feed feed = mockFeed(feedMedia, feedId); - FeedPreferences feedPreferences = mock(FeedPreferences.class); - when(feed.getPreferences()).thenReturn(feedPreferences); - return feedPreferences; - } - - private Feed mockFeed(FeedMedia feedMedia, String feedId) { - FeedItem feedItem = mock(FeedItem.class); - when(feedMedia.getItem()).thenReturn(feedItem); - Feed feed = mock(Feed.class); - when(feed.getIdentifyingValue()).thenReturn(feedId); - when(feedItem.getFeed()).thenReturn(feed); - return feed; - } -} diff --git a/core/src/test/java/de/danoeh/antennapod/core/service/playback/PlaybackVolumeUpdaterTest.java b/core/src/test/java/de/danoeh/antennapod/core/service/playback/PlaybackVolumeUpdaterTest.java new file mode 100644 index 000000000..4ebe4e5ba --- /dev/null +++ b/core/src/test/java/de/danoeh/antennapod/core/service/playback/PlaybackVolumeUpdaterTest.java @@ -0,0 +1,230 @@ +package de.danoeh.antennapod.core.service.playback; + +import de.danoeh.antennapod.core.feed.Feed; +import de.danoeh.antennapod.core.feed.FeedItem; +import de.danoeh.antennapod.core.feed.FeedMedia; +import de.danoeh.antennapod.core.feed.FeedPreferences; +import de.danoeh.antennapod.core.feed.VolumeReductionSetting; +import de.danoeh.antennapod.core.util.playback.Playable; +import org.junit.Before; +import org.junit.Test; + +import static org.mockito.Mockito.anyBoolean; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +public class PlaybackVolumeUpdaterTest { + + private static final String FEED_ID = "feedId"; + + private PlaybackServiceMediaPlayer mediaPlayer; + + @Before + public void setUp() throws Exception { + mediaPlayer = mock(PlaybackServiceMediaPlayer.class); + } + + @Test + public void noChangeIfNoFeedMediaPlaying() { + PlaybackVolumeUpdater playbackVolumeUpdater = new PlaybackVolumeUpdater(); + + when(mediaPlayer.getPlayerStatus()).thenReturn(PlayerStatus.PAUSED); + + Playable noFeedMedia = mock(Playable.class); + when(mediaPlayer.getPlayable()).thenReturn(noFeedMedia); + + playbackVolumeUpdater.updateVolumeIfNecessary(mediaPlayer, FEED_ID, VolumeReductionSetting.OFF); + + verify(mediaPlayer, never()).pause(anyBoolean(), anyBoolean()); + verify(mediaPlayer, never()).resume(); + } + + @Test + public void noChangeIfPlayerStatusIsError() { + PlaybackVolumeUpdater playbackVolumeUpdater = new PlaybackVolumeUpdater(); + + when(mediaPlayer.getPlayerStatus()).thenReturn(PlayerStatus.ERROR); + + FeedMedia feedMedia = mock(FeedMedia.class); + when(mediaPlayer.getPlayable()).thenReturn(feedMedia); + + playbackVolumeUpdater.updateVolumeIfNecessary(mediaPlayer, FEED_ID, VolumeReductionSetting.OFF); + + verify(mediaPlayer, never()).pause(anyBoolean(), anyBoolean()); + verify(mediaPlayer, never()).resume(); + } + + @Test + public void noChangeIfPlayerStatusIsIndeterminate() { + PlaybackVolumeUpdater playbackVolumeUpdater = new PlaybackVolumeUpdater(); + + when(mediaPlayer.getPlayerStatus()).thenReturn(PlayerStatus.INDETERMINATE); + + FeedMedia feedMedia = mock(FeedMedia.class); + when(mediaPlayer.getPlayable()).thenReturn(feedMedia); + + playbackVolumeUpdater.updateVolumeIfNecessary(mediaPlayer, FEED_ID, VolumeReductionSetting.OFF); + + verify(mediaPlayer, never()).pause(anyBoolean(), anyBoolean()); + verify(mediaPlayer, never()).resume(); + } + + @Test + public void noChangeIfPlayerStatusIsStopped() { + PlaybackVolumeUpdater playbackVolumeUpdater = new PlaybackVolumeUpdater(); + + when(mediaPlayer.getPlayerStatus()).thenReturn(PlayerStatus.STOPPED); + + FeedMedia feedMedia = mock(FeedMedia.class); + when(mediaPlayer.getPlayable()).thenReturn(feedMedia); + + playbackVolumeUpdater.updateVolumeIfNecessary(mediaPlayer, FEED_ID, VolumeReductionSetting.OFF); + + verify(mediaPlayer, never()).pause(anyBoolean(), anyBoolean()); + verify(mediaPlayer, never()).resume(); + } + + @Test + public void noChangeIfPlayableIsNoItemOfAffectedFeed() { + PlaybackVolumeUpdater playbackVolumeUpdater = new PlaybackVolumeUpdater(); + + when(mediaPlayer.getPlayerStatus()).thenReturn(PlayerStatus.PLAYING); + + FeedMedia feedMedia = mock(FeedMedia.class); + when(mediaPlayer.getPlayable()).thenReturn(feedMedia); + Feed feed = mockFeed(feedMedia, FEED_ID); + when(feed.getIdentifyingValue()).thenReturn("wrongFeedId"); + + playbackVolumeUpdater.updateVolumeIfNecessary(mediaPlayer, FEED_ID, VolumeReductionSetting.OFF); + + verify(mediaPlayer, never()).pause(anyBoolean(), anyBoolean()); + verify(mediaPlayer, never()).resume(); + } + + @Test + public void updatesPreferencesForLoadedFeedMediaIfPlayerStatusIsPaused() { + PlaybackVolumeUpdater playbackVolumeUpdater = new PlaybackVolumeUpdater(); + + when(mediaPlayer.getPlayerStatus()).thenReturn(PlayerStatus.PAUSED); + + FeedMedia feedMedia = mock(FeedMedia.class); + when(mediaPlayer.getPlayable()).thenReturn(feedMedia); + FeedPreferences feedPreferences = mockFeedPreferences(feedMedia, FEED_ID); + + playbackVolumeUpdater.updateVolumeIfNecessary(mediaPlayer, FEED_ID, VolumeReductionSetting.LIGHT); + + verify(feedPreferences, times(1)).setVolumeReductionSetting(VolumeReductionSetting.LIGHT); + + verify(mediaPlayer, never()).pause(anyBoolean(), anyBoolean()); + verify(mediaPlayer, never()).resume(); + } + + @Test + public void updatesPreferencesForLoadedFeedMediaIfPlayerStatusIsPrepared() { + PlaybackVolumeUpdater playbackVolumeUpdater = new PlaybackVolumeUpdater(); + + when(mediaPlayer.getPlayerStatus()).thenReturn(PlayerStatus.PREPARED); + + FeedMedia feedMedia = mock(FeedMedia.class); + when(mediaPlayer.getPlayable()).thenReturn(feedMedia); + FeedPreferences feedPreferences = mockFeedPreferences(feedMedia, FEED_ID); + + playbackVolumeUpdater.updateVolumeIfNecessary(mediaPlayer, FEED_ID, VolumeReductionSetting.LIGHT); + + verify(feedPreferences, times(1)).setVolumeReductionSetting(VolumeReductionSetting.LIGHT); + + verify(mediaPlayer, never()).pause(anyBoolean(), anyBoolean()); + verify(mediaPlayer, never()).resume(); + } + + @Test + public void updatesPreferencesForLoadedFeedMediaIfPlayerStatusIsInitializing() { + PlaybackVolumeUpdater playbackVolumeUpdater = new PlaybackVolumeUpdater(); + + when(mediaPlayer.getPlayerStatus()).thenReturn(PlayerStatus.INITIALIZING); + + FeedMedia feedMedia = mock(FeedMedia.class); + when(mediaPlayer.getPlayable()).thenReturn(feedMedia); + FeedPreferences feedPreferences = mockFeedPreferences(feedMedia, FEED_ID); + + playbackVolumeUpdater.updateVolumeIfNecessary(mediaPlayer, FEED_ID, VolumeReductionSetting.LIGHT); + + verify(feedPreferences, times(1)).setVolumeReductionSetting(VolumeReductionSetting.LIGHT); + + verify(mediaPlayer, never()).pause(anyBoolean(), anyBoolean()); + verify(mediaPlayer, never()).resume(); + } + + @Test + public void updatesPreferencesForLoadedFeedMediaIfPlayerStatusIsPreparing() { + PlaybackVolumeUpdater playbackVolumeUpdater = new PlaybackVolumeUpdater(); + + when(mediaPlayer.getPlayerStatus()).thenReturn(PlayerStatus.PREPARING); + + FeedMedia feedMedia = mock(FeedMedia.class); + when(mediaPlayer.getPlayable()).thenReturn(feedMedia); + FeedPreferences feedPreferences = mockFeedPreferences(feedMedia, FEED_ID); + + playbackVolumeUpdater.updateVolumeIfNecessary(mediaPlayer, FEED_ID, VolumeReductionSetting.LIGHT); + + verify(feedPreferences, times(1)).setVolumeReductionSetting(VolumeReductionSetting.LIGHT); + + verify(mediaPlayer, never()).pause(anyBoolean(), anyBoolean()); + verify(mediaPlayer, never()).resume(); + } + + @Test + public void updatesPreferencesForLoadedFeedMediaIfPlayerStatusIsSeeking() { + PlaybackVolumeUpdater playbackVolumeUpdater = new PlaybackVolumeUpdater(); + + when(mediaPlayer.getPlayerStatus()).thenReturn(PlayerStatus.SEEKING); + + FeedMedia feedMedia = mock(FeedMedia.class); + when(mediaPlayer.getPlayable()).thenReturn(feedMedia); + FeedPreferences feedPreferences = mockFeedPreferences(feedMedia, FEED_ID); + + playbackVolumeUpdater.updateVolumeIfNecessary(mediaPlayer, FEED_ID, VolumeReductionSetting.LIGHT); + + verify(feedPreferences, times(1)).setVolumeReductionSetting(VolumeReductionSetting.LIGHT); + + verify(mediaPlayer, never()).pause(anyBoolean(), anyBoolean()); + verify(mediaPlayer, never()).resume(); + } + + @Test + public void updatesPreferencesAndForcesVolumeChangeForLoadedFeedMediaIfPlayerStatusIsPlaying() { + PlaybackVolumeUpdater playbackVolumeUpdater = new PlaybackVolumeUpdater(); + + when(mediaPlayer.getPlayerStatus()).thenReturn(PlayerStatus.PLAYING); + + FeedMedia feedMedia = mock(FeedMedia.class); + when(mediaPlayer.getPlayable()).thenReturn(feedMedia); + FeedPreferences feedPreferences = mockFeedPreferences(feedMedia, FEED_ID); + + playbackVolumeUpdater.updateVolumeIfNecessary(mediaPlayer, FEED_ID, VolumeReductionSetting.HEAVY); + + verify(feedPreferences, times(1)).setVolumeReductionSetting(VolumeReductionSetting.HEAVY); + + verify(mediaPlayer, times(1)).pause(false, false); + verify(mediaPlayer, times(1)).resume(); + } + + private FeedPreferences mockFeedPreferences(FeedMedia feedMedia, String feedId) { + Feed feed = mockFeed(feedMedia, feedId); + FeedPreferences feedPreferences = mock(FeedPreferences.class); + when(feed.getPreferences()).thenReturn(feedPreferences); + return feedPreferences; + } + + private Feed mockFeed(FeedMedia feedMedia, String feedId) { + FeedItem feedItem = mock(FeedItem.class); + when(feedMedia.getItem()).thenReturn(feedItem); + Feed feed = mock(Feed.class); + when(feed.getIdentifyingValue()).thenReturn(feedId); + when(feedItem.getFeed()).thenReturn(feed); + return feed; + } +} -- cgit v1.2.3 From 14db72ac3532f2258df301074bc781d691d68658 Mon Sep 17 00:00:00 2001 From: Max Bechtold Date: Thu, 17 Oct 2019 11:54:11 +0200 Subject: #3248 Merge FeedVolumeReduction into VolumeReductionSetting --- .../core/feed/VolumeReductionSetting.java | 14 +++++--- .../core/service/playback/FeedVolumeReduction.java | 16 ---------- .../core/service/playback/LocalPSMP.java | 7 ++-- .../core/feed/VolumeReductionSettingTest.java | 18 ++++++++++- .../service/playback/FeedVolumeReductionTest.java | 37 ---------------------- 5 files changed, 30 insertions(+), 62 deletions(-) delete mode 100644 core/src/main/java/de/danoeh/antennapod/core/service/playback/FeedVolumeReduction.java delete mode 100644 core/src/test/java/de/danoeh/antennapod/core/service/playback/FeedVolumeReductionTest.java (limited to 'core/src') diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/VolumeReductionSetting.java b/core/src/main/java/de/danoeh/antennapod/core/feed/VolumeReductionSetting.java index ec6db4872..53808580a 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/feed/VolumeReductionSetting.java +++ b/core/src/main/java/de/danoeh/antennapod/core/feed/VolumeReductionSetting.java @@ -1,14 +1,16 @@ package de.danoeh.antennapod.core.feed; public enum VolumeReductionSetting { - OFF(0), - LIGHT(1), - HEAVY(2); + OFF(0, 1.0f), + LIGHT(1, 0.5f), + HEAVY(2, 0.2f); private final int value; + private float reductionFactor; - VolumeReductionSetting(int value) { + VolumeReductionSetting(int value, float reductionFactor) { this.value = value; + this.reductionFactor = reductionFactor; } public static VolumeReductionSetting fromInteger(int value) { @@ -23,4 +25,8 @@ public enum VolumeReductionSetting { public int toInteger() { return value; } + + public float getReductionFactor() { + return reductionFactor; + } } diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/FeedVolumeReduction.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/FeedVolumeReduction.java deleted file mode 100644 index 608e8375b..000000000 --- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/FeedVolumeReduction.java +++ /dev/null @@ -1,16 +0,0 @@ -package de.danoeh.antennapod.core.service.playback; - -import de.danoeh.antennapod.core.feed.FeedPreferences; -import de.danoeh.antennapod.core.feed.VolumeReductionSetting; - -public class FeedVolumeReduction { - float getReductionFactor(FeedPreferences preferences) { - VolumeReductionSetting volumeReductionSetting = preferences.getVolumeReductionSetting(); - if (volumeReductionSetting == VolumeReductionSetting.LIGHT) { - return 0.5f; - } else if (volumeReductionSetting == VolumeReductionSetting.HEAVY) { - return 0.2f; - } - return 1.0f; - } -} diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java index a09d6cb19..e5dd292f0 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java @@ -29,6 +29,7 @@ import java.util.concurrent.locks.ReentrantLock; import de.danoeh.antennapod.core.feed.FeedMedia; import de.danoeh.antennapod.core.feed.FeedPreferences; import de.danoeh.antennapod.core.feed.MediaType; +import de.danoeh.antennapod.core.feed.VolumeReductionSetting; import de.danoeh.antennapod.core.preferences.UserPreferences; import de.danoeh.antennapod.core.util.RewindAfterPauseUtils; import de.danoeh.antennapod.core.util.playback.AudioPlayer; @@ -55,8 +56,6 @@ public class LocalPSMP extends PlaybackServiceMediaPlayer { private volatile boolean pausedBecauseOfTransientAudiofocusLoss; private volatile Pair videoSize; - private final FeedVolumeReduction feedVolumeReduction; - /** * Some asynchronous calls might change the state of the MediaPlayer object. Therefore calls in other threads * have to wait until these operations have finished. @@ -142,7 +141,6 @@ public class LocalPSMP extends PlaybackServiceMediaPlayer { super(context, callback); this.audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); this.playerLock = new PlayerLock(); - this.feedVolumeReduction = new FeedVolumeReduction(); this.startWhenPrepared = new AtomicBoolean(false); executor = new PlayerExecutor(); @@ -676,7 +674,8 @@ public class LocalPSMP extends PlaybackServiceMediaPlayer { if (playable instanceof FeedMedia) { FeedMedia feedMedia = (FeedMedia) playable; FeedPreferences preferences = feedMedia.getItem().getFeed().getPreferences(); - float reductionFactor = feedVolumeReduction.getReductionFactor(preferences); + VolumeReductionSetting volumeReductionSetting = preferences.getVolumeReductionSetting(); + float reductionFactor = volumeReductionSetting.getReductionFactor(); volumeLeft *= reductionFactor; volumeRight *= reductionFactor; } diff --git a/core/src/test/java/de/danoeh/antennapod/core/feed/VolumeReductionSettingTest.java b/core/src/test/java/de/danoeh/antennapod/core/feed/VolumeReductionSettingTest.java index 26c2132fe..a97fb6f20 100644 --- a/core/src/test/java/de/danoeh/antennapod/core/feed/VolumeReductionSettingTest.java +++ b/core/src/test/java/de/danoeh/antennapod/core/feed/VolumeReductionSettingTest.java @@ -1,11 +1,12 @@ package de.danoeh.antennapod.core.feed; - import org.junit.Test; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; public class VolumeReductionSettingTest { @@ -45,4 +46,19 @@ public class VolumeReductionSettingTest { public void cannotMapValuesOutOfRange() { VolumeReductionSetting.fromInteger(3); } + + @Test + public void noReductionIfTurnedOff() { + float reductionFactor = VolumeReductionSetting.OFF.getReductionFactor(); + assertEquals(1.0f, reductionFactor, 0.01f); + } + + @Test + public void lightReductionYieldsHigherValueThanHeavyReduction() { + float lightReductionFactor = VolumeReductionSetting.LIGHT.getReductionFactor(); + + float heavyReductionFactor = VolumeReductionSetting.HEAVY.getReductionFactor(); + + assertTrue("Light reduction must have higher factor than heavy reduction", lightReductionFactor > heavyReductionFactor); + } } \ No newline at end of file diff --git a/core/src/test/java/de/danoeh/antennapod/core/service/playback/FeedVolumeReductionTest.java b/core/src/test/java/de/danoeh/antennapod/core/service/playback/FeedVolumeReductionTest.java deleted file mode 100644 index 109b361fe..000000000 --- a/core/src/test/java/de/danoeh/antennapod/core/service/playback/FeedVolumeReductionTest.java +++ /dev/null @@ -1,37 +0,0 @@ -package de.danoeh.antennapod.core.service.playback; - -import de.danoeh.antennapod.core.feed.FeedPreferences; -import de.danoeh.antennapod.core.feed.VolumeReductionSetting; -import org.junit.Test; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -public class FeedVolumeReductionTest { - - @Test - public void noReductionIfTurnedOff() { - FeedPreferences feedPreferences = mock(FeedPreferences.class); - when(feedPreferences.getVolumeReductionSetting()).thenReturn(VolumeReductionSetting.OFF); - - FeedVolumeReduction feedVolumeReduction = new FeedVolumeReduction(); - float reductionFactor = feedVolumeReduction.getReductionFactor(feedPreferences); - assertEquals(1.0f, reductionFactor, 0.01f ); - } - - @Test - public void lightReductionYieldsHigherValueThanHeavyReduction() { - FeedPreferences feedPreferences = mock(FeedPreferences.class); - FeedVolumeReduction feedVolumeReduction = new FeedVolumeReduction(); - - when(feedPreferences.getVolumeReductionSetting()).thenReturn(VolumeReductionSetting.LIGHT); - float lightReductionFactor = feedVolumeReduction.getReductionFactor(feedPreferences); - - when(feedPreferences.getVolumeReductionSetting()).thenReturn(VolumeReductionSetting.HEAVY); - float heavyReductionFactor = feedVolumeReduction.getReductionFactor(feedPreferences); - - assertTrue("Light reduction must have higher factor than heavy reduction", lightReductionFactor > heavyReductionFactor); - } -} \ No newline at end of file -- cgit v1.2.3 From cc9c8bb63a27deb35f0e234d252e22a73ef6c117 Mon Sep 17 00:00:00 2001 From: Max Bechtold Date: Thu, 17 Oct 2019 12:06:15 +0200 Subject: #3248 Extract @string resource for summary --- core/src/main/res/values/strings.xml | 1 + 1 file changed, 1 insertion(+) (limited to 'core/src') diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index 5b6e9eed6..2f3375fe0 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -90,6 +90,7 @@ The new Auto Download setting will automatically be applied to new episodes.\nDo you also want to apply it to previously published episodes? Auto Delete Episode Volume Reduction + Turn down volume for episodes of this feed: \%s Off Light Heavy -- cgit v1.2.3 From 12be60f1ba7ff88da9b3e5bc06f501892f3d7ba4 Mon Sep 17 00:00:00 2001 From: Max Bechtold Date: Sat, 21 Dec 2019 12:21:05 +0100 Subject: resolve review remarks w.r.t naming: volume reduction -> volume adaption --- .../java/de/danoeh/antennapod/core/feed/Feed.java | 2 +- .../antennapod/core/feed/FeedPreferences.java | 26 ++++----- .../core/feed/VolumeAdaptionSetting.java | 32 +++++++++++ .../core/feed/VolumeReductionSetting.java | 32 ----------- .../core/service/download/DownloadService.java | 1 - .../service/download/handler/FeedParserTask.java | 4 +- .../core/service/playback/LocalPSMP.java | 10 ++-- .../core/service/playback/PlaybackService.java | 28 +++++----- .../service/playback/PlaybackVolumeUpdater.java | 10 ++-- .../danoeh/antennapod/core/storage/DBUpgrader.java | 2 +- .../antennapod/core/storage/PodDBAdapter.java | 9 ++- .../core/feed/VolumeAdaptionSettingTest.java | 64 ++++++++++++++++++++++ .../core/feed/VolumeReductionSettingTest.java | 64 ---------------------- .../playback/PlaybackVolumeUpdaterTest.java | 36 ++++++------ 14 files changed, 158 insertions(+), 162 deletions(-) create mode 100644 core/src/main/java/de/danoeh/antennapod/core/feed/VolumeAdaptionSetting.java delete mode 100644 core/src/main/java/de/danoeh/antennapod/core/feed/VolumeReductionSetting.java create mode 100644 core/src/test/java/de/danoeh/antennapod/core/feed/VolumeAdaptionSettingTest.java delete mode 100644 core/src/test/java/de/danoeh/antennapod/core/feed/VolumeReductionSettingTest.java (limited to 'core/src') diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/Feed.java b/core/src/main/java/de/danoeh/antennapod/core/feed/Feed.java index 58a21760b..b1598f111 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/feed/Feed.java +++ b/core/src/main/java/de/danoeh/antennapod/core/feed/Feed.java @@ -171,7 +171,7 @@ public class Feed extends FeedFile implements ImageResource { */ public Feed(String url, String lastUpdate, String title, String username, String password) { this(url, lastUpdate, title); - preferences = new FeedPreferences(0, true, FeedPreferences.AutoDeleteAction.GLOBAL, VolumeReductionSetting.OFF, username, password); + preferences = new FeedPreferences(0, true, FeedPreferences.AutoDeleteAction.GLOBAL, VolumeAdaptionSetting.OFF, username, password); } public static Feed fromCursor(Cursor cursor) { diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedPreferences.java b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedPreferences.java index cb5a59a3b..b24c52266 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedPreferences.java +++ b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedPreferences.java @@ -29,22 +29,22 @@ public class FeedPreferences { } private AutoDeleteAction auto_delete_action; - private VolumeReductionSetting volumeReductionSetting; + private VolumeAdaptionSetting volumeAdaptionSetting; private String username; private String password; private float feedPlaybackSpeed; - public FeedPreferences(long feedID, boolean autoDownload, AutoDeleteAction auto_delete_action, VolumeReductionSetting volumeReductionSetting, String username, String password) { - this(feedID, autoDownload, true, auto_delete_action, volumeReductionSetting, username, password, new FeedFilter(), SPEED_USE_GLOBAL); + public FeedPreferences(long feedID, boolean autoDownload, AutoDeleteAction auto_delete_action, VolumeAdaptionSetting volumeAdaptionSetting, String username, String password) { + this(feedID, autoDownload, true, auto_delete_action, volumeAdaptionSetting, username, password, new FeedFilter(), SPEED_USE_GLOBAL); } - private FeedPreferences(long feedID, boolean autoDownload, boolean keepUpdated, AutoDeleteAction auto_delete_action, VolumeReductionSetting volumeReductionSetting, String username, String password, @NonNull FeedFilter filter, float feedPlaybackSpeed) { + private FeedPreferences(long feedID, boolean autoDownload, boolean keepUpdated, AutoDeleteAction auto_delete_action, VolumeAdaptionSetting volumeAdaptionSetting, String username, String password, @NonNull FeedFilter filter, float feedPlaybackSpeed) { this.feedID = feedID; this.autoDownload = autoDownload; this.keepUpdated = keepUpdated; this.auto_delete_action = auto_delete_action; - this.volumeReductionSetting = volumeReductionSetting; + this.volumeAdaptionSetting = volumeAdaptionSetting; this.username = username; this.password = password; this.filter = filter; @@ -56,7 +56,7 @@ public class FeedPreferences { int indexAutoDownload = cursor.getColumnIndex(PodDBAdapter.KEY_AUTO_DOWNLOAD); int indexAutoRefresh = cursor.getColumnIndex(PodDBAdapter.KEY_KEEP_UPDATED); int indexAutoDeleteAction = cursor.getColumnIndex(PodDBAdapter.KEY_AUTO_DELETE_ACTION); - int indexVolumeReduction = cursor.getColumnIndex(PodDBAdapter.KEY_FEED_VOLUME_REDUCTION); + int indexVolumeAdaption = cursor.getColumnIndex(PodDBAdapter.KEY_FEED_VOLUME_ADAPTION); int indexUsername = cursor.getColumnIndex(PodDBAdapter.KEY_USERNAME); int indexPassword = cursor.getColumnIndex(PodDBAdapter.KEY_PASSWORD); int indexIncludeFilter = cursor.getColumnIndex(PodDBAdapter.KEY_INCLUDE_FILTER); @@ -68,14 +68,14 @@ public class FeedPreferences { boolean autoRefresh = cursor.getInt(indexAutoRefresh) > 0; int autoDeleteActionIndex = cursor.getInt(indexAutoDeleteAction); AutoDeleteAction autoDeleteAction = AutoDeleteAction.values()[autoDeleteActionIndex]; - int volumeReductionValue = cursor.getInt(indexVolumeReduction); - VolumeReductionSetting volumeReductionSetting = VolumeReductionSetting.fromInteger(volumeReductionValue); + int volumeAdaptionValue = cursor.getInt(indexVolumeAdaption); + VolumeAdaptionSetting volumeAdaptionSetting = VolumeAdaptionSetting.fromInteger(volumeAdaptionValue); String username = cursor.getString(indexUsername); String password = cursor.getString(indexPassword); String includeFilter = cursor.getString(indexIncludeFilter); String excludeFilter = cursor.getString(indexExcludeFilter); float feedPlaybackSpeed = cursor.getFloat(indexFeedPlaybackSpeed); - return new FeedPreferences(feedId, autoDownload, autoRefresh, autoDeleteAction, volumeReductionSetting, username, password, new FeedFilter(includeFilter, excludeFilter), feedPlaybackSpeed); + return new FeedPreferences(feedId, autoDownload, autoRefresh, autoDeleteAction, volumeAdaptionSetting, username, password, new FeedFilter(includeFilter, excludeFilter), feedPlaybackSpeed); } /** @@ -151,16 +151,16 @@ public class FeedPreferences { return auto_delete_action; } - public VolumeReductionSetting getVolumeReductionSetting() { - return volumeReductionSetting; + public VolumeAdaptionSetting getVolumeAdaptionSetting() { + return volumeAdaptionSetting; } public void setAutoDeleteAction(AutoDeleteAction auto_delete_action) { this.auto_delete_action = auto_delete_action; } - public void setVolumeReductionSetting(VolumeReductionSetting volumeReductionSetting) { - this.volumeReductionSetting = volumeReductionSetting; + public void setVolumeAdaptionSetting(VolumeAdaptionSetting volumeAdaptionSetting) { + this.volumeAdaptionSetting = volumeAdaptionSetting; } public boolean getCurrentAutoDelete() { diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/VolumeAdaptionSetting.java b/core/src/main/java/de/danoeh/antennapod/core/feed/VolumeAdaptionSetting.java new file mode 100644 index 000000000..bf4fc582a --- /dev/null +++ b/core/src/main/java/de/danoeh/antennapod/core/feed/VolumeAdaptionSetting.java @@ -0,0 +1,32 @@ +package de.danoeh.antennapod.core.feed; + +public enum VolumeAdaptionSetting { + OFF(0, 1.0f), + LIGHT_REDUCTION(1, 0.5f), + HEAVY_REDUCTION(2, 0.2f); + + private final int value; + private float adaptionFactor; + + VolumeAdaptionSetting(int value, float adaptionFactor) { + this.value = value; + this.adaptionFactor = adaptionFactor; + } + + public static VolumeAdaptionSetting fromInteger(int value) { + for (VolumeAdaptionSetting setting : values()) { + if (setting.value == value) { + return setting; + } + } + throw new IllegalArgumentException("Cannot map value to VolumeAdaptionSetting: " + value); + } + + public int toInteger() { + return value; + } + + public float getAdaptionFactor() { + return adaptionFactor; + } +} diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/VolumeReductionSetting.java b/core/src/main/java/de/danoeh/antennapod/core/feed/VolumeReductionSetting.java deleted file mode 100644 index 53808580a..000000000 --- a/core/src/main/java/de/danoeh/antennapod/core/feed/VolumeReductionSetting.java +++ /dev/null @@ -1,32 +0,0 @@ -package de.danoeh.antennapod.core.feed; - -public enum VolumeReductionSetting { - OFF(0, 1.0f), - LIGHT(1, 0.5f), - HEAVY(2, 0.2f); - - private final int value; - private float reductionFactor; - - VolumeReductionSetting(int value, float reductionFactor) { - this.value = value; - this.reductionFactor = reductionFactor; - } - - public static VolumeReductionSetting fromInteger(int value) { - for (VolumeReductionSetting setting : values()) { - if (setting.value == value) { - return setting; - } - } - throw new IllegalArgumentException("Cannot map value to VolumeReductionSetting: " + value); - } - - public int toInteger() { - return value; - } - - public float getReductionFactor() { - return reductionFactor; - } -} diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java b/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java index 72e080902..7c05293c6 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java @@ -17,7 +17,6 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; -import de.danoeh.antennapod.core.feed.VolumeReductionSetting; import org.apache.commons.io.FileUtils; import org.greenrobot.eventbus.EventBus; diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/download/handler/FeedParserTask.java b/core/src/main/java/de/danoeh/antennapod/core/service/download/handler/FeedParserTask.java index a7cbb4cfe..5900f84fc 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/download/handler/FeedParserTask.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/download/handler/FeedParserTask.java @@ -4,7 +4,7 @@ import android.util.Log; import de.danoeh.antennapod.core.feed.Feed; import de.danoeh.antennapod.core.feed.FeedItem; import de.danoeh.antennapod.core.feed.FeedPreferences; -import de.danoeh.antennapod.core.feed.VolumeReductionSetting; +import de.danoeh.antennapod.core.feed.VolumeAdaptionSetting; import de.danoeh.antennapod.core.service.download.DownloadRequest; import de.danoeh.antennapod.core.service.download.DownloadStatus; import de.danoeh.antennapod.core.storage.DownloadRequester; @@ -38,7 +38,7 @@ public class FeedParserTask implements Callable { feed.setId(request.getFeedfileId()); feed.setDownloaded(true); feed.setPreferences(new FeedPreferences(0, true, FeedPreferences.AutoDeleteAction.GLOBAL, - VolumeReductionSetting.OFF, request.getUsername(), request.getPassword())); + VolumeAdaptionSetting.OFF, request.getUsername(), request.getPassword())); feed.setPageNr(request.getArguments().getInt(DownloadRequester.REQUEST_ARG_PAGE_NR, 0)); DownloadError reason = null; diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java index ead686ae4..8965f5fbf 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java @@ -29,8 +29,8 @@ import java.util.concurrent.locks.ReentrantLock; import de.danoeh.antennapod.core.feed.FeedMedia; import de.danoeh.antennapod.core.feed.FeedPreferences; import de.danoeh.antennapod.core.feed.MediaType; +import de.danoeh.antennapod.core.feed.VolumeAdaptionSetting; import de.danoeh.antennapod.core.feed.util.PlaybackSpeedUtils; -import de.danoeh.antennapod.core.feed.VolumeReductionSetting; import de.danoeh.antennapod.core.preferences.UserPreferences; import de.danoeh.antennapod.core.util.RewindAfterPauseUtils; import de.danoeh.antennapod.core.util.playback.AudioPlayer; @@ -673,10 +673,10 @@ public class LocalPSMP extends PlaybackServiceMediaPlayer { if (playable instanceof FeedMedia) { FeedMedia feedMedia = (FeedMedia) playable; FeedPreferences preferences = feedMedia.getItem().getFeed().getPreferences(); - VolumeReductionSetting volumeReductionSetting = preferences.getVolumeReductionSetting(); - float reductionFactor = volumeReductionSetting.getReductionFactor(); - volumeLeft *= reductionFactor; - volumeRight *= reductionFactor; + VolumeAdaptionSetting volumeAdaptionSetting = preferences.getVolumeAdaptionSetting(); + float adaptionFactor = volumeAdaptionSetting.getAdaptionFactor(); + volumeLeft *= adaptionFactor; + volumeRight *= adaptionFactor; } mediaPlayer.setVolume(volumeLeft, volumeRight); Log.d(TAG, "Media player volume was set to " + volumeLeft + " " + volumeRight); diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java index 8f9aff8f8..8673d2744 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java @@ -1,6 +1,5 @@ package de.danoeh.antennapod.core.service.playback; -import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; import android.app.Service; @@ -58,7 +57,7 @@ import de.danoeh.antennapod.core.feed.FeedItem; import de.danoeh.antennapod.core.feed.FeedMedia; import de.danoeh.antennapod.core.feed.MediaType; import de.danoeh.antennapod.core.feed.SearchResult; -import de.danoeh.antennapod.core.feed.VolumeReductionSetting; +import de.danoeh.antennapod.core.feed.VolumeAdaptionSetting; import de.danoeh.antennapod.core.glide.ApGlideSettings; import de.danoeh.antennapod.core.preferences.PlaybackPreferences; import de.danoeh.antennapod.core.preferences.SleepTimerPreferences; @@ -72,7 +71,6 @@ import de.danoeh.antennapod.core.storage.FeedSearcher; import de.danoeh.antennapod.core.feed.util.ImageResourceUtils; import de.danoeh.antennapod.core.util.IntentUtils; import de.danoeh.antennapod.core.util.NetworkUtils; -import de.danoeh.antennapod.core.util.QueueAccess; import de.danoeh.antennapod.core.util.gui.NotificationUtils; import de.danoeh.antennapod.core.util.playback.ExternalMedia; import de.danoeh.antennapod.core.util.playback.Playable; @@ -139,11 +137,11 @@ public class PlaybackService extends MediaBrowserServiceCompat { public static final String ACTION_PAUSE_PLAY_CURRENT_EPISODE = "action.de.danoeh.antennapod.core.service.pausePlayCurrentEpisode"; /** - * If the PlaybackService receives this action, it will try to apply the supplied volume reduction setting. + * If the PlaybackService receives this action, it will try to apply the supplied volume adaption setting. */ - public static final String ACTION_VOLUME_REDUCTION_CHANGED = "action.de.danoeh.antennapod.core.service.volumedReductionChanged"; - public static final String EXTRA_VOLUME_REDUCTION_SETTING = "PlaybackService.VolumeReductionSettingExtra"; - public static final String EXTRA_VOLUME_REDUCTION_AFFECTED_FEED = "PlaybackService.VolumeReductionSettingAffectedFeed"; + public static final String ACTION_VOLUME_ADAPTION_CHANGED = "action.de.danoeh.antennapod.core.service.volumedAdaptionChanged"; + public static final String EXTRA_VOLUME_ADAPTION_SETTING = "PlaybackService.VolumeAdaptionSettingExtra"; + public static final String EXTRA_VOLUME_ADAPTION_AFFECTED_FEED = "PlaybackService.VolumeAdaptionSettingAffectedFeed"; /** * Custom action used by Android Wear @@ -286,7 +284,7 @@ public class PlaybackService extends MediaBrowserServiceCompat { registerReceiver(audioBecomingNoisy, new IntentFilter(AudioManager.ACTION_AUDIO_BECOMING_NOISY)); registerReceiver(skipCurrentEpisodeReceiver, new IntentFilter(ACTION_SKIP_CURRENT_EPISODE)); registerReceiver(pausePlayCurrentEpisodeReceiver, new IntentFilter(ACTION_PAUSE_PLAY_CURRENT_EPISODE)); - registerReceiver(volumeReductionChangedReceiver, new IntentFilter(ACTION_VOLUME_REDUCTION_CHANGED)); + registerReceiver(volumeAdaptionChangedReceiver, new IntentFilter(ACTION_VOLUME_ADAPTION_CHANGED)); taskManager = new PlaybackServiceTaskManager(this, taskManagerCallback); flavorHelper = new PlaybackServiceFlavorHelper(PlaybackService.this, flavorHelperCallback); @@ -1446,18 +1444,18 @@ public class PlaybackService extends MediaBrowserServiceCompat { } }; - private final BroadcastReceiver volumeReductionChangedReceiver = new BroadcastReceiver() { + private final BroadcastReceiver volumeAdaptionChangedReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { - if (TextUtils.equals(intent.getAction(), ACTION_VOLUME_REDUCTION_CHANGED)) { - Log.d(TAG, "Received ACTION_VOLUME_REDUCTION_CHANGED intent"); + if (TextUtils.equals(intent.getAction(), ACTION_VOLUME_ADAPTION_CHANGED)) { + Log.d(TAG, "Received ACTION_VOLUME_ADAPTION_CHANGED intent"); - String affectedFeed = intent.getStringExtra(EXTRA_VOLUME_REDUCTION_AFFECTED_FEED); - Serializable volumeReductionExtra = intent.getSerializableExtra(EXTRA_VOLUME_REDUCTION_SETTING); - VolumeReductionSetting volumeReductionSetting = (VolumeReductionSetting) volumeReductionExtra; + String affectedFeed = intent.getStringExtra(EXTRA_VOLUME_ADAPTION_AFFECTED_FEED); + Serializable volumeAdaptionExtra = intent.getSerializableExtra(EXTRA_VOLUME_ADAPTION_SETTING); + VolumeAdaptionSetting volumeAdaptionSetting = (VolumeAdaptionSetting) volumeAdaptionExtra; PlaybackVolumeUpdater playbackVolumeUpdater = new PlaybackVolumeUpdater(); - playbackVolumeUpdater.updateVolumeIfNecessary(mediaPlayer, affectedFeed, volumeReductionSetting); + playbackVolumeUpdater.updateVolumeIfNecessary(mediaPlayer, affectedFeed, volumeAdaptionSetting); } } }; diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackVolumeUpdater.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackVolumeUpdater.java index aff742105..9e8f34de5 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackVolumeUpdater.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackVolumeUpdater.java @@ -2,25 +2,25 @@ package de.danoeh.antennapod.core.service.playback; import de.danoeh.antennapod.core.feed.FeedMedia; import de.danoeh.antennapod.core.feed.FeedPreferences; -import de.danoeh.antennapod.core.feed.VolumeReductionSetting; +import de.danoeh.antennapod.core.feed.VolumeAdaptionSetting; import de.danoeh.antennapod.core.util.playback.Playable; class PlaybackVolumeUpdater { - public void updateVolumeIfNecessary(PlaybackServiceMediaPlayer mediaPlayer, String affectedFeedIdentifier, VolumeReductionSetting volumeReductionSetting) { + public void updateVolumeIfNecessary(PlaybackServiceMediaPlayer mediaPlayer, String affectedFeedIdentifier, VolumeAdaptionSetting volumeAdaptionSetting) { Playable playable = mediaPlayer.getPlayable(); boolean isFeedMedia = playable instanceof FeedMedia; boolean isPlayableLoaded = isPlayableLoaded(mediaPlayer.getPlayerStatus()); if (isFeedMedia && isPlayableLoaded) { - updateFeedMediaVolumeIfNecessary(mediaPlayer, affectedFeedIdentifier, volumeReductionSetting, (FeedMedia) playable); + updateFeedMediaVolumeIfNecessary(mediaPlayer, affectedFeedIdentifier, volumeAdaptionSetting, (FeedMedia) playable); } } - private void updateFeedMediaVolumeIfNecessary(PlaybackServiceMediaPlayer mediaPlayer, String affectedFeedIdentifier, VolumeReductionSetting volumeReductionSetting, FeedMedia feedMedia) { + private void updateFeedMediaVolumeIfNecessary(PlaybackServiceMediaPlayer mediaPlayer, String affectedFeedIdentifier, VolumeAdaptionSetting volumeAdaptionSetting, FeedMedia feedMedia) { if (mediaBelongsToAffectedFeed(feedMedia, affectedFeedIdentifier)) { FeedPreferences preferences = feedMedia.getItem().getFeed().getPreferences(); - preferences.setVolumeReductionSetting(volumeReductionSetting); + preferences.setVolumeAdaptionSetting(volumeAdaptionSetting); if (mediaPlayer.getPlayerStatus() == PlayerStatus.PLAYING) { forceUpdateVolume(mediaPlayer); diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DBUpgrader.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DBUpgrader.java index aa1395d9c..bae8f2e7c 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/DBUpgrader.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DBUpgrader.java @@ -300,7 +300,7 @@ class DBUpgrader { + " ADD COLUMN " + PodDBAdapter.KEY_SORT_ORDER + " TEXT"); db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS - + " ADD COLUMN " + PodDBAdapter.KEY_FEED_VOLUME_REDUCTION + " INTEGER DEFAULT 0"); + + " ADD COLUMN " + PodDBAdapter.KEY_FEED_VOLUME_ADAPTION + " INTEGER DEFAULT 0"); } } diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java b/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java index d9f4e319a..a91d9a3a0 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java @@ -12,7 +12,6 @@ import android.database.SQLException; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteDatabase.CursorFactory; import android.database.sqlite.SQLiteOpenHelper; -import android.os.Build; import android.text.TextUtils; import android.util.Log; @@ -97,7 +96,7 @@ public class PodDBAdapter { public static final String KEY_AUTO_DOWNLOAD = "auto_download"; public static final String KEY_KEEP_UPDATED = "keep_updated"; public static final String KEY_AUTO_DELETE_ACTION = "auto_delete_action"; - public static final String KEY_FEED_VOLUME_REDUCTION = "feed_volume_reduction"; + public static final String KEY_FEED_VOLUME_ADAPTION = "feed_volume_adaption"; public static final String KEY_PLAYED_DURATION = "played_duration"; public static final String KEY_USERNAME = "username"; public static final String KEY_PASSWORD = "password"; @@ -146,7 +145,7 @@ public class PodDBAdapter { + KEY_LAST_UPDATE_FAILED + " INTEGER DEFAULT 0," + KEY_AUTO_DELETE_ACTION + " INTEGER DEFAULT 0," + KEY_FEED_PLAYBACK_SPEED + " REAL DEFAULT " + SPEED_USE_GLOBAL + "," - + KEY_FEED_VOLUME_REDUCTION + " INTEGER DEFAULT 0)"; + + KEY_FEED_VOLUME_ADAPTION + " INTEGER DEFAULT 0)"; private static final String CREATE_TABLE_FEED_ITEMS = "CREATE TABLE " + TABLE_NAME_FEED_ITEMS + " (" + TABLE_PRIMARY_KEY + KEY_TITLE @@ -243,7 +242,7 @@ public class PodDBAdapter { TABLE_NAME_FEEDS + "." + KEY_SORT_ORDER, TABLE_NAME_FEEDS + "." + KEY_LAST_UPDATE_FAILED, TABLE_NAME_FEEDS + "." + KEY_AUTO_DELETE_ACTION, - TABLE_NAME_FEEDS + "." + KEY_FEED_VOLUME_REDUCTION, + TABLE_NAME_FEEDS + "." + KEY_FEED_VOLUME_ADAPTION, TABLE_NAME_FEEDS + "." + KEY_INCLUDE_FILTER, TABLE_NAME_FEEDS + "." + KEY_EXCLUDE_FILTER, TABLE_NAME_FEEDS + "." + KEY_FEED_PLAYBACK_SPEED @@ -406,7 +405,7 @@ public class PodDBAdapter { values.put(KEY_AUTO_DOWNLOAD, prefs.getAutoDownload()); values.put(KEY_KEEP_UPDATED, prefs.getKeepUpdated()); values.put(KEY_AUTO_DELETE_ACTION, prefs.getAutoDeleteAction().ordinal()); - values.put(KEY_FEED_VOLUME_REDUCTION, prefs.getVolumeReductionSetting().toInteger()); + values.put(KEY_FEED_VOLUME_ADAPTION, prefs.getVolumeAdaptionSetting().toInteger()); values.put(KEY_USERNAME, prefs.getUsername()); values.put(KEY_PASSWORD, prefs.getPassword()); values.put(KEY_INCLUDE_FILTER, prefs.getFilter().getIncludeFilter()); diff --git a/core/src/test/java/de/danoeh/antennapod/core/feed/VolumeAdaptionSettingTest.java b/core/src/test/java/de/danoeh/antennapod/core/feed/VolumeAdaptionSettingTest.java new file mode 100644 index 000000000..45c86cb83 --- /dev/null +++ b/core/src/test/java/de/danoeh/antennapod/core/feed/VolumeAdaptionSettingTest.java @@ -0,0 +1,64 @@ +package de.danoeh.antennapod.core.feed; + +import org.junit.Test; + +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; + +public class VolumeAdaptionSettingTest { + + @Test + public void mapOffToInteger() { + VolumeAdaptionSetting setting = VolumeAdaptionSetting.OFF; + assertThat(setting.toInteger(), is(equalTo(0))); + } + + @Test + public void mapLightReductionToInteger() { + VolumeAdaptionSetting setting = VolumeAdaptionSetting.LIGHT_REDUCTION; + + assertThat(setting.toInteger(), is(equalTo(1))); + } + + @Test + public void mapHeavyReductionToInteger() { + VolumeAdaptionSetting setting = VolumeAdaptionSetting.HEAVY_REDUCTION; + + assertThat(setting.toInteger(), is(equalTo(2))); + } + + @Test + public void mapIntegerToVolumeAdaptionSetting() { + assertThat(VolumeAdaptionSetting.fromInteger(0), is(equalTo(VolumeAdaptionSetting.OFF))); + assertThat(VolumeAdaptionSetting.fromInteger(1), is(equalTo(VolumeAdaptionSetting.LIGHT_REDUCTION))); + assertThat(VolumeAdaptionSetting.fromInteger(2), is(equalTo(VolumeAdaptionSetting.HEAVY_REDUCTION))); + } + + @Test(expected = IllegalArgumentException.class) + public void cannotMapNegativeValues() { + VolumeAdaptionSetting.fromInteger(-1); + } + + @Test(expected = IllegalArgumentException.class) + public void cannotMapValuesOutOfRange() { + VolumeAdaptionSetting.fromInteger(3); + } + + @Test + public void noAdaptionIfTurnedOff() { + float adaptionFactor = VolumeAdaptionSetting.OFF.getAdaptionFactor(); + assertEquals(1.0f, adaptionFactor, 0.01f); + } + + @Test + public void lightReductionYieldsHigherValueThanHeavyReduction() { + float lightReductionFactor = VolumeAdaptionSetting.LIGHT_REDUCTION.getAdaptionFactor(); + + float heavyReductionFactor = VolumeAdaptionSetting.HEAVY_REDUCTION.getAdaptionFactor(); + + assertTrue("Light reduction must have higher factor than heavy reduction", lightReductionFactor > heavyReductionFactor); + } +} \ No newline at end of file diff --git a/core/src/test/java/de/danoeh/antennapod/core/feed/VolumeReductionSettingTest.java b/core/src/test/java/de/danoeh/antennapod/core/feed/VolumeReductionSettingTest.java deleted file mode 100644 index a97fb6f20..000000000 --- a/core/src/test/java/de/danoeh/antennapod/core/feed/VolumeReductionSettingTest.java +++ /dev/null @@ -1,64 +0,0 @@ -package de.danoeh.antennapod.core.feed; - -import org.junit.Test; - -import static org.hamcrest.Matchers.equalTo; -import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertThat; -import static org.junit.Assert.assertTrue; - -public class VolumeReductionSettingTest { - - @Test - public void mapOffToInteger() { - VolumeReductionSetting setting = VolumeReductionSetting.OFF; - assertThat(setting.toInteger(), is(equalTo(0))); - } - - @Test - public void mapLightToInteger() { - VolumeReductionSetting setting = VolumeReductionSetting.LIGHT; - - assertThat(setting.toInteger(), is(equalTo(1))); - } - - @Test - public void mapHeavyToInteger() { - VolumeReductionSetting setting = VolumeReductionSetting.HEAVY; - - assertThat(setting.toInteger(), is(equalTo(2))); - } - - @Test - public void mapIntegerToVolumeReductionSetting() { - assertThat(VolumeReductionSetting.fromInteger(0), is(equalTo(VolumeReductionSetting.OFF))); - assertThat(VolumeReductionSetting.fromInteger(1), is(equalTo(VolumeReductionSetting.LIGHT))); - assertThat(VolumeReductionSetting.fromInteger(2), is(equalTo(VolumeReductionSetting.HEAVY))); - } - - @Test(expected = IllegalArgumentException.class) - public void cannotMapNegativeValues() { - VolumeReductionSetting.fromInteger(-1); - } - - @Test(expected = IllegalArgumentException.class) - public void cannotMapValuesOutOfRange() { - VolumeReductionSetting.fromInteger(3); - } - - @Test - public void noReductionIfTurnedOff() { - float reductionFactor = VolumeReductionSetting.OFF.getReductionFactor(); - assertEquals(1.0f, reductionFactor, 0.01f); - } - - @Test - public void lightReductionYieldsHigherValueThanHeavyReduction() { - float lightReductionFactor = VolumeReductionSetting.LIGHT.getReductionFactor(); - - float heavyReductionFactor = VolumeReductionSetting.HEAVY.getReductionFactor(); - - assertTrue("Light reduction must have higher factor than heavy reduction", lightReductionFactor > heavyReductionFactor); - } -} \ No newline at end of file diff --git a/core/src/test/java/de/danoeh/antennapod/core/service/playback/PlaybackVolumeUpdaterTest.java b/core/src/test/java/de/danoeh/antennapod/core/service/playback/PlaybackVolumeUpdaterTest.java index 4ebe4e5ba..02c3b6efb 100644 --- a/core/src/test/java/de/danoeh/antennapod/core/service/playback/PlaybackVolumeUpdaterTest.java +++ b/core/src/test/java/de/danoeh/antennapod/core/service/playback/PlaybackVolumeUpdaterTest.java @@ -4,7 +4,7 @@ import de.danoeh.antennapod.core.feed.Feed; import de.danoeh.antennapod.core.feed.FeedItem; import de.danoeh.antennapod.core.feed.FeedMedia; import de.danoeh.antennapod.core.feed.FeedPreferences; -import de.danoeh.antennapod.core.feed.VolumeReductionSetting; +import de.danoeh.antennapod.core.feed.VolumeAdaptionSetting; import de.danoeh.antennapod.core.util.playback.Playable; import org.junit.Before; import org.junit.Test; @@ -36,7 +36,7 @@ public class PlaybackVolumeUpdaterTest { Playable noFeedMedia = mock(Playable.class); when(mediaPlayer.getPlayable()).thenReturn(noFeedMedia); - playbackVolumeUpdater.updateVolumeIfNecessary(mediaPlayer, FEED_ID, VolumeReductionSetting.OFF); + playbackVolumeUpdater.updateVolumeIfNecessary(mediaPlayer, FEED_ID, VolumeAdaptionSetting.OFF); verify(mediaPlayer, never()).pause(anyBoolean(), anyBoolean()); verify(mediaPlayer, never()).resume(); @@ -51,7 +51,7 @@ public class PlaybackVolumeUpdaterTest { FeedMedia feedMedia = mock(FeedMedia.class); when(mediaPlayer.getPlayable()).thenReturn(feedMedia); - playbackVolumeUpdater.updateVolumeIfNecessary(mediaPlayer, FEED_ID, VolumeReductionSetting.OFF); + playbackVolumeUpdater.updateVolumeIfNecessary(mediaPlayer, FEED_ID, VolumeAdaptionSetting.OFF); verify(mediaPlayer, never()).pause(anyBoolean(), anyBoolean()); verify(mediaPlayer, never()).resume(); @@ -66,7 +66,7 @@ public class PlaybackVolumeUpdaterTest { FeedMedia feedMedia = mock(FeedMedia.class); when(mediaPlayer.getPlayable()).thenReturn(feedMedia); - playbackVolumeUpdater.updateVolumeIfNecessary(mediaPlayer, FEED_ID, VolumeReductionSetting.OFF); + playbackVolumeUpdater.updateVolumeIfNecessary(mediaPlayer, FEED_ID, VolumeAdaptionSetting.OFF); verify(mediaPlayer, never()).pause(anyBoolean(), anyBoolean()); verify(mediaPlayer, never()).resume(); @@ -81,7 +81,7 @@ public class PlaybackVolumeUpdaterTest { FeedMedia feedMedia = mock(FeedMedia.class); when(mediaPlayer.getPlayable()).thenReturn(feedMedia); - playbackVolumeUpdater.updateVolumeIfNecessary(mediaPlayer, FEED_ID, VolumeReductionSetting.OFF); + playbackVolumeUpdater.updateVolumeIfNecessary(mediaPlayer, FEED_ID, VolumeAdaptionSetting.OFF); verify(mediaPlayer, never()).pause(anyBoolean(), anyBoolean()); verify(mediaPlayer, never()).resume(); @@ -98,7 +98,7 @@ public class PlaybackVolumeUpdaterTest { Feed feed = mockFeed(feedMedia, FEED_ID); when(feed.getIdentifyingValue()).thenReturn("wrongFeedId"); - playbackVolumeUpdater.updateVolumeIfNecessary(mediaPlayer, FEED_ID, VolumeReductionSetting.OFF); + playbackVolumeUpdater.updateVolumeIfNecessary(mediaPlayer, FEED_ID, VolumeAdaptionSetting.OFF); verify(mediaPlayer, never()).pause(anyBoolean(), anyBoolean()); verify(mediaPlayer, never()).resume(); @@ -114,9 +114,9 @@ public class PlaybackVolumeUpdaterTest { when(mediaPlayer.getPlayable()).thenReturn(feedMedia); FeedPreferences feedPreferences = mockFeedPreferences(feedMedia, FEED_ID); - playbackVolumeUpdater.updateVolumeIfNecessary(mediaPlayer, FEED_ID, VolumeReductionSetting.LIGHT); + playbackVolumeUpdater.updateVolumeIfNecessary(mediaPlayer, FEED_ID, VolumeAdaptionSetting.LIGHT_REDUCTION); - verify(feedPreferences, times(1)).setVolumeReductionSetting(VolumeReductionSetting.LIGHT); + verify(feedPreferences, times(1)).setVolumeAdaptionSetting(VolumeAdaptionSetting.LIGHT_REDUCTION); verify(mediaPlayer, never()).pause(anyBoolean(), anyBoolean()); verify(mediaPlayer, never()).resume(); @@ -132,9 +132,9 @@ public class PlaybackVolumeUpdaterTest { when(mediaPlayer.getPlayable()).thenReturn(feedMedia); FeedPreferences feedPreferences = mockFeedPreferences(feedMedia, FEED_ID); - playbackVolumeUpdater.updateVolumeIfNecessary(mediaPlayer, FEED_ID, VolumeReductionSetting.LIGHT); + playbackVolumeUpdater.updateVolumeIfNecessary(mediaPlayer, FEED_ID, VolumeAdaptionSetting.LIGHT_REDUCTION); - verify(feedPreferences, times(1)).setVolumeReductionSetting(VolumeReductionSetting.LIGHT); + verify(feedPreferences, times(1)).setVolumeAdaptionSetting(VolumeAdaptionSetting.LIGHT_REDUCTION); verify(mediaPlayer, never()).pause(anyBoolean(), anyBoolean()); verify(mediaPlayer, never()).resume(); @@ -150,9 +150,9 @@ public class PlaybackVolumeUpdaterTest { when(mediaPlayer.getPlayable()).thenReturn(feedMedia); FeedPreferences feedPreferences = mockFeedPreferences(feedMedia, FEED_ID); - playbackVolumeUpdater.updateVolumeIfNecessary(mediaPlayer, FEED_ID, VolumeReductionSetting.LIGHT); + playbackVolumeUpdater.updateVolumeIfNecessary(mediaPlayer, FEED_ID, VolumeAdaptionSetting.LIGHT_REDUCTION); - verify(feedPreferences, times(1)).setVolumeReductionSetting(VolumeReductionSetting.LIGHT); + verify(feedPreferences, times(1)).setVolumeAdaptionSetting(VolumeAdaptionSetting.LIGHT_REDUCTION); verify(mediaPlayer, never()).pause(anyBoolean(), anyBoolean()); verify(mediaPlayer, never()).resume(); @@ -168,9 +168,9 @@ public class PlaybackVolumeUpdaterTest { when(mediaPlayer.getPlayable()).thenReturn(feedMedia); FeedPreferences feedPreferences = mockFeedPreferences(feedMedia, FEED_ID); - playbackVolumeUpdater.updateVolumeIfNecessary(mediaPlayer, FEED_ID, VolumeReductionSetting.LIGHT); + playbackVolumeUpdater.updateVolumeIfNecessary(mediaPlayer, FEED_ID, VolumeAdaptionSetting.LIGHT_REDUCTION); - verify(feedPreferences, times(1)).setVolumeReductionSetting(VolumeReductionSetting.LIGHT); + verify(feedPreferences, times(1)).setVolumeAdaptionSetting(VolumeAdaptionSetting.LIGHT_REDUCTION); verify(mediaPlayer, never()).pause(anyBoolean(), anyBoolean()); verify(mediaPlayer, never()).resume(); @@ -186,9 +186,9 @@ public class PlaybackVolumeUpdaterTest { when(mediaPlayer.getPlayable()).thenReturn(feedMedia); FeedPreferences feedPreferences = mockFeedPreferences(feedMedia, FEED_ID); - playbackVolumeUpdater.updateVolumeIfNecessary(mediaPlayer, FEED_ID, VolumeReductionSetting.LIGHT); + playbackVolumeUpdater.updateVolumeIfNecessary(mediaPlayer, FEED_ID, VolumeAdaptionSetting.LIGHT_REDUCTION); - verify(feedPreferences, times(1)).setVolumeReductionSetting(VolumeReductionSetting.LIGHT); + verify(feedPreferences, times(1)).setVolumeAdaptionSetting(VolumeAdaptionSetting.LIGHT_REDUCTION); verify(mediaPlayer, never()).pause(anyBoolean(), anyBoolean()); verify(mediaPlayer, never()).resume(); @@ -204,9 +204,9 @@ public class PlaybackVolumeUpdaterTest { when(mediaPlayer.getPlayable()).thenReturn(feedMedia); FeedPreferences feedPreferences = mockFeedPreferences(feedMedia, FEED_ID); - playbackVolumeUpdater.updateVolumeIfNecessary(mediaPlayer, FEED_ID, VolumeReductionSetting.HEAVY); + playbackVolumeUpdater.updateVolumeIfNecessary(mediaPlayer, FEED_ID, VolumeAdaptionSetting.HEAVY_REDUCTION); - verify(feedPreferences, times(1)).setVolumeReductionSetting(VolumeReductionSetting.HEAVY); + verify(feedPreferences, times(1)).setVolumeAdaptionSetting(VolumeAdaptionSetting.HEAVY_REDUCTION); verify(mediaPlayer, times(1)).pause(false, false); verify(mediaPlayer, times(1)).resume(); -- cgit v1.2.3 From 95fd348c113c1661b1035b172c319827e1cba364 Mon Sep 17 00:00:00 2001 From: Max Bechtold Date: Sun, 29 Dec 2019 11:21:30 +0100 Subject: unregister volume adaption receiver --- .../java/de/danoeh/antennapod/core/service/playback/PlaybackService.java | 1 + 1 file changed, 1 insertion(+) (limited to 'core/src') diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java index 8673d2744..577e482ec 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java @@ -356,6 +356,7 @@ public class PlaybackService extends MediaBrowserServiceCompat { unregisterReceiver(audioBecomingNoisy); unregisterReceiver(skipCurrentEpisodeReceiver); unregisterReceiver(pausePlayCurrentEpisodeReceiver); + unregisterReceiver(volumeAdaptionChangedReceiver); flavorHelper.removeCastConsumer(); flavorHelper.unregisterWifiBroadcastReceiver(); mediaPlayer.shutdown(); -- cgit v1.2.3 From 3e610c85b9e113263a2c37a49aeb5a9db1e912e5 Mon Sep 17 00:00:00 2001 From: Max Bechtold Date: Sun, 29 Dec 2019 11:42:45 +0100 Subject: provide drawable for volume adaption setting --- core/src/main/res/drawable/ic_volume_adaption_grey.xml | 9 +++++++++ core/src/main/res/drawable/ic_volume_adaption_white.xml | 9 +++++++++ core/src/main/res/values/attrs.xml | 1 + core/src/main/res/values/styles.xml | 2 ++ 4 files changed, 21 insertions(+) create mode 100644 core/src/main/res/drawable/ic_volume_adaption_grey.xml create mode 100644 core/src/main/res/drawable/ic_volume_adaption_white.xml (limited to 'core/src') diff --git a/core/src/main/res/drawable/ic_volume_adaption_grey.xml b/core/src/main/res/drawable/ic_volume_adaption_grey.xml new file mode 100644 index 000000000..fe39e1c70 --- /dev/null +++ b/core/src/main/res/drawable/ic_volume_adaption_grey.xml @@ -0,0 +1,9 @@ + + + \ No newline at end of file diff --git a/core/src/main/res/drawable/ic_volume_adaption_white.xml b/core/src/main/res/drawable/ic_volume_adaption_white.xml new file mode 100644 index 000000000..27d7c6e7b --- /dev/null +++ b/core/src/main/res/drawable/ic_volume_adaption_white.xml @@ -0,0 +1,9 @@ + + + \ No newline at end of file diff --git a/core/src/main/res/values/attrs.xml b/core/src/main/res/values/attrs.xml index fe571539a..c6668675f 100644 --- a/core/src/main/res/values/attrs.xml +++ b/core/src/main/res/values/attrs.xml @@ -53,6 +53,7 @@ + diff --git a/core/src/main/res/values/styles.xml b/core/src/main/res/values/styles.xml index a638917f4..6a82adf74 100644 --- a/core/src/main/res/values/styles.xml +++ b/core/src/main/res/values/styles.xml @@ -76,6 +76,7 @@ @drawable/ic_bookmark_grey600_24dp @drawable/ic_fab_edit_white @drawable/ic_key_grey600 + @drawable/ic_volume_adaption_grey @color/master_switch_background_light @color/highlight_light @@ -164,6 +165,7 @@ @drawable/ic_bookmark_white_24dp @drawable/ic_fab_edit_white @drawable/ic_key_white + @drawable/ic_volume_adaption_white @color/master_switch_background_dark @color/highlight_dark @style/PreferenceThemeOverlay.v14.Material -- cgit v1.2.3 From 3fa210c41408180b19064c7d98928cb457fb21ef Mon Sep 17 00:00:00 2001 From: Max Bechtold Date: Mon, 30 Dec 2019 12:39:59 +0100 Subject: remove check of media type --- .../core/service/playback/LocalPSMP.java | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) (limited to 'core/src') diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java index 8965f5fbf..9c32e42e0 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java @@ -668,19 +668,17 @@ public class LocalPSMP extends PlaybackServiceMediaPlayer { */ private void setVolumeSync(float volumeLeft, float volumeRight) { playerLock.lock(); - if (media != null && EnumSet.of(MediaType.AUDIO, MediaType.VIDEO).contains(media.getMediaType())) { - Playable playable = getPlayable(); - if (playable instanceof FeedMedia) { - FeedMedia feedMedia = (FeedMedia) playable; - FeedPreferences preferences = feedMedia.getItem().getFeed().getPreferences(); - VolumeAdaptionSetting volumeAdaptionSetting = preferences.getVolumeAdaptionSetting(); - float adaptionFactor = volumeAdaptionSetting.getAdaptionFactor(); - volumeLeft *= adaptionFactor; - volumeRight *= adaptionFactor; - } - mediaPlayer.setVolume(volumeLeft, volumeRight); - Log.d(TAG, "Media player volume was set to " + volumeLeft + " " + volumeRight); + Playable playable = getPlayable(); + if (playable instanceof FeedMedia) { + FeedMedia feedMedia = (FeedMedia) playable; + FeedPreferences preferences = feedMedia.getItem().getFeed().getPreferences(); + VolumeAdaptionSetting volumeAdaptionSetting = preferences.getVolumeAdaptionSetting(); + float adaptionFactor = volumeAdaptionSetting.getAdaptionFactor(); + volumeLeft *= adaptionFactor; + volumeRight *= adaptionFactor; } + mediaPlayer.setVolume(volumeLeft, volumeRight); + Log.d(TAG, "Media player volume was set to " + volumeLeft + " " + volumeRight); playerLock.unlock(); } -- cgit v1.2.3 From 8d0e89b2551b5f3a18a06611903c78505eee9404 Mon Sep 17 00:00:00 2001 From: ByteHamster Date: Thu, 16 Jan 2020 00:23:11 +0100 Subject: Pulled translations --- core/src/main/res/values-ca/strings.xml | 6 ++ core/src/main/res/values-da/strings.xml | 89 +++++++++++++++++++++++++++- core/src/main/res/values-de/strings.xml | 28 ++++----- core/src/main/res/values-fr/strings.xml | 8 +-- core/src/main/res/values-hu/strings.xml | 1 + core/src/main/res/values-it/strings.xml | 92 ++++++++++++++--------------- core/src/main/res/values-nl/strings.xml | 10 ++-- core/src/main/res/values-pl-rPL/strings.xml | 2 + 8 files changed, 166 insertions(+), 70 deletions(-) (limited to 'core/src') diff --git a/core/src/main/res/values-ca/strings.xml b/core/src/main/res/values-ca/strings.xml index aeb5738b2..4d16c469e 100644 --- a/core/src/main/res/values-ca/strings.xml +++ b/core/src/main/res/values-ca/strings.xml @@ -91,11 +91,14 @@ 1 dia després d\'acabar %d dies després d\'acabar + %d sel·leccionat Enllaç del canal URL, canal o lloc web Afegeix podcast amb l\'URL Navega gpodder.net + Descobreix + més » Marca-ho tot com a llegit S\'han marcat tots els episodis com a llegits @@ -246,6 +249,7 @@ Aparença Elements externs Interrupcions + Cerca… Reproductor multimèdia Neteja l\'episodi Els episodis que no es troben a la cua i no són preferits seran candidats a ser suprimits si l\'Auto Descàrrega necessita espai per a nous episodis @@ -494,8 +498,10 @@ S\'estan important les subscripcions des de les apps de propòsit únic... + Cerca podcast… Cerca a iTunes Cerca a fyyd + Cerca avançada Filtra Tot diff --git a/core/src/main/res/values-da/strings.xml b/core/src/main/res/values-da/strings.xml index 728975847..58192ee30 100644 --- a/core/src/main/res/values-da/strings.xml +++ b/core/src/main/res/values-da/strings.xml @@ -64,6 +64,7 @@ Billede Fejl En fejl er opstået: + Tilladelse til lageradgang kræves for denne handling Opdater Ingen ekstern harddisk er tilgængelig. Vær venlig at sørge for at den eksterne hukommelse er monteret så app\'en kan fungere korrekt. Kapitler @@ -86,6 +87,10 @@ Aldrig Når ikke i kø Efter færdig afspilning + + 1 time efter afslutning + %d timer efter afslutning + 1 dag efter færdig afspilning %d dage efter færdig afspilning @@ -95,18 +100,28 @@ www.example.com/feed Tilføj podcast via webadresse Gennemse gpodder.net + Opdag + mere » Marker alle som afspillet Marker alle udsendelser som afspillet Bekræft venligst at du ønsker at markere alle udsendelser som værende afspillet. + Fjern alle \"ny\"-markeringer + Fjernede alle \"ny\"-markeringer Vis information + Vis podcast-indstillinger Podcast-info + Podcast-indstillinger Omdøb podcast Fjern podcast Del… Del udsendelsens webadresse + Del webadresse for udsendelse med position Del fil + Del webstedets adresse Del webadresse for feedet + Del webadresse for mediefil + Del webadresse for mediefil med position Bekræft venligst at du ønsker at slette podcasten \"%1$s\" og ALLE dens udsendelser (inklusive overførte udsendelser) Fjerner podcast Opdater komplet podcast @@ -127,17 +142,40 @@ Åbn podcast Hent + + Henter %d udsendelse. + Henter %d udsendelser. + Afspil Sæt på pause Stream Slet Kan ikke slette fil. En genstart af enheden vil sandsynligvis hjælpe. + Slet udsendelse + + %d udsendelse slettet. + %d udsendelser slettet. + + Fjern \"ny\"-markering + Fjernet \"ny\"-markering Marker som læst Markeret som afspillet + + %d udsendelse markeret som afspillet. + %d udsendelser markeret som afspillet. + Marker som uafspillet + + %d udsendelse markeret som uafspillet. + %d udsendelser markeret som uafspillede. + Føj til kø Føjet til kø Fjern fra kø + + %d udsendelse fjernet fra køen. + %d udsendelser fjernet fra køen. + Føj til foretrukne Føjet til foretrukne Fjern fra foretrukne @@ -189,6 +227,9 @@ Bekræft brug af mobildata Overførsel over mobil dataforbindelse er slået fra i indstillingerne.\n\nDu kan vælge blot at føje udsendelsen til køen eller du kan tillade overførsel midlertidigt.\n\nDit valg vil blive husket i 10 minutter. Overførsel over mobil dataforbindelse er slået fra i indstillingerne.\n\nVil du tillade overførsel midlertidigt?\n\nDit valg vil blive husket i 10 minutter. + Bekræft mobil streaming + Streaming via mobildata er slået fra i indstillingerne. Tryk for at streame alligevel. + Tillad altid Sæt i kø Tillad midlertidigt @@ -198,6 +239,7 @@ Klar Søger Server døde + Kan ikke afspille denne medietype Ukendt fejl Ingen medier afspiller Henter data til buffer @@ -208,27 +250,44 @@ Lås kø op Kø låst Kø låst op + Vis ikke igen Ryd kø Fortryd Flyt til toppen Flyt til bunden Sorter + Hold sorteret Dato Varighed Titel på udsendelse Titel på podcast Tilfældig + Smart blanding Stigende Faldende Bekræft venligst at du vil rydde ALLE udsendelser fra køen + Gamle til nye + Nye til gamle Hent plugin Plugin er ikke installeret Afspilningshastigheder Slå Sonic til + Ingen udsendelser i køen Denne udsendelse har ingen beskrivelse. + Ingen overførsler i gang + Ingen overførte udsendelser + Ingen overførselslog + Ingen historik + Ingen udsendelser + Når du tilføjer en podcast, vil udsendelserne blive vist her. + Når nye udsendelser ankommer, vil de blive vist her. + Ingen foretrukne udsendelser + Du kan føje udsendelser til foretrukne ved at trykke længe på dem + Ingen kapitler Denne udsendelse har ingen kapitler. + Ingen abonnementer Lagring Projekt @@ -237,8 +296,12 @@ Automatisering Detaljer Import/eksport + sikkerhedskopiering, sikkerhedskopi, backup, gendan, gendannelse, restore Udseende Afbrydelser + Søg... + Ingen resultater + Slet historik Medieafspiller Oprydning i udsendelser Tillad at udsendelser, som ikke er i køen og som ikke er markeret som foretrukne, kan fjernes, hvis Automatisk overførsel har brug for plads til nye udsendelser @@ -271,7 +334,11 @@ Afbrydelse af hovedtelefoner Tilslutning af hovedtelefoner igen Bluetooth forbundet igen + Foretræk streaming Mobile opdateringer + Hent automatisk + Download af udsendelser + Streaming Brugergrænseflade Vælg tema Vælg elementer i navigationspanelet @@ -288,6 +355,7 @@ Tillad automatisk overførsel, når batteriet ikke oplades Parallelle overførsler Mellemlager for udsendelser + Brug systemtema Lys Mørk Sort (AMOLED-klar) @@ -331,9 +399,18 @@ Vis rapport over overførsler Lav en rapport, som viser detaljer om fejlene, hvis overførsler fejler Android-versioner før 4.1 understøtter ikke udvidede notifikationer. + Placering i kø + Føj udsendelser til: %1$s + Slutningen + Starten + Efter aktuel udsendelse Slået fra Størrelse på mellemlager (cache) for billeder Størrelse på diskmellemlageret (disk cache) for billeder + Rapportér fejl i appen + Åbn programfejlsdatabase + Kopier til udklipsholder + Kopieret til udklipsholder Eksperimentelt Nuværende værdi: %1$s Proxy @@ -343,9 +420,10 @@ Aktiver understøttelse af fjernafspilning på Cast-enheder (såsom Chromecast, højttalere med indbygget Chromecast, eller Android TV) Chromecast kræver tredjeparts proprietære biblioteker, som er slået fra i denne version af AntennaPod Sæt overførte udsendelser i kø - Føj udsendelser til køen, så snart de er overført + Føj downloadede udsendelser til køen Indbygget Android-afspiller Når videoen forlades + Opførsel når videoafspilning forlades Stop afspilning Fortsæt afspilning af lyd Funktion @@ -355,11 +433,13 @@ Åbn navigationsskuffen Dobbelttryk for at afslutte Bekræft for at afslutte + Er du sikker på at du vil lukke AntennaPod? Tryk på tilbageknappen igen for at afslutte Gå til side ... Vælg side Om + Oversættere Søg efter udsendelser Fundet i beskrivelse @@ -453,6 +533,7 @@ Vælg datamappe Vælg venligst roden af din datamappe. AntennaPod vil oprette passende undermapper. Adgang til eksternt lager er kræver for at ændre datamappen + %1$s af %2$s ledig Opret en ny mappe med navnet \"%1$s\"? Oprettede ny mappe Kan ikke skrive til denne mappe @@ -471,6 +552,7 @@ AntennaPod skal genstartes for at denne indstilling kan træde i kraft Abonner + Abonnerer ... Spol tilbage Spol frem @@ -496,8 +578,10 @@ Importerer abonnementer fra enkeltformålsapps… + Søg efter podcast ... Søg i iTunes Søg i fyyd + Avanceret søgning Filtrér Alle @@ -579,6 +663,9 @@ Handling påkrævet Henter Vises samtidig med den hentes. + Spiller nu Fejl + Ugyldig/ødelagt fil + Ugennemsigtighed diff --git a/core/src/main/res/values-de/strings.xml b/core/src/main/res/values-de/strings.xml index 0d5158d24..444bf4314 100644 --- a/core/src/main/res/values-de/strings.xml +++ b/core/src/main/res/values-de/strings.xml @@ -114,10 +114,10 @@ Alle \"neu\"-Markierungen entfernt Bitte bestätige, dass du die \"neu\"-Markierung aller Episoden entfernen willst. Informationen anzeigen - Zeige Feed-Einstellungen - Feed-Informationen - Feed-Einstellungen - Feed umbenennen + Zeige Podcast-Einstellungen + Podcast-Informationen + Podcast-Einstellungen + Podcast umbenennen Podcast entfernen Teilen… Episoden URL Teilen @@ -127,9 +127,9 @@ Teile URL des Podcasts Teile URL der Episodendatei Teile URL der Episodendatei mit Zeitmarke - Bitte bestätige, dass du den Podcast \"%1$s\" und ALLE heruntergeladenen Episoden dieses Feeds entfernen möchtest. - Entferne Podcast - Kompletten Feed aktualisieren + Bitte bestätige, dass du den Podcast \"%1$s\" und ALL dessen Episoden entfernen möchtest (auch heruntergeladene). + Podcast wird entfernt + Kompletten Podcast aktualisieren Stapelbearbeitung Alles oberhalb auswählen Alles unterhalb auswählen @@ -156,7 +156,7 @@ Streamen Löschen Die Datei kann nicht gelöscht werden. Eventuell hilft es, das Gerät neu zu starten. - Episode entfernen + Episode löschen %d Episode gelöscht. %d Episoden gelöscht. @@ -272,7 +272,7 @@ Datum Dauer Episodentitel - Feedname + Podcast-Name Zufällig Schlaues Mischen Aufsteigend @@ -320,7 +320,7 @@ Erscheinungsbild Externe Elemente Unterbrechungen - Wiedergabesteurung + Wiedergabesteuerung Suchen… Keine Ergebnisse Verlauf leeren @@ -369,7 +369,7 @@ Benutzeroberfläche Theme auswählen Seitenleiste ändern - Ändere, welche Listen in der Seitenleiste erscheinen + Ändere, welche Einträge in der Seitenleiste erscheinen Reihenfolge der Abonnements einstellen Ändere die Reihenfolge deiner Abonnements Abonnement-Zähler einstellen @@ -493,8 +493,8 @@ Suche nach Episoden In Shownotizen gefunden In Kapiteln gefunden - Gefunden in Autor(en) - Gefunden in Podcast + In Autor(en) gefunden + In Podcast gefunden Keine Ergebnisse gefunden Suchen In Titel gefunden @@ -676,7 +676,7 @@ Audioeffekte Heruntermischen: Stereo zu Mono nur Sonic - Nur ExoPlayer + nur ExoPlayer Typ Host diff --git a/core/src/main/res/values-fr/strings.xml b/core/src/main/res/values-fr/strings.xml index 4418289e9..e03b1e301 100644 --- a/core/src/main/res/values-fr/strings.xml +++ b/core/src/main/res/values-fr/strings.xml @@ -261,7 +261,7 @@ Déverrouiller la liste de lecture Liste de lecture verrouillée Liste de lecture déverrouillée - Lorsque la liste est verrouillée le swipe n\'est pas possible et l\'ordre des épisodes ne peut être changé. + Quand la liste de lecture est verrouillée il n\'est pas possible de swiper ou de réorganiser l\'ordre des épisodes. Ne pas réafficher Effacer la liste de lecture Annuler @@ -358,7 +358,7 @@ Connexion des écouteurs Connexion du Bluetooth Préférer le streaming - Afficher dans les listes le bouton du stream au lieu de celui de téléchargement. + Afficher dans les listes le bouton du streaming au lieu de celui du téléchargement. Utilisation de la connexion mobile Choisir ce qui est autorisé lorsque la connexion mobile est utilisée Rafraîchissement des flux @@ -413,7 +413,7 @@ Ce paramètre ne s\'applique pas aux erreurs d\'authentification. Vitesses de lecture Définir les vitesses disponibles lors de la lecture audio - Vitesse de lecture pour les épisodes de ce flux + Vitesse de lecture par défaut pour les épisodes de ce flux Ajuster les informations en fonction la vitesse de lecture La position et la durée affichée tiendront compte de la vitesse de lecture. Durée du saut avant @@ -725,7 +725,7 @@ S\'affiche en cas de problème. Par exemple, un téléchargement ou une synchronisation qui échoue. Fichier invalide/corrompu - Préférences des widget + Préférences des widgets Créer un widget Opacité diff --git a/core/src/main/res/values-hu/strings.xml b/core/src/main/res/values-hu/strings.xml index b84d1900a..c82d505db 100644 --- a/core/src/main/res/values-hu/strings.xml +++ b/core/src/main/res/values-hu/strings.xml @@ -720,6 +720,7 @@ Akkor látszik, ha hiba történt, például ha a letöltés vagy a gpodder szinkronizálás sikertelen. Érvénytelen/sérült fájl + Widget beállítások Widget létrehozása Átlátszatlanság diff --git a/core/src/main/res/values-it/strings.xml b/core/src/main/res/values-it/strings.xml index 384368d35..cef128007 100644 --- a/core/src/main/res/values-it/strings.xml +++ b/core/src/main/res/values-it/strings.xml @@ -1,7 +1,7 @@ - Aggiorna Sottoscrizioni + Aggiorna sottoscrizioni Feed Statistiche Aggiungi un podcast @@ -17,7 +17,7 @@ Registro Sottoscrizioni Elenco sottoscrizioni - Annulla\nil Download + Annulla\nil download Cronologia riproduzioni gpodder.net Sincronizza con altri dispositivi @@ -28,15 +28,15 @@ Tempo totale di riproduzione: %1$d di %2$d episodi iniziati.\n\nRiprodotti %3$s di %4$s. Modalità di calcolo - Calcola il tempo di riproduzione reale. Riprodurre un podcast due volte verrà contato due volte, segnarlo come riprodotto no. + Tempo di riproduzione reale. Riprodurre due volte un episodio verrà contato doppio, segnarlo come riprodotto no. Somma il tempo di riproduzione di tutti i podcast segnati come riprodotti - Avviso: La velocità di riproduzione non viene considerata. + Avviso: la velocità di riproduzione non viene considerata. Resetta statistiche - Verranno eliminate le statistiche del tempo di riproduzione per tutti gli episodi. Sei sicuro? + Verranno eliminate le statistiche sul tempo di riproduzione di tutti gli episodi. Sei sicuro? Apri il menù Chiudi il menù - Preferenze del Drawer + Preferenze del drawer Ordina per contatore Ordina alfabeticamente Ordina per data di pubblicazione @@ -47,13 +47,13 @@ Numero di episodi scaricati Nulla - Apri nel Browser + Apri nel browser Copia URL Condividi URL URL copiato negli appunti Vai a questa posizione - Pulisci la cronologia + Svuota la cronologia Conferma Annulla @@ -68,7 +68,7 @@ È stato rilevato un errore: Questa operazione richiede l\'accesso alla memoria Aggiorna - Non risulta disponibile lo spazio di archiviazione esterno. Assicurati che lo spazio di archiviazione sia montato per permettere all\'applicazione di funzionare correttamente. + Spazio di archiviazione esterno non disponibile. Assicurati che sia montato per consentire all\'app di funzionare correttamente. Capitoli Durata: %1$s Descrizione @@ -78,9 +78,9 @@ Chiudi Riprova Includi nei download automatici - Applica ai Precedenti Episodi - L\'opzione Download Automatico verrà applicata ai nuovi episodi.\nVuoi anche applicarla agli episodi precedenti? - Elimina Episodi Automaticamente + Applica agli episodi precedenti + L\'opzione Download automatico verrà applicata ai nuovi episodi.\nVuoi applicarla anche agli episodi precedenti? + Elimina episodi automaticamente \u0020download paralleli Predefinita globale Sempre @@ -101,7 +101,7 @@ URL del feed www.example.com/feed - Aggiungi un Podcast tramite URL + Aggiungi un podcast tramite URL Esplora gpodder.net Scopri altro » @@ -121,14 +121,14 @@ Rimuovi podcast Condividi... Condividi URL episodio - Condividi URL dell\'episodio con la posizione + Condividi URL episodio con posizione Condividi il file Condividi URL del sito Condividi URL del feed Condividi URL del media - Condividi URL del media con la posizione + Condividi URL del media con posizione Conferma di voler eliminare il podcast \"%1$s\" e TUTTI i suoi episodi (compresi quelli scaricati). - Rimozione del Feed in corso + Rimozione podcast in corso Aggiorna podcast completo Modifica in gruppo Seleziona tutti sopra @@ -144,7 +144,7 @@ E\' preferito Filtrati {fa-exclamation-circle} Ultimo aggiornamento fallito - Apri Podcast + Apri podcast Download @@ -186,14 +186,14 @@ %d episodi rimossi dalla coda. Aggiungi ai preferiti - Aggiunto ai Preferiti + Aggiunto ai preferiti Rimuovi dai preferiti - Rimosso dai Preferiti + Rimosso dai preferiti Visita il sito Salta l\'episodio Attiva il download automatico Disattiva il download automatico - Azzera la Posizione di Riproduzione + Azzera la posizione di riproduzione Elemento rimosso successo @@ -210,10 +210,10 @@ Errore di connessione Host sconosciuto Errore di autenticazione - Errore Formato FIle + Errore del formato file Proibito Download annullato - Download annullato\nDownload Automatico disabilitato per questo elemento + Download annullato\nDownload automatico disabilitato per questo elemento Download completato con un errore (o errori) Rapporto del download URL malformato @@ -225,17 +225,17 @@ %d download rimanenti Elaborazione dei download in corso - Download podcast in corso + Scaricamento podcast in corso %1$d download con successo, %2$d falliti - Titolo Sconosciuto + Titolo sconosciuto Feed File multimediali Rilevato errore durante il download del file:\u0020 Non è stato fornito alcun podcast da mostrare. Autenticazione richiesta La risorsa che hai richiesto richiede un nome utente e una password - Conferma il download su cellulare - Il download tramite rete mobile è disattivato nelle impostazioni.\n\nÈ possibile scegliere di aggiungere semplicemente l\'episodio alla coda o consentire temporaneamente il download.\n\nLa scelta verrà ricordata per 10 minuti. + Conferma download su rete mobile + Il download tramite rete mobile è disattivato nelle impostazioni.\n\nPuoi scegliere di aggiungere semplicemente l\'episodio alla coda o consentire temporaneamente i download.\n\nLa scelta sarà valida per 10 minuti. Il download tramite rete mobile è disattivato nelle impostazioni.\n\nVuoi abilitare temporaneamente il download?\n\nLa scelta verrà ricordata per 10 minuti. Conferma streaming su rete mobile Lo streaming su rete mobile è disattivato nelle impostazioni. Tocca per avviare comunque. @@ -263,7 +263,7 @@ Coda sbloccata Se blocchi la coda non potrai più fare swipe o riordinare gli episodi. Non mostrare più - Svuota la Coda + Svuota la coda Undo Sposta all\'inizio Sposta in fondo @@ -271,7 +271,7 @@ Mantieni ordinato Per data Per durata - Titolo dell\'episodio + Titolo episodio Titolo podcast Casuale Casuale intelligente @@ -326,14 +326,14 @@ Svuota cronologia Media player Pulizia episodi - Gli episodi che non sono in coda e non sono tra i preferiti potrebbero essere rimossi se i Download Automatici richiedono maggiore spazio. + Gli episodi che non sono in coda e non sono tra i preferiti potrebbero essere rimossi se i Download automatici richiedono altro spazio. Sospendi la riproduzione quando le cuffie o il bluetooth vengono disconnessi Riprendi la riproduzione quando vengono riconnesse le cuffie Riprendi la riproduzione quando il Bluetooth si riconnette Il tasto Avanti salta la traccia Quando viene premuto il tasto Avanti sul dispositivo bluetooth connesso, passa all\'episodio successivo invece di andare avanti veloce Il tasto Indietro riavvia la traccia - Quando viene premuto il tasto fisico Indietro, viene riavviata la traccia invece di tornare indietro + Quando viene premuto il tasto fisico Indietro, viene riavviata la traccia invece di saltare indietro Passa al prossimo episodio in coda quando viene completata la riproduzione Elimina l\'episodio quando viene completata la riproduzione Elimina automaticamente @@ -347,7 +347,7 @@ Rete Intervallo o orario di aggiornamento Imposta un intervallo di tempo o un orario specifico in cui le sottoscrizioni vengono aggiornate automaticamente - Puoi impostare un intervallo come \"ogni 2 ore\", impostare un\'ora del giorno specifica, come \"7:00\" oppure disabilitare gli aggiornamenti automatici del tutto.\n\nNota: I tempi di aggiornamento non sono perfetti. Potrai riscontrare dei brevi ritardi. + Puoi impostare un intervallo come \"ogni 2 ore\", un\'ora del giorno specifica come \"7:00\" oppure disabilitare gli aggiornamenti automatici.\n\nNota: I tempi di aggiornamento non sono perfetti. Potrebbero esserci dei leggeri ritardi. Disabilita Imposta Intervallo Imposta orario @@ -381,9 +381,9 @@ Abilita il download automatico solo per alcune reti Wi-Fi selezionate. Autorizzazione richiesta Per il filtro Wi-Fi è richiesto l\'accesso alla posizione. Tocca per autorizzare. - Scarica quando la batteria non è in carica + Scarica episodi con batteria non in carica Permetti il download automatico quando la batteria non è in carica - Download simulanei + Download simultanei Cache degli episodi Numero di episodi scaricati memorizzabili sul dispositivo. I download automatici vengono interrotti se si raggiunge questo valore. Usa immagine episodio @@ -434,7 +434,7 @@ Sostituisce l\'immagine della schermata di blocco con quella dell\'episodio in riproduzione. Mostrerà l\'immagine anche in app di terze parti. Mostra il rapporto del download Se il download fallisce, genera un report che mostra i dettagli dell\'errore. - Le versioni di Android prima della 4.1 non supportano le notifiche estese. + Le versioni Android precedenti alla 4.1 non supportano le notifiche estese. Posizione in coda Aggiungi episodi a: %1$s Retro @@ -463,7 +463,7 @@ Player Android integrato Salta il silenzio audio Uscita dal video - Comportamento quando si esce dalla riproduzione video + Comportamento quando si termina una riproduzione video Interrompi riproduzione Continua riproduzione audio Comportamento @@ -551,7 +551,7 @@ SUGGERIMENTI Cerca su gpodder.net Login - Benvenuto sul processo di login di gpodder.net. Per prima cosa, inserisci le tue informazioni di login: + Benvenuto alla procedura di login di gpodder.net. Come prima cosa, inserisci le credenziali: Login Se non hai ancora un account, puoi crearne uno qui:\nhttps://gpodder.net/register/ Username @@ -563,11 +563,11 @@ Crea un nuovo dispositivo Scegli un dispositivo esistente: L\'ID del dispositivo non può essere vuoto - ID di dispositivo già in uso + ID del dispositivo già in uso La didascalia non può essere vuota Scegli Login effettuato! - Congraturazioni! Il tuo account gpodder.net è stato collegato con il tuo dispositivo. Da ora AntennaPod sincronizzerà automaticamente le sottoscrizioni sul tuo dispositivo con il tuo account gpodder.net. + Congraturazioni! Il tuo account gpodder.net è stato collegato con il dispositivo. Ora AntennaPod sincronizzerà automaticamente le sottoscrizioni sul dispositivo con il tuo account gpodder.net. Avvia la sincronizzazione Vai alla schermata principale errore di autenticazione su gpodder.net @@ -584,7 +584,7 @@ Scegli la base della tua cartella dati. AntennaPod creerà le sottocartelle appropriate. E\' necessario accedere alla memoria esterna per cambiare la cartella dei dati %1$s di %2$s liberi - Crea una nuova directory con nome \"%1$s\"? + Creare una nuova directory con nome \"%1$s\"? Crea una nuova directory Impossibile scrivere in questa directory La cartella esiste già @@ -595,7 +595,7 @@ La cartella non è vuota La cartella che hai selezionato non è vuota. I download dei media e altri file saranno creati in questa cartella. Continuare? Scegli la cartella predefinita - Sospendi la riproduzione invece di abbassare il volume quando un\'altra app emette un suono + Quando un\'altra app emette un suono, sospendi la riproduzione invece di abbassare il volume Pausa su interruzione Riprendi la riproduzione al termine di una chiamata Riprendi dopo la chiamata @@ -622,7 +622,7 @@ Includi Escludi Parole singole \n\"Parole multiple\" - Mantieni Aggiornato + Mantieni aggiornato Includi nell\'(auto-)aggiornamento di tutti i feed Il download automatico è disabilitato nelle Impostazioni generali. @@ -637,9 +637,9 @@ Filtro Tutto - Seleziona tutti gli Episodi + Seleziona tutti gli episodi Nulla - De-seleziona tutti gli episodi + Deseleziona tutti gli episodi Riprodotti Selezionati gli episodi riprodotti Non riprodotti @@ -675,7 +675,7 @@ Dx Effetti Audio Downmix: da Stereo a Mono - solo Sonic + Solo Sonic Solo ExoPlayer Tipo @@ -693,7 +693,7 @@ Numero di colonne Importa/Esporta database - Questa funzione sperimentale può essere usata per trasferire le sottoscrizioni e gli episoti completati ad un altro dispositivo.\n\nIl database potrà essere importato solo se si usa la stessa versione di AntennaPod, altrimenti potrebbero generarsi comportamenti anomali.\n\nDopo l\'importazione, gli episodi potrebbero essere mostrati come scaricati anche se non lo sono. Basta premere Play per farli riconoscere ad AntennaPod. + Questa funzione sperimentale può essere usata per trasferire le sottoscrizioni e gli episodi completati ad un altro dispositivo.\n\nIl database potrà essere importato solo se si usa la stessa versione di AntennaPod, altrimenti potrebbero generarsi comportamenti anomali.\n\nDopo l\'importazione, gli episodi potrebbero essere mostrati come scaricati anche se non lo sono. Basta premere Play per farli riconoscere ad AntennaPod. Importa Esporta Scegli file da importare @@ -716,7 +716,7 @@ Errore nella riproduzione. Salto... Azione richesta - Mostra se è richesto un tuo intervento, per sempio se è necessario inserire la password. + Mostra se è richesto un tuo intervento, per esempio se è necessario inserire la password. Scaricando Mostra mentre è in corso il download In riproduzione diff --git a/core/src/main/res/values-nl/strings.xml b/core/src/main/res/values-nl/strings.xml index 338f4c193..f6cb6c26d 100644 --- a/core/src/main/res/values-nl/strings.xml +++ b/core/src/main/res/values-nl/strings.xml @@ -68,7 +68,7 @@ Er is een fout opgetreden: Machtiging vereist voor gebruik van opslag Verversen - Geen externe opslag beschikbaar. Zorg ervoor dat de externe opslag is aangekoppeld zodat de app goed kan werken. + Geen externe opslag beschikbaar. Zorg ervoor dat de externe opslag gekoppeld is zodat de app juist kan functioneren. Hoofdstukken Duur: %1$s Omschrijving @@ -101,12 +101,12 @@ Feed-url www.voorbeeld.nl/feed - Podcast toevoegen middels url + Podcast toevoegen middels URL Verken gpodder.net Ontdekken meer » - Alles markeren als afgespeeld + Alles als afgespeeld markeren Alle afleveringen zijn gemarkeerd als afgespeeld Bevestig dat je alle afleveringen wilt markeren als afgespeeld. Bevestig dat je alle afleveringen van deze podcast wilt markeren als afgespeeld. @@ -163,13 +163,13 @@ \'Nieuw\'-label verwijderen \'Nieuw\'-label is verwijderd - Markeren als afgespeeld + Als afgespeeld markeren Gemarkeerd als afgespeeld %d aflevering gemarkeerd als afgespeeld. %d afleveringen gemarkeerd als afgespeeld. - Markeren als niet-afgespeeld + Als niet-afgespeeld markeren %d aflevering gemarkeerd als niet-afgespeeld. %d afleveringen gemarkeerd als niet-afgespeeld. diff --git a/core/src/main/res/values-pl-rPL/strings.xml b/core/src/main/res/values-pl-rPL/strings.xml index 22f0cc64e..05204fd4f 100644 --- a/core/src/main/res/values-pl-rPL/strings.xml +++ b/core/src/main/res/values-pl-rPL/strings.xml @@ -302,6 +302,7 @@ Pobierz wtyczkę Wtyczka nie zainstalowana + Aby używać zmiennej prędkości odtwarzania, zalecamy używanie wbudowanego odtwarzacza Sonic. Prędkość odtwarzania Włącz Sonic @@ -750,6 +751,7 @@ https://gpodder.net/register/ Pokazywane gdy coś pójdzie nie tak, na przykład jeśli nie powiedzie się pobieranie lub synchronizacja z gpodder. Nieprawidłowy/uszkodzony plik + Ustawienia widżetu Dodaj widżet Nieprzezroczystość -- cgit v1.2.3 From 7930d62bc04769733f4649053c266a363ef17391 Mon Sep 17 00:00:00 2001 From: "J.P.Klippel" Date: Sun, 19 Jan 2020 11:07:14 +0100 Subject: changed mentions of 'feed' to 'podcast' --- core/src/main/res/values/strings.xml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'core/src') diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index 2b48cb5ee..e0b1e206c 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -7,7 +7,7 @@ AntennaPod de.danoeh.antennapod.provider Update Subscriptions - Feeds + Podcasts Statistics Add Podcast Episodes @@ -116,7 +116,7 @@ Loading more… - Feed URL + Podcast feed URL www.example.com/feed Add Podcast by URL Browse gpodder.net @@ -142,7 +142,7 @@ Share Episode URL with Position Share File Share Website URL - Share Feed URL + Share Podcast URL Share Media File URL Share Media File URL with Position Please confirm that you want to delete the podcast \"%1$s\" and ALL its episodes (including downloaded episodes). @@ -380,7 +380,7 @@ Network Update interval, Download controls, Mobile data Update Interval or Time of Day - Specify an interval or a specific time of day to refresh the feeds automatically + Specify an interval or a specific time of day to refresh the podcasts automatically You can set an interval like \"every 2 hours\", set a specific time of day like \"7:00 AM\" or disable automatic updates altogether.\n\nPlease note: Update times are inexact. You may encounter a short delay. Disable Set Interval @@ -395,7 +395,7 @@ Display stream button instead of download button in lists. Mobile Updates Select what should be allowed over the mobile data connection - Feed refresh + Podcast refresh Cover images Auto download Episode download @@ -448,7 +448,7 @@ This setting does not apply to authentication errors. Playback Speeds Customize the speeds available for variable speed audio playback - The speed to use when starting audio playback for episodes in this feed + The speed to use when starting audio playback for episodes in this podcast Adjust media info to playback speed Displayed position and duration are adapted to playback speed Fast Forward Skip Time @@ -671,7 +671,7 @@ Exclude Single words \n\"Multiple Words\" Keep Updated - Include this feed when (auto-)refreshing all feeds + Include this podcast when (auto-)refreshing all podcasts Auto download is disabled in the main AntennaPod settings -- cgit v1.2.3 From 7702c9ee8c6ef23afd71270ad4126de37eeb7dfb Mon Sep 17 00:00:00 2001 From: ByteHamster Date: Mon, 20 Jan 2020 00:34:12 +0100 Subject: Convert playback speeds to float Advantage: When setting the speed to a value that is not available for the button using the audio controls dialog, we no longer jump to the lowest value. Instead, we jump to the next bigger one. --- .../core/preferences/UserPreferences.java | 30 ++++++++++------------ 1 file changed, 14 insertions(+), 16 deletions(-) (limited to 'core/src') diff --git a/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java b/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java index 4f871e83b..1ba981d27 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java +++ b/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java @@ -389,7 +389,7 @@ public class UserPreferences { return Float.parseFloat(prefs.getString(PREF_PLAYBACK_SPEED, "1.00")); } catch (NumberFormatException e) { Log.e(TAG, Log.getStackTraceString(e)); - UserPreferences.setPlaybackSpeed("1.00"); + UserPreferences.setPlaybackSpeed(1.0f); return 1.0f; } } @@ -399,7 +399,7 @@ public class UserPreferences { return Float.parseFloat(prefs.getString(PREF_VIDEO_PLAYBACK_SPEED, "1.00")); } catch (NumberFormatException e) { Log.e(TAG, Log.getStackTraceString(e)); - UserPreferences.setVideoPlaybackSpeed("1.00"); + UserPreferences.setVideoPlaybackSpeed(1.0f); return 1.0f; } } @@ -408,7 +408,7 @@ public class UserPreferences { return prefs.getBoolean(PREF_PLAYBACK_SKIP_SILENCE, false); } - public static String[] getPlaybackSpeedArray() { + public static float[] getPlaybackSpeedArray() { return readPlaybackSpeedArray(prefs.getString(PREF_PLAYBACK_SPEED_ARRAY, null)); } @@ -638,15 +638,15 @@ public class UserPreferences { .apply(); } - public static void setPlaybackSpeed(String speed) { + public static void setPlaybackSpeed(float speed) { prefs.edit() - .putString(PREF_PLAYBACK_SPEED, speed) + .putString(PREF_PLAYBACK_SPEED, String.valueOf(speed)) .apply(); } - public static void setVideoPlaybackSpeed(String speed) { + public static void setVideoPlaybackSpeed(float speed) { prefs.edit() - .putString(PREF_VIDEO_PLAYBACK_SPEED, speed) + .putString(PREF_VIDEO_PLAYBACK_SPEED, String.valueOf(speed)) .apply(); } @@ -769,24 +769,22 @@ public class UserPreferences { } } - private static String[] readPlaybackSpeedArray(String valueFromPrefs) { - String[] selectedSpeeds = null; - // If this preference hasn't been set yet, return the default options - if (valueFromPrefs == null) { - selectedSpeeds = new String[] { "0.75", "1.00", "1.25", "1.50", "1.75", "2.00" }; - } else { + private static float[] readPlaybackSpeedArray(String valueFromPrefs) { + if (valueFromPrefs != null) { try { JSONArray jsonArray = new JSONArray(valueFromPrefs); - selectedSpeeds = new String[jsonArray.length()]; + float[] selectedSpeeds = new float[jsonArray.length()]; for (int i = 0; i < jsonArray.length(); i++) { - selectedSpeeds[i] = jsonArray.getString(i); + selectedSpeeds[i] = (float) jsonArray.getDouble(i); } + return selectedSpeeds; } catch (JSONException e) { Log.e(TAG, "Got JSON error when trying to get speeds from JSONArray"); e.printStackTrace(); } } - return selectedSpeeds; + // If this preference hasn't been set yet, return the default options + return new float[] { 0.75f, 1.0f, 1.25f, 1.5f, 1.75f, 2.0f }; } public static String getMediaPlayer() { -- cgit v1.2.3 From b4b46fb4d844148fe48f46f8978a554e8c876c9d Mon Sep 17 00:00:00 2001 From: ByteHamster Date: Mon, 20 Jan 2020 00:43:24 +0100 Subject: Fix playback button Steps to reproduce: - Play - Pause - Close AudioPlayerActivity - Open AudioPlayerActivity - Tap speed button - Always sets to the one after 1.0 --- .../main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java | 1 + 1 file changed, 1 insertion(+) (limited to 'core/src') diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java index 485349cb1..1bf0cfb18 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java @@ -639,6 +639,7 @@ public class LocalPSMP extends PlaybackServiceMediaPlayer { float retVal = 1; if ((playerStatus == PlayerStatus.PLAYING || playerStatus == PlayerStatus.PAUSED + || playerStatus == PlayerStatus.INITIALIZED || playerStatus == PlayerStatus.PREPARED) && mediaPlayer.canSetSpeed()) { retVal = mediaPlayer.getCurrentSpeedMultiplier(); } -- cgit v1.2.3 From ac0cb04154ae09cb7868de5f99c5138eff4012e9 Mon Sep 17 00:00:00 2001 From: ByteHamster Date: Tue, 17 Dec 2019 17:15:31 +0100 Subject: More forgiving duplicate detection --- .../core/service/GpodnetSyncService.java | 6 +-- .../de/danoeh/antennapod/core/util/URLChecker.java | 47 ++++++++++++++++++++++ 2 files changed, 50 insertions(+), 3 deletions(-) (limited to 'core/src') diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/GpodnetSyncService.java b/core/src/main/java/de/danoeh/antennapod/core/service/GpodnetSyncService.java index b254cfc59..e4d9ff361 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/GpodnetSyncService.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/GpodnetSyncService.java @@ -38,6 +38,7 @@ import de.danoeh.antennapod.core.storage.DBWriter; import de.danoeh.antennapod.core.storage.DownloadRequestException; import de.danoeh.antennapod.core.storage.DownloadRequester; import de.danoeh.antennapod.core.util.NetworkUtils; +import de.danoeh.antennapod.core.util.URLChecker; import de.danoeh.antennapod.core.util.gui.NotificationUtils; /** @@ -185,15 +186,14 @@ public class GpodnetSyncService extends SafeJobIntentService { // local changes are always superior to remote changes! // add subscription if (1) not already subscribed and (2) not just unsubscribed for (String downloadUrl : changes.getAdded()) { - if (!localSubscriptions.contains(downloadUrl) && - !localRemoved.contains(downloadUrl)) { + if (!URLChecker.containsUrl(localSubscriptions, downloadUrl) && !localRemoved.contains(downloadUrl)) { Feed feed = new Feed(downloadUrl, null); DownloadRequester.getInstance().downloadFeed(this, feed); } } // remove subscription if not just subscribed (again) for (String downloadUrl : changes.getRemoved()) { - if(!localAdded.contains(downloadUrl)) { + if (!localAdded.contains(downloadUrl)) { DBTasks.removeFeedWithDownloadUrl(GpodnetSyncService.this, downloadUrl); } } diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/URLChecker.java b/core/src/main/java/de/danoeh/antennapod/core/util/URLChecker.java index 7e3870a20..dbdb37c3b 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/URLChecker.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/URLChecker.java @@ -1,10 +1,16 @@ package de.danoeh.antennapod.core.util; import android.net.Uri; +import android.text.TextUtils; import androidx.annotation.NonNull; import android.util.Log; import de.danoeh.antennapod.core.BuildConfig; +import okhttp3.HttpUrl; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; /** * Provides methods for checking and editing a URL. @@ -78,4 +84,45 @@ public final class URLChecker { return prepareURL(url); } } + + public static boolean containsUrl(List list, String url) { + for (String item : list) { + if (urlEquals(item, url)) { + return true; + } + } + return false; + } + + public static boolean urlEquals(String string1, String string2) { + HttpUrl url1 = HttpUrl.parse(string1); + HttpUrl url2 = HttpUrl.parse(string2); + if (!url1.host().equals(url2.host())) { + return false; + } + List pathSegments1 = normalizePathSegments(url1.pathSegments()); + List pathSegments2 = normalizePathSegments(url2.pathSegments()); + if (!pathSegments1.equals(pathSegments2)) { + return false; + } + if (TextUtils.isEmpty(url1.query())) { + return TextUtils.isEmpty(url2.query()); + } + return url1.query().equals(url2.query()); + } + + /** + * Removes empty segments and converts all to lower case. + * @param input List of path segments + * @return Normalized list of path segments + */ + private static List normalizePathSegments(List input) { + List result = new ArrayList<>(); + for (String string : input) { + if (!TextUtils.isEmpty(string)) { + result.add(string.toLowerCase()); + } + } + return result; + } } -- cgit v1.2.3 From 3913ff8c45f93a4eafc3a492143ecca049757e9c Mon Sep 17 00:00:00 2001 From: ByteHamster Date: Sat, 25 Jan 2020 14:32:43 +0100 Subject: Make seeking more reliable --- .../antennapod/core/service/playback/ExoPlayerWrapper.java | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'core/src') diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/ExoPlayerWrapper.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/ExoPlayerWrapper.java index c250cd17f..8f7e84561 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/ExoPlayerWrapper.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/ExoPlayerWrapper.java @@ -16,8 +16,9 @@ import com.google.android.exoplayer2.SeekParameters; import com.google.android.exoplayer2.SimpleExoPlayer; import com.google.android.exoplayer2.Timeline; import com.google.android.exoplayer2.audio.AudioAttributes; -import com.google.android.exoplayer2.source.ExtractorMediaSource; +import com.google.android.exoplayer2.extractor.DefaultExtractorsFactory; import com.google.android.exoplayer2.source.MediaSource; +import com.google.android.exoplayer2.source.ProgressiveMediaSource; import com.google.android.exoplayer2.source.TrackGroupArray; import com.google.android.exoplayer2.trackselection.DefaultTrackSelector; import com.google.android.exoplayer2.trackselection.TrackSelectionArray; @@ -71,7 +72,7 @@ public class ExoPlayerWrapper implements IPlayer { loadControl.setBackBuffer(UserPreferences.getRewindSecs() * 1000 + 500, true); SimpleExoPlayer p = ExoPlayerFactory.newSimpleInstance(mContext, new DefaultRenderersFactory(mContext), new DefaultTrackSelector(), loadControl.createDefaultLoadControl()); - p.setSeekParameters(SeekParameters.PREVIOUS_SYNC); + p.setSeekParameters(SeekParameters.EXACT); p.addListener(new Player.EventListener() { @Override public void onTimelineChanged(Timeline timeline, Object manifest, int reason) { @@ -170,7 +171,7 @@ public class ExoPlayerWrapper implements IPlayer { @Override public void prepare() throws IllegalStateException { - mExoPlayer.prepare(mediaSource); + mExoPlayer.prepare(mediaSource, false, true); } @Override @@ -216,7 +217,9 @@ public class ExoPlayerWrapper implements IPlayer { DefaultHttpDataSource.DEFAULT_READ_TIMEOUT_MILLIS, true); DataSource.Factory dataSourceFactory = new DefaultDataSourceFactory(mContext, null, httpDataSourceFactory); - ExtractorMediaSource.Factory f = new ExtractorMediaSource.Factory(dataSourceFactory); + DefaultExtractorsFactory extractorsFactory = new DefaultExtractorsFactory(); + extractorsFactory.setConstantBitrateSeekingEnabled(true); + ProgressiveMediaSource.Factory f = new ProgressiveMediaSource.Factory(dataSourceFactory, extractorsFactory); mediaSource = f.createMediaSource(Uri.parse(s)); } -- cgit v1.2.3 From e2ec07f607ff05e900ac2dd524945ba8f9ff775c Mon Sep 17 00:00:00 2001 From: ByteHamster Date: Sat, 25 Jan 2020 22:35:18 +0100 Subject: Database upgrade --- .../main/java/de/danoeh/antennapod/core/storage/DBUpgrader.java | 4 ++-- .../main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java | 7 +------ 2 files changed, 3 insertions(+), 8 deletions(-) (limited to 'core/src') diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DBUpgrader.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DBUpgrader.java index bae8f2e7c..234ce8367 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/DBUpgrader.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DBUpgrader.java @@ -294,11 +294,11 @@ class DBUpgrader { db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS + " ADD COLUMN " + PodDBAdapter.KEY_FEED_PLAYBACK_SPEED + " REAL DEFAULT " + SPEED_USE_GLOBAL); } - if (oldVersion < 1070401) { db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS + " ADD COLUMN " + PodDBAdapter.KEY_SORT_ORDER + " TEXT"); - + } + if (oldVersion < 1090000) { db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS + " ADD COLUMN " + PodDBAdapter.KEY_FEED_VOLUME_ADAPTION + " INTEGER DEFAULT 0"); } diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java b/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java index a91d9a3a0..6f1f3e65d 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java @@ -1467,10 +1467,7 @@ public class PodDBAdapter { * Helper class for opening the Antennapod database. */ private static class PodDBHelper extends SQLiteOpenHelper { - - private static final int VERSION = 1070401; - - private final Context context; + private static final int VERSION = 1090000; /** * Constructor. @@ -1482,7 +1479,6 @@ public class PodDBAdapter { public PodDBHelper(final Context context, final String name, final CursorFactory factory) { super(context, name, factory, VERSION, new PodDbErrorHandler()); - this.context = context; } @Override @@ -1501,7 +1497,6 @@ public class PodDBAdapter { db.execSQL(CREATE_INDEX_FEEDMEDIA_FEEDITEM); db.execSQL(CREATE_INDEX_QUEUE_FEEDITEM); db.execSQL(CREATE_INDEX_SIMPLECHAPTERS_FEEDITEM); - } @Override -- cgit v1.2.3 From 190b54ad70ccf25f869eb92b9699f0d90552974f Mon Sep 17 00:00:00 2001 From: ByteHamster Date: Sat, 25 Jan 2020 22:52:00 +0100 Subject: Converted to EventBus instead of broadcast --- .../event/settings/VolumeAdaptionChangedEvent.java | 21 +++++++++++++ .../core/service/playback/PlaybackService.java | 34 +++++----------------- .../service/playback/PlaybackVolumeUpdater.java | 15 ++++------ .../playback/PlaybackVolumeUpdaterTest.java | 29 +++++++++--------- 4 files changed, 49 insertions(+), 50 deletions(-) create mode 100644 core/src/main/java/de/danoeh/antennapod/core/event/settings/VolumeAdaptionChangedEvent.java (limited to 'core/src') diff --git a/core/src/main/java/de/danoeh/antennapod/core/event/settings/VolumeAdaptionChangedEvent.java b/core/src/main/java/de/danoeh/antennapod/core/event/settings/VolumeAdaptionChangedEvent.java new file mode 100644 index 000000000..3ed84f6a8 --- /dev/null +++ b/core/src/main/java/de/danoeh/antennapod/core/event/settings/VolumeAdaptionChangedEvent.java @@ -0,0 +1,21 @@ +package de.danoeh.antennapod.core.event.settings; + +import de.danoeh.antennapod.core.feed.VolumeAdaptionSetting; + +public class VolumeAdaptionChangedEvent { + private final VolumeAdaptionSetting volumeAdaptionSetting; + private final long feedId; + + public VolumeAdaptionChangedEvent(VolumeAdaptionSetting volumeAdaptionSetting, long feedId) { + this.volumeAdaptionSetting = volumeAdaptionSetting; + this.feedId = feedId; + } + + public VolumeAdaptionSetting getVolumeAdaptionSetting() { + return volumeAdaptionSetting; + } + + public long getFeedId() { + return feedId; + } +} diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java index 577e482ec..2fb37cc05 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java @@ -41,7 +41,6 @@ import com.bumptech.glide.Glide; import com.bumptech.glide.request.RequestOptions; import com.bumptech.glide.request.target.Target; -import java.io.Serializable; import java.util.ArrayList; import java.util.List; import java.util.concurrent.TimeUnit; @@ -51,13 +50,13 @@ import de.danoeh.antennapod.core.R; import de.danoeh.antennapod.core.event.MessageEvent; import de.danoeh.antennapod.core.event.PlaybackPositionEvent; import de.danoeh.antennapod.core.event.ServiceEvent; +import de.danoeh.antennapod.core.event.settings.VolumeAdaptionChangedEvent; import de.danoeh.antennapod.core.feed.Chapter; import de.danoeh.antennapod.core.feed.Feed; import de.danoeh.antennapod.core.feed.FeedItem; import de.danoeh.antennapod.core.feed.FeedMedia; import de.danoeh.antennapod.core.feed.MediaType; import de.danoeh.antennapod.core.feed.SearchResult; -import de.danoeh.antennapod.core.feed.VolumeAdaptionSetting; import de.danoeh.antennapod.core.glide.ApGlideSettings; import de.danoeh.antennapod.core.preferences.PlaybackPreferences; import de.danoeh.antennapod.core.preferences.SleepTimerPreferences; @@ -79,6 +78,7 @@ import io.reactivex.Observable; import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.disposables.Disposable; import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; /** * Controls the MediaPlayer that plays a FeedMedia-file @@ -136,13 +136,6 @@ public class PlaybackService extends MediaBrowserServiceCompat { */ public static final String ACTION_PAUSE_PLAY_CURRENT_EPISODE = "action.de.danoeh.antennapod.core.service.pausePlayCurrentEpisode"; - /** - * If the PlaybackService receives this action, it will try to apply the supplied volume adaption setting. - */ - public static final String ACTION_VOLUME_ADAPTION_CHANGED = "action.de.danoeh.antennapod.core.service.volumedAdaptionChanged"; - public static final String EXTRA_VOLUME_ADAPTION_SETTING = "PlaybackService.VolumeAdaptionSettingExtra"; - public static final String EXTRA_VOLUME_ADAPTION_AFFECTED_FEED = "PlaybackService.VolumeAdaptionSettingAffectedFeed"; - /** * Custom action used by Android Wear */ @@ -284,7 +277,7 @@ public class PlaybackService extends MediaBrowserServiceCompat { registerReceiver(audioBecomingNoisy, new IntentFilter(AudioManager.ACTION_AUDIO_BECOMING_NOISY)); registerReceiver(skipCurrentEpisodeReceiver, new IntentFilter(ACTION_SKIP_CURRENT_EPISODE)); registerReceiver(pausePlayCurrentEpisodeReceiver, new IntentFilter(ACTION_PAUSE_PLAY_CURRENT_EPISODE)); - registerReceiver(volumeAdaptionChangedReceiver, new IntentFilter(ACTION_VOLUME_ADAPTION_CHANGED)); + EventBus.getDefault().register(this); taskManager = new PlaybackServiceTaskManager(this, taskManagerCallback); flavorHelper = new PlaybackServiceFlavorHelper(PlaybackService.this, flavorHelperCallback); @@ -356,7 +349,6 @@ public class PlaybackService extends MediaBrowserServiceCompat { unregisterReceiver(audioBecomingNoisy); unregisterReceiver(skipCurrentEpisodeReceiver); unregisterReceiver(pausePlayCurrentEpisodeReceiver); - unregisterReceiver(volumeAdaptionChangedReceiver); flavorHelper.removeCastConsumer(); flavorHelper.unregisterWifiBroadcastReceiver(); mediaPlayer.shutdown(); @@ -1445,21 +1437,11 @@ public class PlaybackService extends MediaBrowserServiceCompat { } }; - private final BroadcastReceiver volumeAdaptionChangedReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - if (TextUtils.equals(intent.getAction(), ACTION_VOLUME_ADAPTION_CHANGED)) { - Log.d(TAG, "Received ACTION_VOLUME_ADAPTION_CHANGED intent"); - - String affectedFeed = intent.getStringExtra(EXTRA_VOLUME_ADAPTION_AFFECTED_FEED); - Serializable volumeAdaptionExtra = intent.getSerializableExtra(EXTRA_VOLUME_ADAPTION_SETTING); - VolumeAdaptionSetting volumeAdaptionSetting = (VolumeAdaptionSetting) volumeAdaptionExtra; - - PlaybackVolumeUpdater playbackVolumeUpdater = new PlaybackVolumeUpdater(); - playbackVolumeUpdater.updateVolumeIfNecessary(mediaPlayer, affectedFeed, volumeAdaptionSetting); - } - } - }; + @Subscribe + public void volumeAdaptionChanged(VolumeAdaptionChangedEvent event) { + PlaybackVolumeUpdater playbackVolumeUpdater = new PlaybackVolumeUpdater(); + playbackVolumeUpdater.updateVolumeIfNecessary(mediaPlayer, event.getFeedId(), event.getVolumeAdaptionSetting()); + } public static MediaType getCurrentMediaType() { return currentMediaType; diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackVolumeUpdater.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackVolumeUpdater.java index 9e8f34de5..0ef7e55bc 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackVolumeUpdater.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackVolumeUpdater.java @@ -7,18 +7,20 @@ import de.danoeh.antennapod.core.util.playback.Playable; class PlaybackVolumeUpdater { - public void updateVolumeIfNecessary(PlaybackServiceMediaPlayer mediaPlayer, String affectedFeedIdentifier, VolumeAdaptionSetting volumeAdaptionSetting) { + public void updateVolumeIfNecessary(PlaybackServiceMediaPlayer mediaPlayer, long feedId, + VolumeAdaptionSetting volumeAdaptionSetting) { Playable playable = mediaPlayer.getPlayable(); boolean isFeedMedia = playable instanceof FeedMedia; boolean isPlayableLoaded = isPlayableLoaded(mediaPlayer.getPlayerStatus()); if (isFeedMedia && isPlayableLoaded) { - updateFeedMediaVolumeIfNecessary(mediaPlayer, affectedFeedIdentifier, volumeAdaptionSetting, (FeedMedia) playable); + updateFeedMediaVolumeIfNecessary(mediaPlayer, feedId, volumeAdaptionSetting, (FeedMedia) playable); } } - private void updateFeedMediaVolumeIfNecessary(PlaybackServiceMediaPlayer mediaPlayer, String affectedFeedIdentifier, VolumeAdaptionSetting volumeAdaptionSetting, FeedMedia feedMedia) { - if (mediaBelongsToAffectedFeed(feedMedia, affectedFeedIdentifier)) { + private void updateFeedMediaVolumeIfNecessary(PlaybackServiceMediaPlayer mediaPlayer, long feedId, + VolumeAdaptionSetting volumeAdaptionSetting, FeedMedia feedMedia) { + if (feedMedia.getItem().getFeed().getId() == feedId) { FeedPreferences preferences = feedMedia.getItem().getFeed().getPreferences(); preferences.setVolumeAdaptionSetting(volumeAdaptionSetting); @@ -37,11 +39,6 @@ class PlaybackVolumeUpdater { || playerStatus == PlayerStatus.INITIALIZING; } - private static boolean mediaBelongsToAffectedFeed(FeedMedia feedMedia, String affectedFeedIdentifier) { - return affectedFeedIdentifier != null - && affectedFeedIdentifier.equals(feedMedia.getItem().getFeed().getIdentifyingValue()); - } - private void forceUpdateVolume(PlaybackServiceMediaPlayer mediaPlayer) { mediaPlayer.pause(false, false); mediaPlayer.resume(); diff --git a/core/src/test/java/de/danoeh/antennapod/core/service/playback/PlaybackVolumeUpdaterTest.java b/core/src/test/java/de/danoeh/antennapod/core/service/playback/PlaybackVolumeUpdaterTest.java index 02c3b6efb..a5a4ea760 100644 --- a/core/src/test/java/de/danoeh/antennapod/core/service/playback/PlaybackVolumeUpdaterTest.java +++ b/core/src/test/java/de/danoeh/antennapod/core/service/playback/PlaybackVolumeUpdaterTest.java @@ -18,12 +18,12 @@ import static org.mockito.Mockito.when; public class PlaybackVolumeUpdaterTest { - private static final String FEED_ID = "feedId"; + private static final long FEED_ID = 42; private PlaybackServiceMediaPlayer mediaPlayer; @Before - public void setUp() throws Exception { + public void setUp() { mediaPlayer = mock(PlaybackServiceMediaPlayer.class); } @@ -89,15 +89,14 @@ public class PlaybackVolumeUpdaterTest { @Test public void noChangeIfPlayableIsNoItemOfAffectedFeed() { - PlaybackVolumeUpdater playbackVolumeUpdater = new PlaybackVolumeUpdater(); - when(mediaPlayer.getPlayerStatus()).thenReturn(PlayerStatus.PLAYING); FeedMedia feedMedia = mock(FeedMedia.class); when(mediaPlayer.getPlayable()).thenReturn(feedMedia); - Feed feed = mockFeed(feedMedia, FEED_ID); + Feed feed = mockFeed(feedMedia); when(feed.getIdentifyingValue()).thenReturn("wrongFeedId"); + PlaybackVolumeUpdater playbackVolumeUpdater = new PlaybackVolumeUpdater(); playbackVolumeUpdater.updateVolumeIfNecessary(mediaPlayer, FEED_ID, VolumeAdaptionSetting.OFF); verify(mediaPlayer, never()).pause(anyBoolean(), anyBoolean()); @@ -112,7 +111,7 @@ public class PlaybackVolumeUpdaterTest { FeedMedia feedMedia = mock(FeedMedia.class); when(mediaPlayer.getPlayable()).thenReturn(feedMedia); - FeedPreferences feedPreferences = mockFeedPreferences(feedMedia, FEED_ID); + FeedPreferences feedPreferences = mockFeedPreferences(feedMedia); playbackVolumeUpdater.updateVolumeIfNecessary(mediaPlayer, FEED_ID, VolumeAdaptionSetting.LIGHT_REDUCTION); @@ -130,7 +129,7 @@ public class PlaybackVolumeUpdaterTest { FeedMedia feedMedia = mock(FeedMedia.class); when(mediaPlayer.getPlayable()).thenReturn(feedMedia); - FeedPreferences feedPreferences = mockFeedPreferences(feedMedia, FEED_ID); + FeedPreferences feedPreferences = mockFeedPreferences(feedMedia); playbackVolumeUpdater.updateVolumeIfNecessary(mediaPlayer, FEED_ID, VolumeAdaptionSetting.LIGHT_REDUCTION); @@ -148,7 +147,7 @@ public class PlaybackVolumeUpdaterTest { FeedMedia feedMedia = mock(FeedMedia.class); when(mediaPlayer.getPlayable()).thenReturn(feedMedia); - FeedPreferences feedPreferences = mockFeedPreferences(feedMedia, FEED_ID); + FeedPreferences feedPreferences = mockFeedPreferences(feedMedia); playbackVolumeUpdater.updateVolumeIfNecessary(mediaPlayer, FEED_ID, VolumeAdaptionSetting.LIGHT_REDUCTION); @@ -166,7 +165,7 @@ public class PlaybackVolumeUpdaterTest { FeedMedia feedMedia = mock(FeedMedia.class); when(mediaPlayer.getPlayable()).thenReturn(feedMedia); - FeedPreferences feedPreferences = mockFeedPreferences(feedMedia, FEED_ID); + FeedPreferences feedPreferences = mockFeedPreferences(feedMedia); playbackVolumeUpdater.updateVolumeIfNecessary(mediaPlayer, FEED_ID, VolumeAdaptionSetting.LIGHT_REDUCTION); @@ -184,7 +183,7 @@ public class PlaybackVolumeUpdaterTest { FeedMedia feedMedia = mock(FeedMedia.class); when(mediaPlayer.getPlayable()).thenReturn(feedMedia); - FeedPreferences feedPreferences = mockFeedPreferences(feedMedia, FEED_ID); + FeedPreferences feedPreferences = mockFeedPreferences(feedMedia); playbackVolumeUpdater.updateVolumeIfNecessary(mediaPlayer, FEED_ID, VolumeAdaptionSetting.LIGHT_REDUCTION); @@ -202,7 +201,7 @@ public class PlaybackVolumeUpdaterTest { FeedMedia feedMedia = mock(FeedMedia.class); when(mediaPlayer.getPlayable()).thenReturn(feedMedia); - FeedPreferences feedPreferences = mockFeedPreferences(feedMedia, FEED_ID); + FeedPreferences feedPreferences = mockFeedPreferences(feedMedia); playbackVolumeUpdater.updateVolumeIfNecessary(mediaPlayer, FEED_ID, VolumeAdaptionSetting.HEAVY_REDUCTION); @@ -212,18 +211,18 @@ public class PlaybackVolumeUpdaterTest { verify(mediaPlayer, times(1)).resume(); } - private FeedPreferences mockFeedPreferences(FeedMedia feedMedia, String feedId) { - Feed feed = mockFeed(feedMedia, feedId); + private FeedPreferences mockFeedPreferences(FeedMedia feedMedia) { + Feed feed = mockFeed(feedMedia); FeedPreferences feedPreferences = mock(FeedPreferences.class); when(feed.getPreferences()).thenReturn(feedPreferences); return feedPreferences; } - private Feed mockFeed(FeedMedia feedMedia, String feedId) { + private Feed mockFeed(FeedMedia feedMedia) { FeedItem feedItem = mock(FeedItem.class); when(feedMedia.getItem()).thenReturn(feedItem); Feed feed = mock(Feed.class); - when(feed.getIdentifyingValue()).thenReturn(feedId); + when(feed.getId()).thenReturn(FEED_ID); when(feedItem.getFeed()).thenReturn(feed); return feed; } -- cgit v1.2.3 From e09fae22a26f79ce277ce4f2e708643ce2f103d3 Mon Sep 17 00:00:00 2001 From: ByteHamster Date: Sat, 25 Jan 2020 22:53:26 +0100 Subject: Fix volume adaption while paused --- .../core/service/playback/PlaybackVolumeUpdater.java | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) (limited to 'core/src') diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackVolumeUpdater.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackVolumeUpdater.java index 0ef7e55bc..d03830387 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackVolumeUpdater.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackVolumeUpdater.java @@ -10,10 +10,8 @@ class PlaybackVolumeUpdater { public void updateVolumeIfNecessary(PlaybackServiceMediaPlayer mediaPlayer, long feedId, VolumeAdaptionSetting volumeAdaptionSetting) { Playable playable = mediaPlayer.getPlayable(); - boolean isFeedMedia = playable instanceof FeedMedia; - boolean isPlayableLoaded = isPlayableLoaded(mediaPlayer.getPlayerStatus()); - if (isFeedMedia && isPlayableLoaded) { + if (playable instanceof FeedMedia) { updateFeedMediaVolumeIfNecessary(mediaPlayer, feedId, volumeAdaptionSetting, (FeedMedia) playable); } } @@ -30,15 +28,6 @@ class PlaybackVolumeUpdater { } } - private static boolean isPlayableLoaded(PlayerStatus playerStatus) { - return playerStatus == PlayerStatus.PLAYING - || playerStatus == PlayerStatus.PAUSED - || playerStatus == PlayerStatus.SEEKING - || playerStatus == PlayerStatus.PREPARING - || playerStatus == PlayerStatus.PREPARED - || playerStatus == PlayerStatus.INITIALIZING; - } - private void forceUpdateVolume(PlaybackServiceMediaPlayer mediaPlayer) { mediaPlayer.pause(false, false); mediaPlayer.resume(); -- cgit v1.2.3 From 964a519b8ccfc2f4c8835a15018d81407768e11f Mon Sep 17 00:00:00 2001 From: ByteHamster Date: Sat, 25 Jan 2020 23:18:31 +0100 Subject: Always mock full feedMedia --- .../playback/PlaybackVolumeUpdaterTest.java | 54 ++++++++++------------ 1 file changed, 25 insertions(+), 29 deletions(-) (limited to 'core/src') diff --git a/core/src/test/java/de/danoeh/antennapod/core/service/playback/PlaybackVolumeUpdaterTest.java b/core/src/test/java/de/danoeh/antennapod/core/service/playback/PlaybackVolumeUpdaterTest.java index a5a4ea760..22f67933f 100644 --- a/core/src/test/java/de/danoeh/antennapod/core/service/playback/PlaybackVolumeUpdaterTest.java +++ b/core/src/test/java/de/danoeh/antennapod/core/service/playback/PlaybackVolumeUpdaterTest.java @@ -48,7 +48,7 @@ public class PlaybackVolumeUpdaterTest { when(mediaPlayer.getPlayerStatus()).thenReturn(PlayerStatus.ERROR); - FeedMedia feedMedia = mock(FeedMedia.class); + FeedMedia feedMedia = mockFeedMedia(); when(mediaPlayer.getPlayable()).thenReturn(feedMedia); playbackVolumeUpdater.updateVolumeIfNecessary(mediaPlayer, FEED_ID, VolumeAdaptionSetting.OFF); @@ -63,7 +63,7 @@ public class PlaybackVolumeUpdaterTest { when(mediaPlayer.getPlayerStatus()).thenReturn(PlayerStatus.INDETERMINATE); - FeedMedia feedMedia = mock(FeedMedia.class); + FeedMedia feedMedia = mockFeedMedia(); when(mediaPlayer.getPlayable()).thenReturn(feedMedia); playbackVolumeUpdater.updateVolumeIfNecessary(mediaPlayer, FEED_ID, VolumeAdaptionSetting.OFF); @@ -78,7 +78,7 @@ public class PlaybackVolumeUpdaterTest { when(mediaPlayer.getPlayerStatus()).thenReturn(PlayerStatus.STOPPED); - FeedMedia feedMedia = mock(FeedMedia.class); + FeedMedia feedMedia = mockFeedMedia(); when(mediaPlayer.getPlayable()).thenReturn(feedMedia); playbackVolumeUpdater.updateVolumeIfNecessary(mediaPlayer, FEED_ID, VolumeAdaptionSetting.OFF); @@ -91,10 +91,9 @@ public class PlaybackVolumeUpdaterTest { public void noChangeIfPlayableIsNoItemOfAffectedFeed() { when(mediaPlayer.getPlayerStatus()).thenReturn(PlayerStatus.PLAYING); - FeedMedia feedMedia = mock(FeedMedia.class); + FeedMedia feedMedia = mockFeedMedia(); when(mediaPlayer.getPlayable()).thenReturn(feedMedia); - Feed feed = mockFeed(feedMedia); - when(feed.getIdentifyingValue()).thenReturn("wrongFeedId"); + when(feedMedia.getItem().getFeed().getId()).thenReturn(FEED_ID + 1); PlaybackVolumeUpdater playbackVolumeUpdater = new PlaybackVolumeUpdater(); playbackVolumeUpdater.updateVolumeIfNecessary(mediaPlayer, FEED_ID, VolumeAdaptionSetting.OFF); @@ -109,9 +108,9 @@ public class PlaybackVolumeUpdaterTest { when(mediaPlayer.getPlayerStatus()).thenReturn(PlayerStatus.PAUSED); - FeedMedia feedMedia = mock(FeedMedia.class); + FeedMedia feedMedia = mockFeedMedia(); when(mediaPlayer.getPlayable()).thenReturn(feedMedia); - FeedPreferences feedPreferences = mockFeedPreferences(feedMedia); + FeedPreferences feedPreferences = feedMedia.getItem().getFeed().getPreferences(); playbackVolumeUpdater.updateVolumeIfNecessary(mediaPlayer, FEED_ID, VolumeAdaptionSetting.LIGHT_REDUCTION); @@ -127,9 +126,9 @@ public class PlaybackVolumeUpdaterTest { when(mediaPlayer.getPlayerStatus()).thenReturn(PlayerStatus.PREPARED); - FeedMedia feedMedia = mock(FeedMedia.class); + FeedMedia feedMedia = mockFeedMedia(); when(mediaPlayer.getPlayable()).thenReturn(feedMedia); - FeedPreferences feedPreferences = mockFeedPreferences(feedMedia); + FeedPreferences feedPreferences = feedMedia.getItem().getFeed().getPreferences(); playbackVolumeUpdater.updateVolumeIfNecessary(mediaPlayer, FEED_ID, VolumeAdaptionSetting.LIGHT_REDUCTION); @@ -145,9 +144,9 @@ public class PlaybackVolumeUpdaterTest { when(mediaPlayer.getPlayerStatus()).thenReturn(PlayerStatus.INITIALIZING); - FeedMedia feedMedia = mock(FeedMedia.class); + FeedMedia feedMedia = mockFeedMedia(); when(mediaPlayer.getPlayable()).thenReturn(feedMedia); - FeedPreferences feedPreferences = mockFeedPreferences(feedMedia); + FeedPreferences feedPreferences = feedMedia.getItem().getFeed().getPreferences(); playbackVolumeUpdater.updateVolumeIfNecessary(mediaPlayer, FEED_ID, VolumeAdaptionSetting.LIGHT_REDUCTION); @@ -163,9 +162,9 @@ public class PlaybackVolumeUpdaterTest { when(mediaPlayer.getPlayerStatus()).thenReturn(PlayerStatus.PREPARING); - FeedMedia feedMedia = mock(FeedMedia.class); + FeedMedia feedMedia = mockFeedMedia(); when(mediaPlayer.getPlayable()).thenReturn(feedMedia); - FeedPreferences feedPreferences = mockFeedPreferences(feedMedia); + FeedPreferences feedPreferences = feedMedia.getItem().getFeed().getPreferences(); playbackVolumeUpdater.updateVolumeIfNecessary(mediaPlayer, FEED_ID, VolumeAdaptionSetting.LIGHT_REDUCTION); @@ -181,9 +180,9 @@ public class PlaybackVolumeUpdaterTest { when(mediaPlayer.getPlayerStatus()).thenReturn(PlayerStatus.SEEKING); - FeedMedia feedMedia = mock(FeedMedia.class); + FeedMedia feedMedia = mockFeedMedia(); when(mediaPlayer.getPlayable()).thenReturn(feedMedia); - FeedPreferences feedPreferences = mockFeedPreferences(feedMedia); + FeedPreferences feedPreferences = feedMedia.getItem().getFeed().getPreferences(); playbackVolumeUpdater.updateVolumeIfNecessary(mediaPlayer, FEED_ID, VolumeAdaptionSetting.LIGHT_REDUCTION); @@ -199,9 +198,9 @@ public class PlaybackVolumeUpdaterTest { when(mediaPlayer.getPlayerStatus()).thenReturn(PlayerStatus.PLAYING); - FeedMedia feedMedia = mock(FeedMedia.class); + FeedMedia feedMedia = mockFeedMedia(); when(mediaPlayer.getPlayable()).thenReturn(feedMedia); - FeedPreferences feedPreferences = mockFeedPreferences(feedMedia); + FeedPreferences feedPreferences = feedMedia.getItem().getFeed().getPreferences(); playbackVolumeUpdater.updateVolumeIfNecessary(mediaPlayer, FEED_ID, VolumeAdaptionSetting.HEAVY_REDUCTION); @@ -210,20 +209,17 @@ public class PlaybackVolumeUpdaterTest { verify(mediaPlayer, times(1)).pause(false, false); verify(mediaPlayer, times(1)).resume(); } - - private FeedPreferences mockFeedPreferences(FeedMedia feedMedia) { - Feed feed = mockFeed(feedMedia); + + private FeedMedia mockFeedMedia() { + FeedMedia feedMedia = mock(FeedMedia.class); + FeedItem feedItem = mock(FeedItem.class); + Feed feed = mock(Feed.class); FeedPreferences feedPreferences = mock(FeedPreferences.class); - when(feed.getPreferences()).thenReturn(feedPreferences); - return feedPreferences; - } - private Feed mockFeed(FeedMedia feedMedia) { - FeedItem feedItem = mock(FeedItem.class); when(feedMedia.getItem()).thenReturn(feedItem); - Feed feed = mock(Feed.class); - when(feed.getId()).thenReturn(FEED_ID); when(feedItem.getFeed()).thenReturn(feed); - return feed; + when(feed.getId()).thenReturn(FEED_ID); + when(feed.getPreferences()).thenReturn(feedPreferences); + return feedMedia; } } -- cgit v1.2.3 From 116125f7217cdaca96bd910a65ada52558392ab0 Mon Sep 17 00:00:00 2001 From: ByteHamster Date: Sun, 26 Jan 2020 13:44:30 +0100 Subject: Display splash for all screens --- core/src/main/res/values-v26/styles.xml | 6 ++++++ core/src/main/res/values/styles.xml | 6 +++++- 2 files changed, 11 insertions(+), 1 deletion(-) create mode 100644 core/src/main/res/values-v26/styles.xml (limited to 'core/src') diff --git a/core/src/main/res/values-v26/styles.xml b/core/src/main/res/values-v26/styles.xml new file mode 100644 index 000000000..87453eb5e --- /dev/null +++ b/core/src/main/res/values-v26/styles.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/core/src/main/res/values/styles.xml b/core/src/main/res/values/styles.xml index 2ccd48353..64fe97d4f 100644 --- a/core/src/main/res/values/styles.xml +++ b/core/src/main/res/values/styles.xml @@ -266,7 +266,11 @@ @android:anim/fade_out - + + + + + +

AntennaPod Subscriptions

+ + Get AntennaPod + + diff --git a/core/src/main/java/de/danoeh/antennapod/core/backup/OpmlBackupAgent.java b/core/src/main/java/de/danoeh/antennapod/core/backup/OpmlBackupAgent.java index 80ce6cf56..61e4e599b 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/backup/OpmlBackupAgent.java +++ b/core/src/main/java/de/danoeh/antennapod/core/backup/OpmlBackupAgent.java @@ -93,7 +93,7 @@ public class OpmlBackupAgent extends BackupAgentHelper { try { // Write OPML - new OpmlWriter().writeDocument(DBReader.getFeedList(), writer); + new OpmlWriter().writeDocument(DBReader.getFeedList(), writer, mContext); // Compare checksum of new and old file to see if we need to perform a backup at all if (digester != null) { diff --git a/core/src/main/java/de/danoeh/antennapod/core/export/ExportWriter.java b/core/src/main/java/de/danoeh/antennapod/core/export/ExportWriter.java index d6a187b21..e0f0d4626 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/export/ExportWriter.java +++ b/core/src/main/java/de/danoeh/antennapod/core/export/ExportWriter.java @@ -11,8 +11,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package de.danoeh.antennapod.core.export; +import android.content.Context; import java.io.IOException; import java.io.Writer; import java.util.List; @@ -21,9 +23,9 @@ import de.danoeh.antennapod.core.feed.Feed; public interface ExportWriter { - void writeDocument(List feeds, Writer writer) - throws IllegalArgumentException, IllegalStateException, IOException; + void writeDocument(List feeds, Writer writer, Context context) + throws IllegalArgumentException, IllegalStateException, IOException; - String fileExtension(); + String fileExtension(); } diff --git a/core/src/main/java/de/danoeh/antennapod/core/export/html/HtmlSymbols.java b/core/src/main/java/de/danoeh/antennapod/core/export/html/HtmlSymbols.java deleted file mode 100644 index 1ca126469..000000000 --- a/core/src/main/java/de/danoeh/antennapod/core/export/html/HtmlSymbols.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package de.danoeh.antennapod.core.export.html; - -import de.danoeh.antennapod.core.export.CommonSymbols; - -class HtmlSymbols extends CommonSymbols { - - static final String HTML = "html"; - - static final String ORDERED_LIST = "ol"; - static final String LIST_ITEM = "li"; - - static final String HEADING = "h1"; - - static final String LINK = "a"; - static final String LINK_DESTINATION = "href"; - -} diff --git a/core/src/main/java/de/danoeh/antennapod/core/export/html/HtmlWriter.java b/core/src/main/java/de/danoeh/antennapod/core/export/html/HtmlWriter.java index c24b39812..93b66daed 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/export/html/HtmlWriter.java +++ b/core/src/main/java/de/danoeh/antennapod/core/export/html/HtmlWriter.java @@ -1,77 +1,45 @@ package de.danoeh.antennapod.core.export.html; -import android.text.TextUtils; +import android.content.Context; import android.util.Log; -import android.util.Xml; - -import org.xmlpull.v1.XmlSerializer; - +import de.danoeh.antennapod.core.export.ExportWriter; +import de.danoeh.antennapod.core.feed.Feed; import java.io.IOException; +import java.io.InputStream; import java.io.Writer; import java.util.List; - -import de.danoeh.antennapod.core.export.ExportWriter; -import de.danoeh.antennapod.core.feed.Feed; +import org.apache.commons.io.IOUtils; /** Writes HTML documents. */ public class HtmlWriter implements ExportWriter { - private static final String TAG = "HtmlWriter"; - private static final String ENCODING = "UTF-8"; - private static final String HTML_TITLE = "AntennaPod Subscriptions"; /** * Takes a list of feeds and a writer and writes those into an HTML * document. - * - * @throws IOException - * @throws IllegalStateException - * @throws IllegalArgumentException */ @Override - public void writeDocument(List feeds, Writer writer) + public void writeDocument(List feeds, Writer writer, Context context) throws IllegalArgumentException, IllegalStateException, IOException { Log.d(TAG, "Starting to write document"); - XmlSerializer xs = Xml.newSerializer(); - xs.setFeature(HtmlSymbols.XML_FEATURE_INDENT_OUTPUT, true); - xs.setOutput(writer); - xs.startDocument(ENCODING, false); - xs.startTag(null, HtmlSymbols.HTML); - xs.startTag(null, HtmlSymbols.HEAD); - xs.startTag(null, HtmlSymbols.TITLE); - xs.text(HTML_TITLE); - xs.endTag(null, HtmlSymbols.TITLE); - xs.endTag(null, HtmlSymbols.HEAD); + InputStream templateStream = context.getAssets().open("html-export-template.html"); + String template = IOUtils.toString(templateStream, "UTF-8"); + String[] templateParts = template.split("\\{FEEDS\\}"); - xs.startTag(null, HtmlSymbols.BODY); - xs.startTag(null, HtmlSymbols.HEADING); - xs.text(HTML_TITLE); - xs.endTag(null, HtmlSymbols.HEADING); - xs.startTag(null, HtmlSymbols.ORDERED_LIST); + writer.append(templateParts[0]); for (Feed feed : feeds) { - xs.startTag(null, HtmlSymbols.LIST_ITEM); - xs.text(feed.getTitle()); - if (!TextUtils.isEmpty(feed.getLink())) { - xs.text(" ["); - xs.startTag(null, HtmlSymbols.LINK); - xs.attribute(null, HtmlSymbols.LINK_DESTINATION, feed.getLink()); - xs.text("Website"); - xs.endTag(null, HtmlSymbols.LINK); - xs.text("]"); - } - xs.text(" ["); - xs.startTag(null, HtmlSymbols.LINK); - xs.attribute(null, HtmlSymbols.LINK_DESTINATION, feed.getDownload_url()); - xs.text("Feed"); - xs.endTag(null, HtmlSymbols.LINK); - xs.text("]"); - xs.endTag(null, HtmlSymbols.LIST_ITEM); + writer.append("
  • "); + writer.append(feed.getTitle()); + writer.append(" WebsiteFeed

  • \n"); } - xs.endTag(null, HtmlSymbols.ORDERED_LIST); - xs.endTag(null, HtmlSymbols.BODY); - xs.endTag(null, HtmlSymbols.HTML); - xs.endDocument(); + writer.append(templateParts[1]); Log.d(TAG, "Finished writing document"); } diff --git a/core/src/main/java/de/danoeh/antennapod/core/export/opml/OpmlWriter.java b/core/src/main/java/de/danoeh/antennapod/core/export/opml/OpmlWriter.java index fd0922f72..c93d4e8e0 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/export/opml/OpmlWriter.java +++ b/core/src/main/java/de/danoeh/antennapod/core/export/opml/OpmlWriter.java @@ -1,5 +1,6 @@ package de.danoeh.antennapod.core.export.opml; +import android.content.Context; import android.util.Log; import android.util.Xml; @@ -17,62 +18,58 @@ import de.danoeh.antennapod.core.util.DateUtils; /** Writes OPML documents. */ public class OpmlWriter implements ExportWriter { - private static final String TAG = "OpmlWriter"; - private static final String ENCODING = "UTF-8"; - private static final String OPML_VERSION = "2.0"; - private static final String OPML_TITLE = "AntennaPod Subscriptions"; + private static final String TAG = "OpmlWriter"; + private static final String ENCODING = "UTF-8"; + private static final String OPML_VERSION = "2.0"; + private static final String OPML_TITLE = "AntennaPod Subscriptions"; - /** - * Takes a list of feeds and a writer and writes those into an OPML - * document. - * - * @throws IOException - * @throws IllegalStateException - * @throws IllegalArgumentException - */ - @Override - public void writeDocument(List feeds, Writer writer) - throws IllegalArgumentException, IllegalStateException, IOException { - Log.d(TAG, "Starting to write document"); - XmlSerializer xs = Xml.newSerializer(); - xs.setFeature(OpmlSymbols.XML_FEATURE_INDENT_OUTPUT, true); - xs.setOutput(writer); + /** + * Takes a list of feeds and a writer and writes those into an OPML + * document. + */ + @Override + public void writeDocument(List feeds, Writer writer, Context context) + throws IllegalArgumentException, IllegalStateException, IOException { + Log.d(TAG, "Starting to write document"); + XmlSerializer xs = Xml.newSerializer(); + xs.setFeature(OpmlSymbols.XML_FEATURE_INDENT_OUTPUT, true); + xs.setOutput(writer); - xs.startDocument(ENCODING, false); - xs.startTag(null, OpmlSymbols.OPML); - xs.attribute(null, OpmlSymbols.VERSION, OPML_VERSION); + xs.startDocument(ENCODING, false); + xs.startTag(null, OpmlSymbols.OPML); + xs.attribute(null, OpmlSymbols.VERSION, OPML_VERSION); - xs.startTag(null, OpmlSymbols.HEAD); - xs.startTag(null, OpmlSymbols.TITLE); - xs.text(OPML_TITLE); - xs.endTag(null, OpmlSymbols.TITLE); - xs.startTag(null, OpmlSymbols.DATE_CREATED); - xs.text(DateUtils.formatRFC822Date(new Date())); - xs.endTag(null, OpmlSymbols.DATE_CREATED); - xs.endTag(null, OpmlSymbols.HEAD); + xs.startTag(null, OpmlSymbols.HEAD); + xs.startTag(null, OpmlSymbols.TITLE); + xs.text(OPML_TITLE); + xs.endTag(null, OpmlSymbols.TITLE); + xs.startTag(null, OpmlSymbols.DATE_CREATED); + xs.text(DateUtils.formatRFC822Date(new Date())); + xs.endTag(null, OpmlSymbols.DATE_CREATED); + xs.endTag(null, OpmlSymbols.HEAD); - xs.startTag(null, OpmlSymbols.BODY); - for (Feed feed : feeds) { - xs.startTag(null, OpmlSymbols.OUTLINE); - xs.attribute(null, OpmlSymbols.TEXT, feed.getTitle()); - xs.attribute(null, OpmlSymbols.TITLE, feed.getTitle()); - if (feed.getType() != null) { - xs.attribute(null, OpmlSymbols.TYPE, feed.getType()); - } - xs.attribute(null, OpmlSymbols.XMLURL, feed.getDownload_url()); - if (feed.getLink() != null) { - xs.attribute(null, OpmlSymbols.HTMLURL, feed.getLink()); - } - xs.endTag(null, OpmlSymbols.OUTLINE); - } - xs.endTag(null, OpmlSymbols.BODY); - xs.endTag(null, OpmlSymbols.OPML); - xs.endDocument(); - Log.d(TAG, "Finished writing document"); - } + xs.startTag(null, OpmlSymbols.BODY); + for (Feed feed : feeds) { + xs.startTag(null, OpmlSymbols.OUTLINE); + xs.attribute(null, OpmlSymbols.TEXT, feed.getTitle()); + xs.attribute(null, OpmlSymbols.TITLE, feed.getTitle()); + if (feed.getType() != null) { + xs.attribute(null, OpmlSymbols.TYPE, feed.getType()); + } + xs.attribute(null, OpmlSymbols.XMLURL, feed.getDownload_url()); + if (feed.getLink() != null) { + xs.attribute(null, OpmlSymbols.HTMLURL, feed.getLink()); + } + xs.endTag(null, OpmlSymbols.OUTLINE); + } + xs.endTag(null, OpmlSymbols.BODY); + xs.endTag(null, OpmlSymbols.OPML); + xs.endDocument(); + Log.d(TAG, "Finished writing document"); + } - public String fileExtension() { - return "opml"; - } + public String fileExtension() { + return "opml"; + } } -- cgit v1.2.3 From 0c7dd3cc24e6ab8c2b529a00edb6a2057c048218 Mon Sep 17 00:00:00 2001 From: ByteHamster Date: Mon, 27 Jan 2020 09:39:23 +0100 Subject: Added summaries --- core/src/main/res/values/strings.xml | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) (limited to 'core/src') diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index 88fa07049..26ed87537 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -544,7 +544,16 @@ Found in title No results were found for \"%1$s\" - + + Move subscriptions and queue to another device + Database + OPML + HTML + Show your subscriptions to a friend + Transfer your subscriptions to another podcast app + Import your subscriptions from another podcast app + Transfer subscriptions, listened episodes and queue to AntennaPod on another device + Import AntennaPod database from another device Option %1$d Choose a specific file path from the local filesystem. Many applications like Google Mail, Dropbox, Google Drive and most file managers can open OPML files with AntennaPod. @@ -562,6 +571,13 @@ Export successful The exported file was written to:\n\n%1$s Access to external storage is required to read the OPML file + Database import/export + This experimental function can be used to transfer your subscriptions and played episodes to another device.\n\nExported databases can only be imported when using the same version of AntennaPod. Otherwise, this function will lead to unexpected behavior.\n\nAfter importing, episodes might be displayed as downloaded even though they are not. Just press the play button of the episodes to make AntennaPod detect this. + Import + Export + Select file to import + Export successful. + Import successful.\n\nPlease press OK to restart AntennaPod Set sleep timer @@ -755,15 +771,6 @@ Number of columns - - Database import/export - This experimental function can be used to transfer your subscriptions and played episodes to another device.\n\nExported databases can only be imported when using the same version of AntennaPod. Otherwise, this function will lead to unexpected behavior.\n\nAfter importing, episodes might be displayed as downloaded even though they are not. Just press the play button of the episodes to make AntennaPod detect this. - Import - Export - Select file to import - Export successful. - Import successful.\n\nPlease press OK to restart AntennaPod - Play on… Disconnect the cast session -- cgit v1.2.3 From 8ecbe95e1654ba3e31408c39e57f80dcf6ead3cb Mon Sep 17 00:00:00 2001 From: ByteHamster Date: Mon, 27 Jan 2020 10:28:41 +0100 Subject: Moved database import/export to settings --- .../antennapod/core/storage/DatabaseExporter.java | 95 ++++++++++++++++++++++ core/src/main/res/values/strings.xml | 4 +- 2 files changed, 98 insertions(+), 1 deletion(-) create mode 100644 core/src/main/java/de/danoeh/antennapod/core/storage/DatabaseExporter.java (limited to 'core/src') diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DatabaseExporter.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DatabaseExporter.java new file mode 100644 index 000000000..af3d1206c --- /dev/null +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DatabaseExporter.java @@ -0,0 +1,95 @@ +package de.danoeh.antennapod.core.storage; + +import android.content.Context; +import android.net.Uri; +import android.os.ParcelFileDescriptor; +import android.util.Log; +import de.danoeh.antennapod.core.R; +import org.apache.commons.io.FileUtils; +import org.apache.commons.io.IOUtils; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.channels.FileChannel; +import java.util.Arrays; + +public class DatabaseExporter { + private static final String TAG = "DatabaseExporter"; + private static final byte[] SQLITE3_MAGIC = "SQLite format 3\0".getBytes(); + + public static boolean validateDB(Uri inputUri, Context context) throws IOException { + try (InputStream inputStream = context.getContentResolver().openInputStream(inputUri)) { + byte[] magicBuf = new byte[SQLITE3_MAGIC.length]; + if (inputStream.read(magicBuf) == magicBuf.length) { + return Arrays.equals(SQLITE3_MAGIC, magicBuf); + } + } + return false; + } + + public static void exportToDocument(Uri uri, Context context) throws IOException { + ParcelFileDescriptor pfd = null; + FileOutputStream fileOutputStream = null; + try { + pfd = context.getContentResolver().openFileDescriptor(uri, "w"); + fileOutputStream = new FileOutputStream(pfd.getFileDescriptor()); + exportToStream(fileOutputStream, context); + } catch (IOException e) { + Log.e(TAG, Log.getStackTraceString(e)); + throw e; + } finally { + IOUtils.closeQuietly(fileOutputStream); + + if (pfd != null) { + try { + pfd.close(); + } catch (IOException e) { + Log.d(TAG, "Unable to close ParcelFileDescriptor"); + } + } + } + } + + public static void exportToStream(FileOutputStream outFileStream, Context context) throws IOException { + FileChannel src = null; + FileChannel dst = null; + try { + File currentDB = context.getDatabasePath(PodDBAdapter.DATABASE_NAME); + + if (currentDB.exists()) { + src = new FileInputStream(currentDB).getChannel(); + dst = outFileStream.getChannel(); + dst.transferFrom(src, 0, src.size()); + } else { + throw new IOException("Can not access current database"); + } + } catch (IOException e) { + Log.e(TAG, Log.getStackTraceString(e)); + throw e; + } finally { + IOUtils.closeQuietly(src); + IOUtils.closeQuietly(dst); + } + } + + public static void importBackup(Uri inputUri, Context context) throws IOException { + InputStream inputStream = null; + try { + if (!validateDB(inputUri, context)) { + throw new IOException(context.getString(R.string.import_bad_file)); + } + + File currentDB = context.getDatabasePath(PodDBAdapter.DATABASE_NAME); + inputStream = context.getContentResolver().openInputStream(inputUri); + FileUtils.copyInputStreamToFile(inputStream, currentDB); + } catch (IOException e) { + Log.e(TAG, Log.getStackTraceString(e)); + throw e; + } finally { + IOUtils.closeQuietly(inputStream); + } + } +} diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index 26ed87537..554e1489f 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -566,7 +566,9 @@ From local filesystem OPML export HTML export - Exporting… + Database export + Database import + Please wait… Export error Export successful The exported file was written to:\n\n%1$s -- cgit v1.2.3 From 639c586a80f99d0f5242e0f86d42a4d69705c0e7 Mon Sep 17 00:00:00 2001 From: ByteHamster Date: Mon, 27 Jan 2020 10:35:02 +0100 Subject: Cleanup --- core/src/main/res/values/strings.xml | 6 ------ 1 file changed, 6 deletions(-) (limited to 'core/src') diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index 554e1489f..49b8875b6 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -558,7 +558,6 @@ Choose a specific file path from the local filesystem. Many applications like Google Mail, Dropbox, Google Drive and most file managers can open OPML files with AntennaPod. OPML Import - Reading OPML file An error has occurred while reading the OPML document: No file selected! Select all @@ -573,12 +572,7 @@ Export successful The exported file was written to:\n\n%1$s Access to external storage is required to read the OPML file - Database import/export - This experimental function can be used to transfer your subscriptions and played episodes to another device.\n\nExported databases can only be imported when using the same version of AntennaPod. Otherwise, this function will lead to unexpected behavior.\n\nAfter importing, episodes might be displayed as downloaded even though they are not. Just press the play button of the episodes to make AntennaPod detect this. - Import - Export Select file to import - Export successful. Import successful.\n\nPlease press OK to restart AntennaPod -- cgit v1.2.3 From bb8a7a2ac0889f9f3b7af6380a87de9f39631747 Mon Sep 17 00:00:00 2001 From: ByteHamster Date: Mon, 27 Jan 2020 10:46:42 +0100 Subject: Removed OPML import activity with only one button --- core/src/main/res/values/strings.xml | 4 ---- 1 file changed, 4 deletions(-) (limited to 'core/src') diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index 49b8875b6..d2774ac7a 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -554,15 +554,11 @@ Import your subscriptions from another podcast app Transfer subscriptions, listened episodes and queue to AntennaPod on another device Import AntennaPod database from another device - Option %1$d - Choose a specific file path from the local filesystem. - Many applications like Google Mail, Dropbox, Google Drive and most file managers can open OPML files with AntennaPod. OPML Import An error has occurred while reading the OPML document: No file selected! Select all Deselect all - From local filesystem OPML export HTML export Database export -- cgit v1.2.3 From 29bc5109a61c6bee9359a2986297917a2896405f Mon Sep 17 00:00:00 2001 From: ByteHamster Date: Fri, 31 Jan 2020 16:37:42 +0100 Subject: Do not restart sleep timer when automatically playing next episode --- .../danoeh/antennapod/core/service/playback/PlaybackService.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'core/src') diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java index d53f7d669..b9afb5c75 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java @@ -570,6 +570,7 @@ public class PlaybackService extends MediaBrowserServiceCompat { } else if (mediaPlayer.getPlayable() == null) { startPlayingFromPreferences(); } + taskManager.restartSleepTimer(); return true; case KeyEvent.KEYCODE_MEDIA_PLAY: if (status == PlayerStatus.PAUSED || status == PlayerStatus.PREPARED) { @@ -580,6 +581,7 @@ public class PlaybackService extends MediaBrowserServiceCompat { } else if (mediaPlayer.getPlayable() == null) { startPlayingFromPreferences(); } + taskManager.restartSleepTimer(); return true; case KeyEvent.KEYCODE_MEDIA_PAUSE: if (status == PlayerStatus.PLAYING) { @@ -827,9 +829,6 @@ public class PlaybackService extends MediaBrowserServiceCompat { @Override public void onPlaybackStart(@NonNull Playable playable, int position) { - if (taskManager.isSleepTimerActive()) { - taskManager.restartSleepTimer(); - } taskManager.startWidgetUpdater(); if (position != PlaybackServiceMediaPlayer.INVALID_TIME) { playable.setPosition(position); @@ -1446,10 +1445,12 @@ public class PlaybackService extends MediaBrowserServiceCompat { public void resume() { mediaPlayer.resume(); + taskManager.restartSleepTimer(); } public void prepare() { mediaPlayer.prepare(); + taskManager.restartSleepTimer(); } public void pause(boolean abandonAudioFocus, boolean reinit) { -- cgit v1.2.3 From 17444d9a3c275c4f2f865c8e6ec8b886f1e37e7f Mon Sep 17 00:00:00 2001 From: ByteHamster Date: Fri, 31 Jan 2020 17:33:49 +0100 Subject: Updated sleep timer UI --- .../core/service/playback/PlaybackService.java | 11 ++-- .../playback/PlaybackServiceTaskManager.java | 61 +++++++++++----------- .../core/util/playback/PlaybackController.java | 4 -- core/src/main/res/values/strings.xml | 7 +-- 4 files changed, 38 insertions(+), 45 deletions(-) (limited to 'core/src') diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java index 2fb37cc05..edcaacefc 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java @@ -745,10 +745,12 @@ public class PlaybackService extends MediaBrowserServiceCompat { setupPositionUpdater(); stateManager.validStartCommandWasReceived(); // set sleep timer if auto-enabled - if (newInfo.oldPlayerStatus != null && newInfo.oldPlayerStatus != PlayerStatus.SEEKING && - SleepTimerPreferences.autoEnable() && !sleepTimerActive()) { + if (newInfo.oldPlayerStatus != null && newInfo.oldPlayerStatus != PlayerStatus.SEEKING + && SleepTimerPreferences.autoEnable() && !sleepTimerActive()) { setSleepTimer(SleepTimerPreferences.timerMillis(), SleepTimerPreferences.shakeToReset(), SleepTimerPreferences.vibrate()); + EventBus.getDefault().post(new MessageEvent(getString(R.string.sleep_timer_enabled_label), + PlaybackService.this::disableSleepTimer)); } break; @@ -1007,17 +1009,14 @@ public class PlaybackService extends MediaBrowserServiceCompat { } public void setSleepTimer(long waitingTime, boolean shakeToReset, boolean vibrate) { - Log.d(TAG, "Setting sleep timer to " + Long.toString(waitingTime) + " milliseconds"); + Log.d(TAG, "Setting sleep timer to " + waitingTime + " milliseconds"); taskManager.setSleepTimer(waitingTime, shakeToReset, vibrate); sendNotificationBroadcast(NOTIFICATION_TYPE_SLEEPTIMER_UPDATE, 0); - EventBus.getDefault().post(new MessageEvent(getString(R.string.sleep_timer_enabled_label), - this::disableSleepTimer)); } public void disableSleepTimer() { taskManager.disableSleepTimer(); sendNotificationBroadcast(NOTIFICATION_TYPE_SLEEPTIMER_UPDATE, 0); - EventBus.getDefault().post(new MessageEvent(getString(R.string.sleep_timer_disabled_label))); } private void sendNotificationBroadcast(int type, int code) { diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceTaskManager.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceTaskManager.java index 736cf8cf2..62eda415e 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceTaskManager.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceTaskManager.java @@ -397,41 +397,42 @@ public class PlaybackServiceTaskManager { while (timeLeft > 0) { try { Thread.sleep(UPDATE_INTERVAL); - long now = System.currentTimeMillis(); - timeLeft -= now - lastTick; - lastTick = now; - - if(timeLeft < NOTIFICATION_THRESHOLD && !notifiedAlmostExpired) { - Log.d(TAG, "Sleep timer is about to expire"); - if(vibrate) { - Vibrator v = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE); - if(v != null) { - v.vibrate(500); - } - } - if(shakeListener == null && shakeToReset) { - shakeListener = new ShakeListener(context, this); - } - postCallback(callback::onSleepTimerAlmostExpired); - notifiedAlmostExpired = true; - } - if (timeLeft <= 0) { - Log.d(TAG, "Sleep timer expired"); - if(shakeListener != null) { - shakeListener.pause(); - shakeListener = null; - } - if (!Thread.currentThread().isInterrupted()) { - postCallback(callback::onSleepTimerExpired); - } else { - Log.d(TAG, "Sleep timer interrupted"); - } - } } catch (InterruptedException e) { Log.d(TAG, "Thread was interrupted while waiting"); e.printStackTrace(); break; } + + long now = System.currentTimeMillis(); + timeLeft -= now - lastTick; + lastTick = now; + + if (timeLeft < NOTIFICATION_THRESHOLD && !notifiedAlmostExpired) { + Log.d(TAG, "Sleep timer is about to expire"); + if (vibrate) { + Vibrator v = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE); + if (v != null) { + v.vibrate(500); + } + } + if (shakeListener == null && shakeToReset) { + shakeListener = new ShakeListener(context, this); + } + postCallback(callback::onSleepTimerAlmostExpired); + notifiedAlmostExpired = true; + } + if (timeLeft <= 0) { + Log.d(TAG, "Sleep timer expired"); + if (shakeListener != null) { + shakeListener.pause(); + shakeListener = null; + } + if (!Thread.currentThread().isInterrupted()) { + postCallback(callback::onSleepTimerExpired); + } else { + Log.d(TAG, "Sleep timer interrupted"); + } + } } } diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/playback/PlaybackController.java b/core/src/main/java/de/danoeh/antennapod/core/util/playback/PlaybackController.java index e7f6ad4f1..cb22fbcc9 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/playback/PlaybackController.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/playback/PlaybackController.java @@ -628,10 +628,6 @@ public class PlaybackController { return playbackService != null && playbackService.sleepTimerActive(); } - public boolean sleepTimerNotActive() { - return playbackService != null && !playbackService.sleepTimerActive(); - } - public void disableSleepTimer() { if (playbackService != null) { playbackService.disableSleepTimer(); diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index 88fa07049..93e20ab2e 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -312,6 +312,7 @@ Please confirm that you want to clear the queue of ALL of the episodes in it Old to new New to old + Time left:\u0020 Download Plugin @@ -566,12 +567,9 @@ Set sleep timer Disable sleep timer - Enter time Sleep timer - Time left:\u0020 Invalid input, time has to be an integer - When timer is about to expire: - Shake to reset timer + Shake to reset Vibrate seconds minutes @@ -590,7 +588,6 @@ Auto-enable Sleep timer enabled - Sleep timer disabled CATEGORIES -- cgit v1.2.3 From 8356226e975f9be5dc0b082ebe5ece9585cc95ea Mon Sep 17 00:00:00 2001 From: ByteHamster Date: Sat, 1 Feb 2020 18:02:19 +0100 Subject: Always allow clicking timecodes --- .../de/danoeh/antennapod/core/util/playback/Timeline.java | 13 ++----------- core/src/main/res/values/strings.xml | 1 + 2 files changed, 3 insertions(+), 11 deletions(-) (limited to 'core/src') diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/playback/Timeline.java b/core/src/main/java/de/danoeh/antennapod/core/util/playback/Timeline.java index 5b9452d6f..8624ec7e5 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/playback/Timeline.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/playback/Timeline.java @@ -106,11 +106,10 @@ public class Timeline { * This method does NOT change the original shownotes string of the shownotesProvider object and it should * also not be changed by the caller. * - * @param addTimecodes True if this method should add timecode links * @return The processed HTML string. */ @NonNull - public String processShownotes(final boolean addTimecodes) { + public String processShownotes() { final Playable playable = (shownotesProvider instanceof Playable) ? (Playable) shownotesProvider : null; // load shownotes @@ -155,10 +154,7 @@ public class Timeline { document.head().appendElement("style").attr("type", "text/css").text(styleStr); // apply timecode links - if (addTimecodes) { - addTimecodes(document, playable); - } - + addTimecodes(document, playable); return document.toString(); } @@ -188,11 +184,6 @@ public class Timeline { return -1; } - - public void setShownotesProvider(@NonNull ShownotesProvider shownotesProvider) { - this.shownotesProvider = shownotesProvider; - } - private void addTimecodes(Document document, final Playable playable) { Elements elementsWithTimeCodes = document.body().getElementsMatchingOwnText(TIMECODE_REGEX); Log.d(TAG, "Recognized " + elementsWithTimeCodes.size() + " timecodes"); diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index 88fa07049..f9e38ded9 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -192,6 +192,7 @@ Marked as played Mark as read Marked as read + To jump to positions, you need to play the episode %d episode marked as played. %d episodes marked as played. -- cgit v1.2.3 From c174b3dcc158dceea35b599b5c4aaefa375fb9fb Mon Sep 17 00:00:00 2001 From: ByteHamster Date: Sat, 1 Feb 2020 18:28:58 +0100 Subject: Updated translations --- core/src/main/res/values-de/strings.xml | 2 +- core/src/main/res/values-fr/strings.xml | 6 +-- core/src/main/res/values-gl-rES/strings.xml | 79 +++++++++++++++-------------- core/src/main/res/values-uk-rUA/strings.xml | 53 ++++++++++++++++--- core/src/main/res/values-zh-rCN/strings.xml | 2 + 5 files changed, 93 insertions(+), 49 deletions(-) (limited to 'core/src') diff --git a/core/src/main/res/values-de/strings.xml b/core/src/main/res/values-de/strings.xml index 444bf4314..379693f9f 100644 --- a/core/src/main/res/values-de/strings.xml +++ b/core/src/main/res/values-de/strings.xml @@ -462,7 +462,7 @@ Füge heruntergeladene Episoden zur Abspielliste hinzu Androids eingebauter Abspieler Stille im Ton überspringen - Beim Beenden des Videos + Beim Beenden von Videos Verhalten beim Verlassen der Video-Wiedergabe Wiedergabe anhalten Audiowiedergabe fortsetzen diff --git a/core/src/main/res/values-fr/strings.xml b/core/src/main/res/values-fr/strings.xml index e03b1e301..a27013c44 100644 --- a/core/src/main/res/values-fr/strings.xml +++ b/core/src/main/res/values-fr/strings.xml @@ -261,7 +261,7 @@ Déverrouiller la liste de lecture Liste de lecture verrouillée Liste de lecture déverrouillée - Quand la liste de lecture est verrouillée il n\'est pas possible de swiper ou de réorganiser l\'ordre des épisodes. + Quand la liste est verrouillée il n\'est plus possible d\'utiliser le swipe ou de changer l\'ordre des épisodes. Ne pas réafficher Effacer la liste de lecture Annuler @@ -361,7 +361,7 @@ Afficher dans les listes le bouton du streaming au lieu de celui du téléchargement. Utilisation de la connexion mobile Choisir ce qui est autorisé lorsque la connexion mobile est utilisée - Rafraîchissement des flux + Mise à jour des flux Récupération des images Téléchargement automatique Téléchargement d\'épisodes @@ -387,7 +387,7 @@ Nombre d\'épisodes stockés Nombre maximum d\'épisodes stockés sur l\'appareil. Le téléchargement automatique sera suspendu si ce nombre est atteint. Image des épisodes - Lorsqu\'elle existe, utiliser l\'image propre aux épisodes au lieu de celle du podcast. + Lorsqu\'elles existent, utiliser les images propres aux épisodes au lieu de celle du podcast. Thème du système Clair Sombre diff --git a/core/src/main/res/values-gl-rES/strings.xml b/core/src/main/res/values-gl-rES/strings.xml index 4a0131a20..42b46be47 100644 --- a/core/src/main/res/values-gl-rES/strings.xml +++ b/core/src/main/res/values-gl-rES/strings.xml @@ -23,7 +23,7 @@ Sincronizar con outros dispositivos gpodder.net Conexión Caché de episodios chea - Acadouse o límite de espazo na caché de episodios. Pode incrementalo nos Axustes do tamaño da caché. + Acadouse o límite de espazo na caché de episodios. Podes incrementalo nos Axustes do tamaño da caché. Tempo total dos podcast reproducidos: %1$d de %2$d episodios iniciados.\n\nReproducidos %3$s de %4$s. @@ -68,7 +68,7 @@ Produciuse un fallo: Precísase o permiso de almacenamento para esta operación Actualizar - Non se dispón de almacenamento externo. Por favor asegúrese de que o almacenamento externo está montado e así a aplicación poderá funcionar correctamente. + Non se dispón de almacenamento externo. Por favor asegúrate de que o almacenamento externo está montado e así a aplicación poderá funcionar correctamente. Capítulos Duración: %1$s Descrición @@ -79,7 +79,7 @@ Reintentar Incluír en descargas automáticas Aplicar a episodios previos - A nova función Descarga automática aplicarase automáticamente aos novos episodios.\nQuere que tamén se aplique aos episodios publicados con anterioridade? + A nova función Descarga automática aplicarase automáticamente aos novos episodios.\nQueres que tamén se aplique aos episodios publicados con anterioridade? Borrado automático do episodio \u0020descargas paralelas Valor xeral por omisión @@ -111,8 +111,8 @@ Por favor confirme que quere marcar todos os episodios como reproducidos. Por favor, confirme que quere marcar todos os episodios deste podcast como reproducidos. Quitarlle a marca de \"novidade\" a todo - Eliminou todas as \"novas\" marcas - Por favor, confirme que quere quitar marca de \"novidade\" a todos os episodios. + Eliminaches o aviso de \"novos\" episodios + Confirma que queres quitarlle marca de \"novidade\" a todos os episodios. Mostrar información Mostrar axustes do podcast Información do podcast @@ -235,7 +235,7 @@ Precísase autenticación O recurso solicitado require un usuario e contrasinal Confirme a descarga con datos do móbil - Descargar coa conexión de datos do móbil está desactivada nos axustes.\n\nPode escoller ben só engadir o episodio a cola ou pode permitir a descarga temporalmente.\n\n A súa elección lembrarase durante 10 minutos. + Descargar coa conexión de datos do móbil está desactivada nos axustes.\n\nPodes escoller ben só engadir o episodio a cola ou podes permitir a descarga temporalmente.\n\n A túa elección lembrarase durante 10 minutos. A descarga con datos móbiles está desactivada nos axustes.\n\nQuere permitir a descarga temporalmente?\n\n A súa decisión lembrarase durante 10 minutos. Confirmar retransmisión Móbil Desactivouse nos axustes Retransmitir mediante a conexión de datos. Toque para retransmitir igualmente. @@ -262,7 +262,7 @@ Cola bloqueada Cola desbloqueada Se bloqueas a cola, non poderás quitar ou mover os episodios. - Non mostrar outra vez + Non mostrar de novo Limpar cola Desfacer Mover arriba @@ -288,12 +288,12 @@ Habilitar Sonic Sen episodios na cola - Engada un episodio descargándoo, ou manteña preso un episodio e escolla \"Engadir a cola\". + Engade un episodio descargándoo, ou mantén preso un episodio e escolle \"Engadir a cola\". Este episodio non ten notas de episodio. Sen descargas activas - Pode descargar episodios na pantalla con detalles do episodio. + Podes descargar episodios na pantalla con detalles do podcast. Sen episodios descargados - Pode descargar episodios na pantalla de detalles do podcast. + Podes descargar episodios na pantalla de detalles do podcast. Sen rexistro da descarga Os rexistros de descarga aparecerán aquí se están dispoñibles. Sen Historial @@ -301,9 +301,9 @@ Sen episodios Cando engade un podcast, os episodios mostraranse aquí. Sen episodios novos - Cando reciba novos episodios, mostraranse aquí. + Cando recibas novos episodios, mostraranse aquí. Sen episodios favoritos - Pode engadir episodios aos favoritos manténdoos pulsados. + Podes engadir episodios aos favoritos manténdoos presos. Sen capítulos Este episodio non ten capítulos. Sen subscricións @@ -326,12 +326,12 @@ Limpar historial Reprodutor de medios Limpeza de episodios - Os episodios que non están na cola e tampouco son favoritos deberían poder ser candidatos a ser eliminados si a función Descarga Automática precisa espazo para novos episodios. + Os episodios que non están na cola e tampouco son favoritos deberían poder ser candidatos a ser eliminados se a función Descarga Automática precisa espazo para novos episodios. Deter a reprodución cando se desconectan os auriculares ou bluetooth Retomar a reprodución cando se conectan os auriculares Retomar a reprodución cando se reconecta o bluetooth O botón Adiante salta - A premer no botón de adiante nun dispositivo conectado por bluetooth ir ao episodio seguinte en vez dun avance rápido + A premer no botón de adiante nun dispositivo conectado por bluetooth ir ao episodio seguinte no lugar de avance rápido O botón Anterior reinicia Cando se presiona Anterior no dispositivo reinicia o episodio no lugar de ir cara atrás Saltar ao seguinte elemento na cola cando remata o episodio @@ -347,7 +347,7 @@ Rede Intervalo de actualización ou Hora do día Indicar un intervalo ou unha hora en concreto para actualizar automaticamente as fontes - Pode establecer un intervalo como \"2 horas\", unha hora do día en concreto como \"7:00 AM\" ou desactivar totalmente a actualización automática.\n\nAviso: pode haber un lixeiro retardo do momento da actualización. + Podes establecer un intervalo como \"2 horas\", unha hora do día en concreto como \"7:00 AM\" ou desactivar totalmente a actualización automática.\n\nAviso: pode haber un lixeiro retardo do momento da actualización. Desactivar Establecer intervalo Establecer hora do día @@ -360,17 +360,17 @@ Preferir Difusión Mostrar botón de difusión no lugar de botón de descarga nas listas. Actualizacións Móbil - Escolla o que estará permitido utilizando conexión de datos do móbil + Escolle o que estará permitido utilizando conexión de datos do móbil Actualizar fontes Imaxes de portadas Descarga automática Descarga de episodio Retransmisión Interface de usuaria - Escolla o decorado - Estableza os elementos da Caixa de navegación + Escolle o decorado + Escoller os elementos da Caixa de navegación Cambie os elementos que aparecerán na Caixa de navegación - Estableza a orde das subscricións + Indicar a orde das subscricións Cambie a orde das subscricións Establecer o contador de subscricións Cambiar a información mostrada polo contador de subscricións. Tamén afecta á orde das subscricións se \"Orde das subscricións\" está establecida a \"Contador\". @@ -412,14 +412,14 @@ Mostrar notificacións de erros na sincronización. Esta preferencia non se aplica a fallos na autenticación. Velocidades de reprodución - Personalice a velocidade variable de reprodución de audio + Personaliza a velocidade variable de reprodución de audio A velocidade a utilizar cando se reproduce o audio dos episodios de esta fonte Axustar info dos medios a velocidade de reprodución A posición mostrada e a duración están adaptadas a velocidade de reprodución Avance rápido Salta tempo - Personalice o número de segundos a avanzar cando o se pulsa o botón de avance rápido + Personaliza o número de segundos a avanzar cando o se preme o botón de avance rápido Retroceso Salta tempo - Personalice o número de segundos que se retrocede na reprodución cando se pulsa o botón retroceso + Personaliza o número de segundos que se retrocede na reprodución cando se preme o botón retroceso Establecer servidor Utilizar servidor por omisión Alta prioridade nas notificacións @@ -428,13 +428,14 @@ Manter notificación e controles na pantalla de bloqueo cando a reprodución está pausada. Establecer botóns de pantalla de bloqueo Cambiar os botóns de reprodución na pantalla de bloqueo. O botón reproducir/pausa sempre se inclúe. - Escolla un máximo de %1$d elementos - Só pode selecionar un máximo de %1$d elementos. + Escolle un máximo de %1$d elementos + Só podes selecionar un máximo de %1$d elementos. Establecer fondo da pantalla de bloqueo Establecer o fondo de pantalla de bloqueo coa imaxe do episodio actual. Como consecuencia, esto tamén mostrará a imaxe en aplicacións de terceiros. Mostrar informe de descarga Si falla a descarga, xerar un informe que informe dos detalles do fallo. As versións de Android anteriores a 4.1 non teñen soporte para notificacións expandidas. + Situación na cola Engadir episodios a: %1$s Atrás Diante @@ -448,7 +449,7 @@ Copiar ó portapapeis Copiado ó portapapeis En probas - Escolla o reprodutor de medios para reproducir ficheiros + Escolle o reprodutor de medios para reproducir ficheiros Valor actual: %1$s Proxy Establecer un proxy para a rede @@ -500,7 +501,7 @@ Non hai resultados para \"%1$s\" Opción %1$d - Escolla unha ruta de ficheiro concreta no sistema de ficheiros local. + Escolle unha ruta de ficheiro concreta no sistema de ficheiros local. Moitas aplicacións, como Google Mail, Dropbox, Google Drive e a maioría dos xestores de ficheiros poden abrir ficheiros OPML con AntennaPod. Importar OPML Lendo ficheiro OPML @@ -552,21 +553,21 @@ Conexión Benvida ao proceso de conexión a gpodder.net. Primeiro, escriba os seus datos de conexión: Conexión - Se aínda non ten unha conta, pode crear unha aquí:\nhttps://gpodder.net/register/ + Se aínda non tes unha conta, podes crear unha aquí:\nhttps://gpodder.net/register/ Nome de usuaria Contrasinal Selección de dispositivo - Crear un novo dispositivo para usar coa sua conta gpodder.net ou escoller un existente: + Crear un novo dispositivo para usar coa túa conta gpodder.net ou escoller un existente: ID de dispositivo:\u0020 Título Crear un novo dispositivo Escolle un novo dispositivo: - O ID do dispositivo non pode quedar baldeiro + O ID do dispositivo non pode quedar baleiro ID de dispositivo xa en uso - Non pode quedar baldeiro o titulo + O título non pode estar baleiro Escoller Conexión correcta! - Parabéns! A súa conta gpodder.net está conectada ao dispositivo. AntennaPod poderá agora sincronizar automaticamente as súas subscricións no dispositivo na conta de gpodder.net + Parabéns! A túa conta gpodder.net está conectada ao dispositivo. AntennaPod poderá agora sincronizar automaticamente as túas subscricións no dispositivo na conta de gpodder.net Iniciar a sincronización Ir a pantalla principal fallo na autenticación en gpodder.net @@ -580,20 +581,20 @@ Cartafol escollido: Crear cartafol Escoller cartafol de datos - Por favor escolla a base do cartafol dos seus datos. AntennaPod creará os subcartafoles axeitados. + Por favor escolle a base do cartafol dos teus datos. AntennaPod creará os subcartafoles axeitados. Precísase o acceso ao almacenamento externo para mudar o cartafol de datos %1$s de %2$s libre Crear un novo cartafol de nome \"%1$s\"? Novo cartafol creado - Non se pode escribir en este cartafol + Non se pode escribir neste cartafol O cartafol xa existe Non se creou o cartafol \"%1$s\" non existe \"%1$s\" non se pode ler non se pode escribir en \"%1$s\" - O cartafol non está baldeiro - O cartafol escollido non está baldeiro. As descargas de medios e outros ficheiros situaranse directamente en este cartafol. Proceder de todos xeitos? - Escolla o cartafol por omisión + O cartafol non está baleiro + O cartafol escollido non está baleiro. As descargas de medios e outros ficheiros situaranse directamente neste cartafol. Utilizalo igualmente? + Escolle o cartafol por omisión Pausar a reprodución en lugar de baixar o volume cando outra aplicación quere reproducir un son. Pausa para interrupcións Retomar a reprodución despois de rematar a chamada telefónica @@ -685,7 +686,7 @@ Comprobando... Proba exitosa Fallo na proba - Servidor non pode quedar baldeiro + Servidor non pode quedar baleiro O servidor indicado non é un dominio ou IP válidos Porto non válido @@ -695,7 +696,7 @@ Esta función experimental utilízase para transferir as súas subscricións e episodios reproducidos noutro dispositivo.\n\nAs bases de datos exportadas só se poden importar se utiliza a misma versión de AntennaPod. De todos xeitos, esta función pode comportarse de xeito raro.\n\nDespois de importar, os episodios poderían ser mostrados como descargados sin telo sido. Simplemente pulse o botón de reprodución dos episodios para que AntennaPod detecte esto. Importar Exportar - Escolla o ficheiro a importar + Escolle o ficheiro a importar Exportado con éxito. Importación correcta.\n\nPulse OK para reiniciar AntennaPod @@ -708,7 +709,7 @@ Non se puido establecer o volume Non hai conexión ao dispositivo de emisión - Perdeuse a conexión ao dispositivo de emisión. A aplicación está a intentar restablecela se fose posible. Por favor, agarde uns segundos e inténteo de novo. + Perdeuse a conexión ao dispositivo de emisión. A aplicación está a intentar restablecela se fose posible. Por favor, agarda uns intres e inténtao outra vez. Fallo de sincronización co dispositivo de emisión Non se puido cambiar a posición no dispositivo de emisión O reprodutor receptor atopou un fallo grave diff --git a/core/src/main/res/values-uk-rUA/strings.xml b/core/src/main/res/values-uk-rUA/strings.xml index 34d2b0ebe..37f1049ac 100644 --- a/core/src/main/res/values-uk-rUA/strings.xml +++ b/core/src/main/res/values-uk-rUA/strings.xml @@ -105,6 +105,7 @@ Посилання на канал чи сторінку Додати подкаст за URL Переглянути gpodder.net + більше » Позначити всі як відтворені Позначено всі епізоди як відтворені @@ -117,12 +118,13 @@ Перейменувати подкаст Видалити подкаст Поділитися… - Поділитись посиланням на епізод + Поділитися посиланням на епізод Поділіться посиланням на епізод з позицією відтворення - Поділитись файлом - Поділитись посиланням на канал - Поділитись посиланням на медіа-файл - Поділитись посиланням на медіа-файл з позицією відтворення + Поділитися файлом + Поділитися посиланням на сайт + Поділитися посиланням на канал + Поділитися посиланням на медіа-файл + Поділитися посиланням на медіа-файл з позицією відтворення Будь ласка, підтвердіть що ви бажаєте видалити подкаст \"%1$s\" і ВСІ його епізоди (разом з завантаженими). Видалення подкасту Оновити весь подкаст @@ -245,6 +247,7 @@ Підтвердження завантажень через мобільні мережі Завантаження через мобільні мережі вимкнено в налаштуваннях.\n\nВибрати додавання епізоду до черги чи тимчасове завантаження?\n\nВаш вибір буде дійсним 10 хвилин. Завантаження через мобільні мережі вимкнено в налаштуваннях.\n\nУвімкнути тимчасово?\n\nВаш вибір буде дійсним 10 хвилин. + Завжди дозволяти Лише додати до черги Увімкнути тимчасово @@ -254,6 +257,7 @@ Готов Шукаю Сервер помер + Тип медіа не підтримується Невідома помилка Немає що грати Буферізую @@ -264,6 +268,7 @@ Розблокувати чергу Чергу заблоковано Чергу розблоковано + Більше не показувати Очистити чергу Скасувати Догори @@ -278,6 +283,8 @@ За зростанням За спаданням Будь ласка, підтвердіть що ви бажаєте вилучити всі епізоди з черги. + Спочатку старіші + Спочатку новіші Завантажити додаток Додаток не встановлено @@ -301,7 +308,10 @@ Коли з’являться нові епізоди, іх буде показано тут. Немає улюблених епізодів Ви можете додавати епізоди до улюблених за допомогою довгого натискання. - В цьому епізоді немає розділів. + Немає глав + В цьому епізоді немає глав. + Немає підписок + Щоб підписатись на подкаст, натисніть на значок плюса нижче Зберігання Проект @@ -314,6 +324,9 @@ Вигляд Зовнішні елементи Тимчасові паузи + Пошук... + Немає результатів + Очистити історію Медіа програвач Очищення епізодів Епізоди що не знаходяться в черзі та не помічені як улюблені можуть бути видалені якщо Автозавантажувач потребуватиме місце для нових епізодів. @@ -365,6 +378,7 @@ Дозволити автозавантаження коли зарядний пристрій не підключений Паралельні завантаження Кеш епізодів + Використовувати системну тему Світла Темна Чорна (для AMOLED) @@ -389,6 +403,7 @@ Це налаштування не застосовується до помилок автентифікації. Швидкість програвання Налаштування швідкості доступно для змінної швидкості програвання + Виберіть швидкість відтворення епізодів з цього каналу Час, що пропускається кнопкою перемотки вперед Налаштувати кількість секунд, які пропускаються при натисканні кнопки перемотки вперед Час, що пропускається кнопкою відмотки назад @@ -408,14 +423,21 @@ Показати звіт про завантаження У разі помилки при завантаженні створити детальний звіт про помилку. Android до версії 4.1 не підтримує розширені повідомлення. + Додати епізоди до: %1$s + Після поточного епізоду Вимкнено Розмір кеша зображень Розмір дискового кеша для зображень. + Повідомити про помилку + Відкрити трекер помилок + Копіювати + Скопійовано Експериментальні Оберіть медіа плеєр для програвання файлів Поточне значення: %1$s Проксі Застосувати проксі сервер + Часті питання Веб браузер не знайдено. Підтримка для Chromecast Включити підтримку програвання на таких пристроях як Chromecast або Android TV @@ -443,6 +465,14 @@ Автоматично видаляти епізод із черги, коли він буде видалений. Про програму + Версія AntennaPod + Розробники + Кожен може допомогти AntennaPod стати краще + Перекладачі + Переклади створюються користувачами AntennaPod за допомогою Transifex + Політика конфіденційності + Ліцензії + AntennaPod використовує інше чудове програмне забезпечення Пошук епізодів Знайдено в нотатках епізода @@ -536,12 +566,14 @@ Трапилась помилка при сінхронизації:\u0020 Успішно Невдало + Імена користувачів можуть містити лише літери, цифри, дефіси та підкреслення. Обрати папку: Нова папка Обрати папку Оберіть, будь ласка, базовий каталог даних. AntennaPod створить відповідні підрозділи. Для зміни папки зберігання даних потрібен доступ до зовнішнього носія + %1$s з %2$s вільно Створити папку з ім\'ям \"%1$s\"? Створена нова папка Не можу записати в цю папку @@ -560,6 +592,7 @@ Для застосування змін потрібно перезапустити AntennaPod Підписатися + Підписка... Перемотка назад Перемотка вперед @@ -580,13 +613,17 @@ Виключити Окремі слова \n\"Кілька слів\" Підтримувати оновленим + Включити цей канал під час (авто-)оновлення всіх каналів + Автозавантаження вимкнено в налаштуваннях AntennaPod Оновлення бази даних Імпорт подкастів з інших програм... + Шукати подкаст... Пошук в iTunes Шукати в fyyd + Розширений пошук Фільтр Всі @@ -676,5 +713,9 @@ Дозволяє керувати відтворенням. Це основне сповіщення, яке ви бачите під час відтворення подкасту. Помилки Відображається, якщо щось пішло не так, наприклад, якщо не вдалося завантажити або синхронізувати з gpodder. + Недоступний/пошкоджений файл + Налаштування віджету + Створити віджет + Непрозорість diff --git a/core/src/main/res/values-zh-rCN/strings.xml b/core/src/main/res/values-zh-rCN/strings.xml index 123c1cc0d..758e7de78 100644 --- a/core/src/main/res/values-zh-rCN/strings.xml +++ b/core/src/main/res/values-zh-rCN/strings.xml @@ -274,6 +274,7 @@ 插件下载 插件没有安装 + 为了使变速播放正常工作,我们建议启用内置的Sonic媒体播放器 播放速度 允许声音 @@ -712,6 +713,7 @@ 发生错误时显示,比如下载或与gpodder的同步失败 无效/损坏文件 + 小部件设置 创建小部件 不透明度 -- cgit v1.2.3 From edef730bd4bb642cc3d0b8496be34ef3c8e59b20 Mon Sep 17 00:00:00 2001 From: ByteHamster Date: Sat, 1 Feb 2020 19:08:11 +0100 Subject: Clean up statistics Removed unused `StatisticsData` wrapper class and extracted `StatisticsItem` to new class --- .../danoeh/antennapod/core/storage/DBReader.java | 72 ++-------------------- .../antennapod/core/storage/StatisticsItem.java | 51 +++++++++++++++ 2 files changed, 55 insertions(+), 68 deletions(-) create mode 100644 core/src/main/java/de/danoeh/antennapod/core/storage/StatisticsItem.java (limited to 'core/src') 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 e6d21794c..e2da40ec3 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 @@ -866,17 +866,15 @@ public final class DBReader { } /** - * Searches the DB for statistics + * Searches the DB for statistics. * - * @return The StatisticsInfo object + * @return The list of statistics objects */ @NonNull - public static StatisticsData getStatistics() { + public static List getStatistics() { PodDBAdapter adapter = PodDBAdapter.getInstance(); adapter.open(); - long totalTimeCountAll = 0; - long totalTime = 0; List feedTime = new ArrayList<>(); List feeds = getFeedList(); @@ -922,72 +920,10 @@ public final class DBReader { feedTime.add(new StatisticsItem( feed, feedTotalTime, feedPlayedTime, feedPlayedTimeCountAll, episodes, episodesStarted, episodesStartedIncludingMarked, totalDownloadSize)); - totalTime += feedPlayedTime; - totalTimeCountAll += feedPlayedTimeCountAll; } adapter.close(); - return new StatisticsData(totalTime, totalTimeCountAll, feedTime); - } - - public static class StatisticsData { - /** - * Simply sums up time of podcasts that are marked as played - */ - public final long totalTimeCountAll; - - /** - * Respects speed, listening twice, ... - */ - public final long totalTime; - - public final List feeds; - - public StatisticsData(long totalTime, long totalTimeCountAll, List feeds) { - this.totalTime = totalTime; - this.totalTimeCountAll = totalTimeCountAll; - this.feeds = feeds; - } - } - - public static class StatisticsItem { - public final Feed feed; - public final long time; - - /** - * Respects speed, listening twice, ... - */ - public final long timePlayed; - /** - * Simply sums up time of podcasts that are marked as played - */ - public final long timePlayedCountAll; - public final long episodes; - /** - * Episodes that are actually played - */ - public final long episodesStarted; - /** - * All episodes that are marked as played (or have position != 0) - */ - public final long episodesStartedIncludingMarked; - /** - * Simply sums up the size of download podcasts - */ - public final long totalDownloadSize; - - public StatisticsItem(Feed feed, long time, long timePlayed, long timePlayedCountAll, - long episodes, long episodesStarted, long episodesStartedIncludingMarked, - long totalDownloadSize) { - this.feed = feed; - this.time = time; - this.timePlayed = timePlayed; - this.timePlayedCountAll = timePlayedCountAll; - this.episodes = episodes; - this.episodesStarted = episodesStarted; - this.episodesStartedIncludingMarked = episodesStartedIncludingMarked; - this.totalDownloadSize = totalDownloadSize; - } + return feedTime; } /** diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/StatisticsItem.java b/core/src/main/java/de/danoeh/antennapod/core/storage/StatisticsItem.java new file mode 100644 index 000000000..f96af185b --- /dev/null +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/StatisticsItem.java @@ -0,0 +1,51 @@ +package de.danoeh.antennapod.core.storage; + +import de.danoeh.antennapod.core.feed.Feed; + +public class StatisticsItem { + public final Feed feed; + public final long time; + + /** + * Respects speed, listening twice, ... + */ + public final long timePlayed; + + /** + * Simply sums up time of podcasts that are marked as played. + */ + public final long timePlayedCountAll; + + /** + * Number of episodes. + */ + public final long episodes; + + /** + * Episodes that are actually played. + */ + public final long episodesStarted; + + /** + * All episodes that are marked as played (or have position != 0). + */ + public final long episodesStartedIncludingMarked; + + /** + * Simply sums up the size of download podcasts. + */ + public final long totalDownloadSize; + + public StatisticsItem(Feed feed, long time, long timePlayed, long timePlayedCountAll, + long episodes, long episodesStarted, long episodesStartedIncludingMarked, + long totalDownloadSize) { + this.feed = feed; + this.time = time; + this.timePlayed = timePlayed; + this.timePlayedCountAll = timePlayedCountAll; + this.episodes = episodes; + this.episodesStarted = episodesStarted; + this.episodesStartedIncludingMarked = episodesStartedIncludingMarked; + this.totalDownloadSize = totalDownloadSize; + } +} -- cgit v1.2.3 From 42313f5cea1c593e4d531c2ee3203b68f432b394 Mon Sep 17 00:00:00 2001 From: ByteHamster Date: Sat, 1 Feb 2020 19:24:13 +0100 Subject: Removed unused code --- .../core/preferences/UserPreferences.java | 8 ------ .../core/service/playback/PlaybackService.java | 1 - .../danoeh/antennapod/core/util/QueueAccess.java | 32 ---------------------- 3 files changed, 41 deletions(-) (limited to 'core/src') diff --git a/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java b/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java index 4f871e83b..9db5eb212 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java +++ b/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java @@ -805,14 +805,6 @@ public class UserPreferences { prefs.edit().putString(PREF_MEDIA_PLAYER, "sonic").apply(); } - public static void enableExoplayer() { - prefs.edit().putString(PREF_MEDIA_PLAYER, PREF_MEDIA_PLAYER_EXOPLAYER).apply(); - } - - public static void enableBuiltin() { - prefs.edit().putString(PREF_MEDIA_PLAYER, "builtin").apply(); - } - public static boolean stereoToMono() { return prefs.getBoolean(PREF_STEREO_TO_MONO, false); } diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java index edcaacefc..e01d1fdf2 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java @@ -151,7 +151,6 @@ public class PlaybackService extends MediaBrowserServiceCompat { public static final int EXTRA_CODE_CAST = 3; public static final int NOTIFICATION_TYPE_ERROR = 0; - public static final int NOTIFICATION_TYPE_INFO = 1; public static final int NOTIFICATION_TYPE_BUFFER_UPDATE = 2; /** diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/QueueAccess.java b/core/src/main/java/de/danoeh/antennapod/core/util/QueueAccess.java index 9408be348..ec8b8a430 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/QueueAccess.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/QueueAccess.java @@ -26,36 +26,4 @@ public abstract class QueueAccess { private QueueAccess() { } - - public static QueueAccess ItemListAccess(final List items) { - return new QueueAccess() { - @Override - public boolean contains(long id) { - if (items == null) { - return false; - } - for (FeedItem item : items) { - if (item.getId() == id) { - return true; - } - } - return false; - } - - @Override - public boolean remove(long id) { - Iterator it = items.iterator(); - FeedItem item; - while (it.hasNext()) { - item = it.next(); - if (item.getId() == id) { - it.remove(); - return true; - } - } - return false; - } - }; - } - } -- cgit v1.2.3 From 05b4945233c1dd04efdf4f3c47e68df6f0a25aef Mon Sep 17 00:00:00 2001 From: ByteHamster Date: Sun, 2 Feb 2020 10:50:16 +0100 Subject: Fixed crash when tapping external link in shownotes --- core/src/main/java/de/danoeh/antennapod/core/util/IntentUtils.java | 1 + 1 file changed, 1 insertion(+) (limited to 'core/src') diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/IntentUtils.java b/core/src/main/java/de/danoeh/antennapod/core/util/IntentUtils.java index 656b518bf..959a3e574 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/IntentUtils.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/IntentUtils.java @@ -38,6 +38,7 @@ public class IntentUtils { public static void openInBrowser(Context context, String url) { try { Intent myIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); + myIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); context.startActivity(myIntent); } catch (ActivityNotFoundException e) { Toast.makeText(context, R.string.pref_no_browser_found, Toast.LENGTH_LONG).show(); -- cgit v1.2.3 From 998a17a852323f96f0fdaa6feaa3136a694d93c6 Mon Sep 17 00:00:00 2001 From: ByteHamster Date: Sun, 2 Feb 2020 17:09:25 +0100 Subject: Update speed when changing feed defaults --- .../core/event/settings/SpeedPresetChangedEvent.java | 19 +++++++++++++++++++ .../core/service/playback/PlaybackService.java | 19 ++++++++++++++++++- 2 files changed, 37 insertions(+), 1 deletion(-) create mode 100644 core/src/main/java/de/danoeh/antennapod/core/event/settings/SpeedPresetChangedEvent.java (limited to 'core/src') diff --git a/core/src/main/java/de/danoeh/antennapod/core/event/settings/SpeedPresetChangedEvent.java b/core/src/main/java/de/danoeh/antennapod/core/event/settings/SpeedPresetChangedEvent.java new file mode 100644 index 000000000..0ac7e1316 --- /dev/null +++ b/core/src/main/java/de/danoeh/antennapod/core/event/settings/SpeedPresetChangedEvent.java @@ -0,0 +1,19 @@ +package de.danoeh.antennapod.core.event.settings; + +public class SpeedPresetChangedEvent { + private final float speed; + private final long feedId; + + public SpeedPresetChangedEvent(float speed, long feedId) { + this.speed = speed; + this.feedId = feedId; + } + + public float getSpeed() { + return speed; + } + + public long getFeedId() { + return feedId; + } +} diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java index edcaacefc..3a8302be7 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java @@ -50,6 +50,7 @@ import de.danoeh.antennapod.core.R; import de.danoeh.antennapod.core.event.MessageEvent; import de.danoeh.antennapod.core.event.PlaybackPositionEvent; import de.danoeh.antennapod.core.event.ServiceEvent; +import de.danoeh.antennapod.core.event.settings.SpeedPresetChangedEvent; import de.danoeh.antennapod.core.event.settings.VolumeAdaptionChangedEvent; import de.danoeh.antennapod.core.feed.Chapter; import de.danoeh.antennapod.core.feed.Feed; @@ -79,6 +80,9 @@ import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.disposables.Disposable; import org.greenrobot.eventbus.EventBus; import org.greenrobot.eventbus.Subscribe; +import org.greenrobot.eventbus.ThreadMode; + +import static de.danoeh.antennapod.core.feed.FeedPreferences.SPEED_USE_GLOBAL; /** * Controls the MediaPlayer that plays a FeedMedia-file @@ -1436,12 +1440,25 @@ public class PlaybackService extends MediaBrowserServiceCompat { } }; - @Subscribe + @Subscribe(threadMode = ThreadMode.MAIN) public void volumeAdaptionChanged(VolumeAdaptionChangedEvent event) { PlaybackVolumeUpdater playbackVolumeUpdater = new PlaybackVolumeUpdater(); playbackVolumeUpdater.updateVolumeIfNecessary(mediaPlayer, event.getFeedId(), event.getVolumeAdaptionSetting()); } + @Subscribe(threadMode = ThreadMode.MAIN) + public void speedPresetChanged(SpeedPresetChangedEvent event) { + if (getPlayable() instanceof FeedMedia) { + if (((FeedMedia) getPlayable()).getItem().getFeed().getId() == event.getFeedId()) { + if (event.getSpeed() == SPEED_USE_GLOBAL) { + setSpeed(UserPreferences.getPlaybackSpeed(getPlayable().getMediaType())); + } else { + setSpeed(event.getSpeed()); + } + } + } + } + public static MediaType getCurrentMediaType() { return currentMediaType; } -- cgit v1.2.3 From b2fb239853de79e9666f405599bd708f962c3177 Mon Sep 17 00:00:00 2001 From: ByteHamster Date: Sun, 2 Feb 2020 17:33:38 +0100 Subject: Enforce valid javadoc --- core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java | 2 +- .../main/java/de/danoeh/antennapod/core/util/TimeSpeedConverter.java | 2 +- .../de/danoeh/antennapod/core/util/syndication/HtmlToPlainText.java | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'core/src') 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 e2da40ec3..4f4ee4721 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 @@ -689,7 +689,7 @@ public final class DBReader { * Returns credentials based on image URL * * @param imageUrl The URL of the image - * @return Credentials in format ":", empty String if no authorization given + * @return Credentials in format "Username:Password", empty String if no authorization given */ public static String getImageAuthentication(final String imageUrl) { Log.d(TAG, "getImageAuthentication() called with: " + "imageUrl = [" + imageUrl + "]"); diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/TimeSpeedConverter.java b/core/src/main/java/de/danoeh/antennapod/core/util/TimeSpeedConverter.java index 5d44c14b8..bbfe528be 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/TimeSpeedConverter.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/TimeSpeedConverter.java @@ -10,7 +10,7 @@ public class TimeSpeedConverter { } /** Convert millisecond according to the current playback speed - * @param time: time to convert + * @param time time to convert * @return converted time (can be < 0 if time is < 0) */ public int convert(int time) { diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/syndication/HtmlToPlainText.java b/core/src/main/java/de/danoeh/antennapod/core/util/syndication/HtmlToPlainText.java index 3550f28c6..84d98a905 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/syndication/HtmlToPlainText.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/syndication/HtmlToPlainText.java @@ -57,7 +57,7 @@ public class HtmlToPlainText { * Use this method to determine if a given text has any HTML tag * * @param str String to be tested for presence of HTML content - * @return True if text contains any HTML tags
    False is no HTML tag is found + * @return True if text contains any HTML tags
    False is no HTML tag is found */ private static boolean isHtml(String str) { final String HTML_TAG_PATTERN = "<(\"[^\"]*\"|'[^']*'|[^'\">])*>"; -- cgit v1.2.3 From 8f08bd1f6da579658fba565a736a2823f55ca5d3 Mon Sep 17 00:00:00 2001 From: ByteHamster Date: Sun, 2 Feb 2020 17:47:41 +0100 Subject: Enforce method names --- .../antennapod/core/backup/OpmlBackupAgent.java | 27 ++++++---------------- 1 file changed, 7 insertions(+), 20 deletions(-) (limited to 'core/src') diff --git a/core/src/main/java/de/danoeh/antennapod/core/backup/OpmlBackupAgent.java b/core/src/main/java/de/danoeh/antennapod/core/backup/OpmlBackupAgent.java index 61e4e599b..4c11d0489 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/backup/OpmlBackupAgent.java +++ b/core/src/main/java/de/danoeh/antennapod/core/backup/OpmlBackupAgent.java @@ -27,7 +27,6 @@ import java.security.NoSuchAlgorithmException; import java.util.ArrayList; import java.util.Arrays; -import de.danoeh.antennapod.core.BuildConfig; import de.danoeh.antennapod.core.export.opml.OpmlElement; import de.danoeh.antennapod.core.export.opml.OpmlReader; import de.danoeh.antennapod.core.export.opml.OpmlWriter; @@ -45,18 +44,6 @@ public class OpmlBackupAgent extends BackupAgentHelper { addHelper(OPML_BACKUP_KEY, new OpmlBackupHelper(this)); } - private static void LOGD(String tag, String msg) { - if (BuildConfig.DEBUG && Log.isLoggable(tag, Log.DEBUG)) { - Log.d(tag, msg); - } - } - - private static void LOGD(String tag, String msg, Throwable tr) { - if (BuildConfig.DEBUG && Log.isLoggable(tag, Log.DEBUG)) { - Log.d(tag, msg, tr); - } - } - /** * Class for backing up and restoring the OPML file. */ @@ -98,7 +85,7 @@ public class OpmlBackupAgent extends BackupAgentHelper { // Compare checksum of new and old file to see if we need to perform a backup at all if (digester != null) { byte[] newChecksum = digester.digest(); - LOGD(TAG, "New checksum: " + new BigInteger(1, newChecksum).toString(16)); + Log.d(TAG, "New checksum: " + new BigInteger(1, newChecksum).toString(16)); // Get the old checksum if (oldState != null) { @@ -108,10 +95,10 @@ public class OpmlBackupAgent extends BackupAgentHelper { if (len != -1) { byte[] oldChecksum = new byte[len]; inState.read(oldChecksum); - LOGD(TAG, "Old checksum: " + new BigInteger(1, oldChecksum).toString(16)); + Log.d(TAG, "Old checksum: " + new BigInteger(1, oldChecksum).toString(16)); if (Arrays.equals(oldChecksum, newChecksum)) { - LOGD(TAG, "Checksums are the same; won't backup"); + Log.d(TAG, "Checksums are the same; won't backup"); return; } } @@ -120,7 +107,7 @@ public class OpmlBackupAgent extends BackupAgentHelper { writeNewStateDescription(newState, newChecksum); } - LOGD(TAG, "Backing up OPML"); + Log.d(TAG, "Backing up OPML"); byte[] bytes = byteStream.toByteArray(); data.writeEntityHeader(OPML_ENTITY_KEY, bytes.length); data.writeEntityData(bytes, bytes.length); @@ -138,10 +125,10 @@ public class OpmlBackupAgent extends BackupAgentHelper { @Override public void restoreEntity(BackupDataInputStream data) { - LOGD(TAG, "Backup restore"); + Log.d(TAG, "Backup restore"); if (!OPML_ENTITY_KEY.equals(data.getKey())) { - LOGD(TAG, "Unknown entity key: " + data.getKey()); + Log.d(TAG, "Unknown entity key: " + data.getKey()); return; } @@ -167,7 +154,7 @@ public class OpmlBackupAgent extends BackupAgentHelper { try { downloader.downloadFeed(mContext, feed); } catch (DownloadRequestException e) { - LOGD(TAG, "Error while restoring/downloading feed", e); + Log.d(TAG, "Error while restoring/downloading feed", e); } } } catch (XmlPullParserException e) { -- cgit v1.2.3 From b656cb91a2a9b6aa6395b648195e4eb49e07f8da Mon Sep 17 00:00:00 2001 From: ByteHamster Date: Sun, 2 Feb 2020 17:52:21 +0100 Subject: Enforce MethodParamPad --- .../de/danoeh/antennapod/core/service/playback/PlaybackService.java | 2 +- core/src/main/java/de/danoeh/antennapod/core/util/LongList.java | 4 ++-- .../java/de/danoeh/antennapod/core/service/playback/RemotePSMP.java | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'core/src') diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java index e01d1fdf2..3349b3d36 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java @@ -1325,7 +1325,7 @@ public class PlaybackService extends MediaBrowserServiceCompat { @Override public void onReceive(Context context, Intent intent) { - if (isInitialStickyBroadcast ()) { + if (isInitialStickyBroadcast()) { // Don't pause playback after we just started, just because the receiver // delivers the current headset state (instead of a change) return; diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/LongList.java b/core/src/main/java/de/danoeh/antennapod/core/util/LongList.java index fdc244517..742920702 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/LongList.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/LongList.java @@ -154,7 +154,7 @@ public final class LongList { growIfNeeded(); - System.arraycopy (values, n, values, n+1, size - n); + System.arraycopy(values, n, values, n+1, size - n); values[n] = value; size++; } @@ -211,7 +211,7 @@ public final class LongList { throw new IndexOutOfBoundsException("n < 0"); } size--; - System.arraycopy (values, index + 1, values, index, size - index); + System.arraycopy(values, index + 1, values, index, size - index); } /** diff --git a/core/src/play/java/de/danoeh/antennapod/core/service/playback/RemotePSMP.java b/core/src/play/java/de/danoeh/antennapod/core/service/playback/RemotePSMP.java index 63fc05cb8..7c84437e1 100644 --- a/core/src/play/java/de/danoeh/antennapod/core/service/playback/RemotePSMP.java +++ b/core/src/play/java/de/danoeh/antennapod/core/service/playback/RemotePSMP.java @@ -64,7 +64,7 @@ public class RemotePSMP extends PlaybackServiceMediaPlayer { remoteState = MediaStatus.PLAYER_STATE_UNKNOWN; } - public void init () { + public void init() { try { if (castMgr.isConnected() && castMgr.isRemoteMediaLoaded()) { onRemoteMediaPlayerStatusUpdated(); -- cgit v1.2.3 From 719af170a704e3172d45e4ae952228761b092285 Mon Sep 17 00:00:00 2001 From: ByteHamster Date: Sun, 2 Feb 2020 17:56:57 +0100 Subject: Enforce SeparatorWrap --- .../java/de/danoeh/antennapod/core/cast/CastManager.java | 13 +++++-------- .../core/storage/ItemEnqueuePositionCalculatorTest.java | 4 +--- 2 files changed, 6 insertions(+), 11 deletions(-) (limited to 'core/src') diff --git a/core/src/play/java/de/danoeh/antennapod/core/cast/CastManager.java b/core/src/play/java/de/danoeh/antennapod/core/cast/CastManager.java index bf9ef3f5b..5014a1fc5 100644 --- a/core/src/play/java/de/danoeh/antennapod/core/cast/CastManager.java +++ b/core/src/play/java/de/danoeh/antennapod/core/cast/CastManager.java @@ -1243,14 +1243,11 @@ public class CastManager extends BaseCastManager implements OnFailedListener { throw new NoConnectionException(); } Log.d(TAG, "remoteMediaPlayer.seek() to position " + position); - remoteMediaPlayer.seek(mApiClient, - position, - RESUME_STATE_UNCHANGED). - setResultCallback(result -> { - if (!result.getStatus().isSuccess()) { - onFailed(R.string.cast_failed_seek, result.getStatus().getStatusCode()); - } - }); + remoteMediaPlayer.seek(mApiClient, position, RESUME_STATE_UNCHANGED).setResultCallback(result -> { + if (!result.getStatus().isSuccess()) { + onFailed(R.string.cast_failed_seek, result.getStatus().getStatusCode()); + } + }); } /** diff --git a/core/src/test/java/de/danoeh/antennapod/core/storage/ItemEnqueuePositionCalculatorTest.java b/core/src/test/java/de/danoeh/antennapod/core/storage/ItemEnqueuePositionCalculatorTest.java index 17b88bdd2..275b104ea 100644 --- a/core/src/test/java/de/danoeh/antennapod/core/storage/ItemEnqueuePositionCalculatorTest.java +++ b/core/src/test/java/de/danoeh/antennapod/core/storage/ItemEnqueuePositionCalculatorTest.java @@ -226,9 +226,7 @@ public class ItemEnqueuePositionCalculatorTest { private static FeedItem setAsDownloading(int id, DownloadStateProvider stubDownloadStateProvider, boolean isDownloading) { FeedItem item = createFeedItem(id); - FeedMedia media = - new FeedMedia(item, "http://download.url.net/" + id - , 100000 + id, "audio/mp3"); + FeedMedia media = new FeedMedia(item, "http://download.url.net/" + id, 100000 + id, "audio/mp3"); media.setId(item.getId()); item.setMedia(media); return setAsDownloading(item, stubDownloadStateProvider, isDownloading); -- cgit v1.2.3 From c524d20cc900104093696c1064f46ad8e4c4bdad Mon Sep 17 00:00:00 2001 From: ByteHamster Date: Mon, 3 Feb 2020 22:43:12 +0100 Subject: Do not add timecode link if timecode equals duration --- .../danoeh/antennapod/core/util/playback/Timeline.java | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) (limited to 'core/src') diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/playback/Timeline.java b/core/src/main/java/de/danoeh/antennapod/core/util/playback/Timeline.java index 8624ec7e5..917f8e8e2 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/playback/Timeline.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/playback/Timeline.java @@ -9,6 +9,7 @@ import android.text.TextUtils; import android.util.Log; import android.util.TypedValue; +import de.danoeh.antennapod.core.feed.FeedItem; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; @@ -27,7 +28,8 @@ import de.danoeh.antennapod.core.util.ShownotesProvider; * shownotes to navigate to another position in the podcast or by highlighting certain parts of the shownotesProvider's * shownotes. *

    - * A timeline object needs a shownotesProvider from which the chapter information is retrieved and shownotes are generated. + * A timeline object needs a shownotesProvider from which the chapter information + * is retrieved and shownotes are generated. */ public class Timeline { private static final String TAG = "Timeline"; @@ -110,8 +112,6 @@ public class Timeline { */ @NonNull public String processShownotes() { - final Playable playable = (shownotesProvider instanceof Playable) ? (Playable) shownotesProvider : null; - // load shownotes String shownotes; @@ -154,7 +154,7 @@ public class Timeline { document.head().appendElement("style").attr("type", "text/css").text(styleStr); // apply timecode links - addTimecodes(document, playable); + addTimecodes(document); return document.toString(); } @@ -184,7 +184,7 @@ public class Timeline { return -1; } - private void addTimecodes(Document document, final Playable playable) { + private void addTimecodes(Document document) { Elements elementsWithTimeCodes = document.body().getElementsMatchingOwnText(TIMECODE_REGEX); Log.d(TAG, "Recognized " + elementsWithTimeCodes.size() + " timecodes"); @@ -193,7 +193,13 @@ public class Timeline { return; } - int playableDuration = playable == null ? Integer.MAX_VALUE : playable.getDuration(); + int playableDuration = Integer.MAX_VALUE; + if (shownotesProvider instanceof Playable) { + playableDuration = ((Playable) shownotesProvider).getDuration(); + } else if (shownotesProvider instanceof FeedItem && ((FeedItem) shownotesProvider).getMedia() != null) { + playableDuration = ((FeedItem) shownotesProvider).getMedia().getDuration(); + } + boolean useHourFormat = true; if (playableDuration != Integer.MAX_VALUE) { -- cgit v1.2.3 From 6a0542ca1fe23537eeeab361c702a0b60a2579db Mon Sep 17 00:00:00 2001 From: ByteHamster Date: Mon, 3 Feb 2020 23:17:04 +0100 Subject: Moved css to readable file instead of variable --- core/src/main/assets/shownotes-style.css | 37 +++++++++ .../antennapod/core/util/playback/Timeline.java | 97 +++++----------------- 2 files changed, 60 insertions(+), 74 deletions(-) create mode 100644 core/src/main/assets/shownotes-style.css (limited to 'core/src') diff --git a/core/src/main/assets/shownotes-style.css b/core/src/main/assets/shownotes-style.css new file mode 100644 index 000000000..d0c8564aa --- /dev/null +++ b/core/src/main/assets/shownotes-style.css @@ -0,0 +1,37 @@ +@font-face { + font-family: 'Roboto-Light'; + src: url('file:///android_asset/Roboto-Light.ttf'); +} +* { + color: %s; + font-family: roboto-Light; + font-size: 13pt; + overflow-wrap: break-word; +} +a { + font-style: normal; + text-decoration: none; + font-weight: normal; + color: #00A8DF; +} +a.timecode { + color: #669900; +} +img, iframe { + display: block; + margin: 10 auto; + max-width: 100%%; + height: auto; +} +body { + margin: %dpx %dpx %dpx %dpx; +} +p#apNoShownotes { + position: fixed; + top: 50%%; + left: 50%%; + transform: translate(-50%%, -50%%); + text-align: center; + -webkit-text-size-adjust: none; + font-size: 80%%; +} diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/playback/Timeline.java b/core/src/main/java/de/danoeh/antennapod/core/util/playback/Timeline.java index 917f8e8e2..0fd658853 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/playback/Timeline.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/playback/Timeline.java @@ -10,11 +10,14 @@ import android.util.Log; import android.util.TypedValue; import de.danoeh.antennapod.core.feed.FeedItem; +import org.apache.commons.io.IOUtils; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; import org.jsoup.select.Elements; +import java.io.IOException; +import java.io.InputStream; import java.util.Locale; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -34,43 +37,14 @@ import de.danoeh.antennapod.core.util.ShownotesProvider; public class Timeline { private static final String TAG = "Timeline"; - private static final String WEBVIEW_STYLE = - "@font-face {" - + "font-family: 'Roboto-Light';" - + "src: url('file:///android_asset/Roboto-Light.ttf');" - + "}" - + "* {" - + "color: %s;" - + "font-family: roboto-Light;" - + "font-size: 13pt;" - + "overflow-wrap: break-word;" - + "}" - + "a {" - + "font-style: normal;" - + "text-decoration: none;" - + "font-weight: normal;" - + "color: #00A8DF;" - + "}" - + "a.timecode {" - + "color: #669900;" - + "}" - + "img, iframe {" - + "display: block;" - + "margin: 10 auto;" - + "max-width: %s;" - + "height: auto;" - + "}" - + "body {" - + "margin: %dpx %dpx %dpx %dpx;" - + "}"; - - - private ShownotesProvider shownotesProvider; + private static final Pattern TIMECODE_LINK_REGEX = Pattern.compile("antennapod://timecode/((\\d+))"); + private static final String TIMECODE_LINK = "%s"; + private static final Pattern TIMECODE_REGEX = Pattern.compile("\\b((\\d+):)?(\\d+):(\\d{2})\\b"); + private static final Pattern LINE_BREAK_REGEX = Pattern.compile("
    "); + private final ShownotesProvider shownotesProvider; private final String noShownotesLabel; - private final String colorPrimaryString; - private final String colorSecondaryString; - private final int pageMargin; + private final String webviewStyle; public Timeline(Context context, ShownotesProvider shownotesProvider) { if (shownotesProvider == null) { @@ -82,26 +56,21 @@ public class Timeline { TypedArray res = context.getTheme().obtainStyledAttributes(new int[]{android.R.attr.textColorPrimary}); @ColorInt int col = res.getColor(0, 0); - colorPrimaryString = "rgba(" + Color.red(col) + "," + Color.green(col) + "," + - Color.blue(col) + "," + (Color.alpha(col) / 255.0) + ")"; + final String colorPrimary = "rgba(" + Color.red(col) + "," + Color.green(col) + "," + + Color.blue(col) + "," + (Color.alpha(col) / 255.0) + ")"; res.recycle(); - res = context.getTheme().obtainStyledAttributes(new int[]{android.R.attr.textColorSecondary}); - col = res.getColor(0, 0); - colorSecondaryString = "rgba(" + Color.red(col) + "," + Color.green(col) + "," + - Color.blue(col) + "," + (Color.alpha(col) / 255.0) + ")"; - res.recycle(); - - pageMargin = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 8, - context.getResources().getDisplayMetrics() - ); + final int margin = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 8, + context.getResources().getDisplayMetrics()); + String styleString = ""; + try { + InputStream templateStream = context.getAssets().open("shownotes-style.css"); + styleString = IOUtils.toString(templateStream, "UTF-8"); + } catch (IOException e) { + e.printStackTrace(); + } + webviewStyle = String.format(Locale.getDefault(), styleString, colorPrimary, margin, margin, margin, margin); } - private static final Pattern TIMECODE_LINK_REGEX = Pattern.compile("antennapod://timecode/((\\d+))"); - private static final String TIMECODE_LINK = "%s"; - private static final Pattern TIMECODE_REGEX = Pattern.compile("\\b((\\d+):)?(\\d+):(\\d{2})\\b"); - private static final Pattern LINE_BREAK_REGEX = Pattern.compile("
    "); - - /** * Applies an app-specific CSS stylesheet and adds timecode links (optional). *

    @@ -112,8 +81,6 @@ public class Timeline { */ @NonNull public String processShownotes() { - // load shownotes - String shownotes; try { shownotes = shownotesProvider.loadShownotes().call(); @@ -124,21 +91,7 @@ public class Timeline { if (TextUtils.isEmpty(shownotes)) { Log.d(TAG, "shownotesProvider contained no shownotes. Returning 'no shownotes' message"); - shownotes = "" + - "" + - "" + - "" + - "" + - "

    " + noShownotesLabel + "

    " + - "" + - ""; - Log.d(TAG, "shownotes: " + shownotes); - return shownotes; + shownotes = "

    " + noShownotesLabel + "

    "; } // replace ASCII line breaks with HTML ones if shownotes don't contain HTML line breaks already @@ -147,11 +100,7 @@ public class Timeline { } Document document = Jsoup.parse(shownotes); - - // apply style - String styleStr = String.format(Locale.getDefault(), WEBVIEW_STYLE, colorPrimaryString, "100%", - pageMargin, pageMargin, pageMargin, pageMargin); - document.head().appendElement("style").attr("type", "text/css").text(styleStr); + document.head().appendElement("style").attr("type", "text/css").text(webviewStyle); // apply timecode links addTimecodes(document); -- cgit v1.2.3 From cae04b5b138f8dd232c19062ec115c81ed818ae2 Mon Sep 17 00:00:00 2001 From: ByteHamster Date: Tue, 4 Feb 2020 14:53:49 +0100 Subject: Extract queue item holder to new class First step to use a single item holder in the future --- .../service/download/handler/PostDownloaderTask.java | 2 ++ .../antennapod/core/storage/DownloadRequester.java | 20 ++++++++++++++++++++ 2 files changed, 22 insertions(+) (limited to 'core/src') diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/download/handler/PostDownloaderTask.java b/core/src/main/java/de/danoeh/antennapod/core/service/download/handler/PostDownloaderTask.java index 5d2c48679..7c998146d 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/download/handler/PostDownloaderTask.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/download/handler/PostDownloaderTask.java @@ -2,6 +2,7 @@ package de.danoeh.antennapod.core.service.download.handler; import de.danoeh.antennapod.core.event.DownloadEvent; import de.danoeh.antennapod.core.service.download.Downloader; +import de.danoeh.antennapod.core.storage.DownloadRequester; import org.greenrobot.eventbus.EventBus; import java.util.ArrayList; @@ -23,6 +24,7 @@ public class PostDownloaderTask implements Runnable { runningDownloads.add(downloader); } } + DownloadRequester.getInstance().updateProgress(downloads); List list = Collections.unmodifiableList(runningDownloads); EventBus.getDefault().postSticky(DownloadEvent.refresh(list)); } diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DownloadRequester.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DownloadRequester.java index 3d4ee443b..8bd9afe38 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/DownloadRequester.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DownloadRequester.java @@ -12,6 +12,7 @@ import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; import androidx.core.content.ContextCompat; +import de.danoeh.antennapod.core.service.download.Downloader; import org.apache.commons.io.FilenameUtils; import java.io.File; @@ -343,6 +344,16 @@ public class DownloadRequester implements DownloadStateProvider { return item.getDownload_url() != null && downloads.containsKey(item.getDownload_url()); } + /** + * Get the downloader for this item. + */ + public synchronized DownloadRequest getRequestFor(FeedFile item) { + if (isDownloadingFile(item)) { + return downloads.get(item.getDownload_url()); + } + return null; + } + /** * Checks if feedfile with the given download url is in the downloads list */ @@ -428,4 +439,13 @@ public class DownloadRequester implements DownloadStateProvider { } return filename; } + + public void updateProgress(List newDownloads) { + for (Downloader downloader : newDownloads) { + DownloadRequest request = downloader.getDownloadRequest(); + if (downloads.containsKey(request.getSource())) { + downloads.put(request.getSource(), request); + } + } + } } -- cgit v1.2.3 From 12288d01a5eadbd5ed015fd59265c9cdef34a889 Mon Sep 17 00:00:00 2001 From: Keunes <11229646+keunes@users.noreply.github.com> Date: Tue, 4 Feb 2020 22:18:04 +0100 Subject: Update strings.xml With the removal of the subheading (#3811), it isn't clear anymore when AP will vibrate. This will clarify the function/checkbox. --- core/src/main/res/values/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'core/src') diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index d87afcd09..bd52dfa1e 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -579,7 +579,7 @@ Sleep timer Invalid input, time has to be an integer Shake to reset - Vibrate + Vibrate shortly before end seconds minutes hours -- cgit v1.2.3 From cb702a2de6b4975c307ac711461890a7fddb0fc9 Mon Sep 17 00:00:00 2001 From: ByteHamster Date: Tue, 4 Feb 2020 22:46:13 +0100 Subject: Cleaned up layout --- core/src/main/res/values-large/dimens.xml | 2 -- core/src/main/res/values/dimens.xml | 4 ++-- 2 files changed, 2 insertions(+), 4 deletions(-) (limited to 'core/src') diff --git a/core/src/main/res/values-large/dimens.xml b/core/src/main/res/values-large/dimens.xml index 2d107eef0..27e269099 100644 --- a/core/src/main/res/values-large/dimens.xml +++ b/core/src/main/res/values-large/dimens.xml @@ -2,6 +2,4 @@ 170dp - 64dp - 64dp \ No newline at end of file diff --git a/core/src/main/res/values/dimens.xml b/core/src/main/res/values/dimens.xml index 02c398b62..d9d1bc6fe 100644 --- a/core/src/main/res/values/dimens.xml +++ b/core/src/main/res/values/dimens.xml @@ -10,8 +10,8 @@ 16sp 18sp 22sp - 64dp - 64dp + 56dp + 56dp 64dp 100dp 132dp -- cgit v1.2.3 From 50dd85276ca3507cfe4d9ec421aa0c406623ac01 Mon Sep 17 00:00:00 2001 From: ByteHamster Date: Tue, 4 Feb 2020 23:50:38 +0100 Subject: Fixed search returning duplicates --- .../java/de/danoeh/antennapod/core/storage/FeedSearcher.java | 8 +------- .../java/de/danoeh/antennapod/core/storage/PodDBAdapter.java | 9 ++------- .../java/de/danoeh/antennapod/core/storage/SearchLocation.java | 4 +--- 3 files changed, 4 insertions(+), 17 deletions(-) (limited to 'core/src') diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/FeedSearcher.java b/core/src/main/java/de/danoeh/antennapod/core/storage/FeedSearcher.java index 1d9e33d0e..6d6359a42 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/FeedSearcher.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/FeedSearcher.java @@ -47,16 +47,10 @@ public class FeedSearcher { SearchLocation location; if (safeContains(item.getTitle(), query)) { location = SearchLocation.TITLE; - } else if (safeContains(item.getContentEncoded(), query)) { - location = SearchLocation.SHOWNOTES; - } else if (safeContains(item.getDescription(), query)) { - location = SearchLocation.SHOWNOTES; } else if (safeContains(item.getChapters(), query)) { location = SearchLocation.CHAPTERS; - } else if (safeContains(item.getFeed().getAuthor(), query)) { - location = SearchLocation.AUTHORS; } else { - location = SearchLocation.FEED; + location = SearchLocation.SHOWNOTES; } result.add(new SearchResult(item, location)); } diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java b/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java index 17b79a3da..48af7def0 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java @@ -1273,20 +1273,15 @@ public class PodDBAdapter { queryFeedId = "1 = 1"; } - String query = "SELECT " + SEL_FI_SMALL_STR + " FROM " + TABLE_NAME_FEED_ITEMS + String query = "SELECT DISTINCT " + SEL_FI_SMALL_STR + " FROM " + TABLE_NAME_FEED_ITEMS + " LEFT JOIN " + TABLE_NAME_SIMPLECHAPTERS + " ON " + TABLE_NAME_SIMPLECHAPTERS + "." + KEY_FEEDITEM + "=" + TABLE_NAME_FEED_ITEMS + "." + KEY_ID - + " LEFT JOIN " + TABLE_NAME_FEEDS - + " ON " + TABLE_NAME_FEED_ITEMS + "." + KEY_FEED - + "=" + TABLE_NAME_FEEDS + "." + KEY_ID + " WHERE " + queryFeedId + " AND (" + TABLE_NAME_FEED_ITEMS + "." + KEY_DESCRIPTION + " LIKE '%" + preparedQuery + "%' OR " + TABLE_NAME_FEED_ITEMS + "." + KEY_CONTENT_ENCODED + " LIKE '%" + preparedQuery + "%' OR " + TABLE_NAME_FEED_ITEMS + "." + KEY_TITLE + " LIKE '%" + preparedQuery + "%' OR " - + TABLE_NAME_SIMPLECHAPTERS + "." + KEY_TITLE + " LIKE '%" + preparedQuery + "%' OR " - + TABLE_NAME_FEEDS + "." + KEY_AUTHOR + " LIKE '%" + preparedQuery + "%' OR " - + TABLE_NAME_FEEDS + "." + KEY_FEED_IDENTIFIER + " LIKE '%" + preparedQuery + "%'" + + TABLE_NAME_SIMPLECHAPTERS + "." + KEY_TITLE + " LIKE '%" + preparedQuery + "%'" + ") ORDER BY " + KEY_PUBDATE + " DESC " + "LIMIT 500"; return db.rawQuery(query, null); diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/SearchLocation.java b/core/src/main/java/de/danoeh/antennapod/core/storage/SearchLocation.java index fabe85b2c..078797bda 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/SearchLocation.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/SearchLocation.java @@ -6,9 +6,7 @@ import de.danoeh.antennapod.core.R; public enum SearchLocation { TITLE(R.string.found_in_title_label), CHAPTERS(R.string.found_in_chapters_label), - SHOWNOTES(R.string.found_in_shownotes_label), - AUTHORS(R.string.found_in_authors_label), - FEED(R.string.found_in_feeds_label); + SHOWNOTES(R.string.found_in_shownotes_label); private int description; SearchLocation(@StringRes int description) { -- cgit v1.2.3 From 8d23571bbaf45062af5bd253281132935a68c0a1 Mon Sep 17 00:00:00 2001 From: ByteHamster Date: Wed, 5 Feb 2020 00:06:32 +0100 Subject: Search for feeds separately --- .../de/danoeh/antennapod/core/storage/DBTasks.java | 17 ++++++++++++++ .../antennapod/core/storage/FeedSearcher.java | 27 ++++++++++++---------- .../antennapod/core/storage/PodDBAdapter.java | 22 +++++++++++++++++- 3 files changed, 53 insertions(+), 13 deletions(-) (limited to 'core/src') diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java index 91f656bf1..8ebe18dc0 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java @@ -553,6 +553,23 @@ public final class DBTasks { }); } + public static FutureTask> searchFeeds(final Context context, final String query) { + return new FutureTask<>(new QueryTask>(context) { + @Override + public void execute(PodDBAdapter adapter) { + Cursor cursor = adapter.searchFeeds(query); + List items = new ArrayList<>(); + if (cursor.moveToFirst()) { + do { + items.add(Feed.fromCursor(cursor)); + } while (cursor.moveToNext()); + } + setResult(items); + cursor.close(); + } + }); + } + /** * A runnable which should be used for database queries. The onCompletion * method is executed on the database executor to handle Cursors correctly. diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/FeedSearcher.java b/core/src/main/java/de/danoeh/antennapod/core/storage/FeedSearcher.java index 6d6359a42..100d0e910 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/FeedSearcher.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/FeedSearcher.java @@ -2,21 +2,16 @@ package de.danoeh.antennapod.core.storage; import android.content.Context; import androidx.annotation.NonNull; - import de.danoeh.antennapod.core.feed.Chapter; +import de.danoeh.antennapod.core.feed.Feed; +import de.danoeh.antennapod.core.feed.FeedItem; +import de.danoeh.antennapod.core.feed.SearchResult; + import java.util.ArrayList; -import java.util.Collections; -import java.util.HashSet; import java.util.List; -import java.util.Set; import java.util.concurrent.ExecutionException; import java.util.concurrent.FutureTask; -import de.danoeh.antennapod.core.R; -import de.danoeh.antennapod.core.feed.FeedItem; -import de.danoeh.antennapod.core.feed.SearchResult; -import de.danoeh.antennapod.core.util.comparator.InReverseChronologicalOrder; - /** * Performs search on Feeds and FeedItems. */ @@ -40,9 +35,17 @@ public class FeedSearcher { public static List performSearch(final Context context, final String query, final long selectedFeed) { final List result = new ArrayList<>(); try { - FutureTask> searchTask = DBTasks.searchFeedItems(context, selectedFeed, query); - searchTask.run(); - final List items = searchTask.get(); + FutureTask> itemSearchTask = DBTasks.searchFeedItems(context, selectedFeed, query); + FutureTask> feedSearchTask = DBTasks.searchFeeds(context, query); + itemSearchTask.run(); + feedSearchTask.run(); + + final List feeds = feedSearchTask.get(); + for (Feed item : feeds) { + result.add(new SearchResult(item, null)); + } + + final List items = itemSearchTask.get(); for (FeedItem item : items) { SearchLocation location; if (safeContains(item.getTitle(), query)) { diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java b/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java index 48af7def0..749597840 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java @@ -284,10 +284,13 @@ public class PodDBAdapter { * Contains FEEDITEM_SEL_FI_SMALL as comma-separated list. Useful for raw queries. */ private static final String SEL_FI_SMALL_STR; + private static final String FEED_SEL_STD_STR; static { String selFiSmall = Arrays.toString(FEEDITEM_SEL_FI_SMALL); SEL_FI_SMALL_STR = selFiSmall.substring(1, selFiSmall.length() - 1); + String selFeedSmall = Arrays.toString(FEED_SEL_STD); + FEED_SEL_STD_STR = selFeedSmall.substring(1, selFeedSmall.length() - 1); } /** @@ -1283,7 +1286,24 @@ public class PodDBAdapter { + TABLE_NAME_FEED_ITEMS + "." + KEY_TITLE + " LIKE '%" + preparedQuery + "%' OR " + TABLE_NAME_SIMPLECHAPTERS + "." + KEY_TITLE + " LIKE '%" + preparedQuery + "%'" + ") ORDER BY " + KEY_PUBDATE + " DESC " - + "LIMIT 500"; + + "LIMIT 300"; + return db.rawQuery(query, null); + } + + /** + * Searches for the given query in various values of all feeds. + * + * @return A cursor with all search results in SEL_FI_EXTRA selection. + */ + public Cursor searchFeeds(String searchQuery) { + String preparedQuery = prepareSearchQuery(searchQuery); + String query = "SELECT " + FEED_SEL_STD_STR + " FROM " + TABLE_NAME_FEEDS + " WHERE " + + KEY_TITLE + " LIKE '%" + preparedQuery + "%' OR " + + KEY_CUSTOM_TITLE + " LIKE '%" + preparedQuery + "%' OR " + + KEY_AUTHOR + " LIKE '%" + preparedQuery + "%' OR " + + KEY_DESCRIPTION + " LIKE '%" + preparedQuery + "%' " + + "ORDER BY " + KEY_TITLE + " ASC " + + "LIMIT 300"; return db.rawQuery(query, null); } -- cgit v1.2.3 From 75e0d2d7e1929a617ea21e235d96e0448eea091b Mon Sep 17 00:00:00 2001 From: ByteHamster Date: Wed, 5 Feb 2020 00:29:07 +0100 Subject: Verify database version before import --- .../antennapod/core/storage/DatabaseExporter.java | 32 ++++++++++------------ .../antennapod/core/storage/PodDBAdapter.java | 12 +++----- core/src/main/res/values/strings.xml | 3 +- 3 files changed, 20 insertions(+), 27 deletions(-) (limited to 'core/src') diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DatabaseExporter.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DatabaseExporter.java index af3d1206c..234c01b20 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/DatabaseExporter.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DatabaseExporter.java @@ -1,6 +1,8 @@ package de.danoeh.antennapod.core.storage; import android.content.Context; +import android.database.sqlite.SQLiteDatabase; +import android.database.sqlite.SQLiteException; import android.net.Uri; import android.os.ParcelFileDescriptor; import android.util.Log; @@ -14,21 +16,10 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.nio.channels.FileChannel; -import java.util.Arrays; public class DatabaseExporter { private static final String TAG = "DatabaseExporter"; - private static final byte[] SQLITE3_MAGIC = "SQLite format 3\0".getBytes(); - - public static boolean validateDB(Uri inputUri, Context context) throws IOException { - try (InputStream inputStream = context.getContentResolver().openInputStream(inputUri)) { - byte[] magicBuf = new byte[SQLITE3_MAGIC.length]; - if (inputStream.read(magicBuf) == magicBuf.length) { - return Arrays.equals(SQLITE3_MAGIC, magicBuf); - } - } - return false; - } + private static final String TEMP_DB_NAME = PodDBAdapter.DATABASE_NAME + "_tmp"; public static void exportToDocument(Uri uri, Context context) throws IOException { ParcelFileDescriptor pfd = null; @@ -78,14 +69,21 @@ public class DatabaseExporter { public static void importBackup(Uri inputUri, Context context) throws IOException { InputStream inputStream = null; try { - if (!validateDB(inputUri, context)) { - throw new IOException(context.getString(R.string.import_bad_file)); + File tempDB = context.getDatabasePath(TEMP_DB_NAME); + inputStream = context.getContentResolver().openInputStream(inputUri); + FileUtils.copyInputStreamToFile(inputStream, tempDB); + + SQLiteDatabase db = SQLiteDatabase.openDatabase(tempDB.getAbsolutePath(), + null, SQLiteDatabase.OPEN_READONLY); + if (db.getVersion() > PodDBAdapter.VERSION) { + throw new IOException(context.getString(R.string.import_no_downgrade)); } + db.close(); File currentDB = context.getDatabasePath(PodDBAdapter.DATABASE_NAME); - inputStream = context.getContentResolver().openInputStream(inputUri); - FileUtils.copyInputStreamToFile(inputStream, currentDB); - } catch (IOException e) { + currentDB.delete(); + FileUtils.moveFile(tempDB, currentDB); + } catch (IOException | SQLiteException e) { Log.e(TAG, Log.getStackTraceString(e)); throw e; } finally { diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java b/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java index 17b79a3da..ce55591ae 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java @@ -48,6 +48,7 @@ public class PodDBAdapter { private static final String TAG = "PodDBAdapter"; public static final String DATABASE_NAME = "Antennapod.db"; + public static final int VERSION = 1090000; /** * Maximum number of arguments for IN-operator. @@ -1336,8 +1337,6 @@ public class PodDBAdapter { * Helper class for opening the Antennapod database. */ private static class PodDBHelper extends SQLiteOpenHelper { - private static final int VERSION = 1090000; - /** * Constructor. * @@ -1345,8 +1344,7 @@ public class PodDBAdapter { * @param name Name of the database * @param factory to use for creating cursor objects */ - public PodDBHelper(final Context context, final String name, - final CursorFactory factory) { + public PodDBHelper(final Context context, final String name, final CursorFactory factory) { super(context, name, factory, VERSION, new PodDbErrorHandler()); } @@ -1369,10 +1367,8 @@ public class PodDBAdapter { } @Override - public void onUpgrade(final SQLiteDatabase db, final int oldVersion, - final int newVersion) { - Log.w("DBAdapter", "Upgrading from version " + oldVersion + " to " - + newVersion + "."); + public void onUpgrade(final SQLiteDatabase db, final int oldVersion, final int newVersion) { + Log.w("DBAdapter", "Upgrading from version " + oldVersion + " to " + newVersion + "."); DBUpgrader.upgrade(db, oldVersion, newVersion); } } diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index d87afcd09..0b9100075 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -572,6 +572,7 @@ Access to external storage is required to read the OPML file Select file to import Import successful.\n\nPlease press OK to restart AntennaPod + This database was exported with a newer version of AntennaPod. Your current installation does not yet know how to handle this file. Set sleep timer @@ -768,7 +769,6 @@ Failed to start the playback of media Failed to stop the playback of media Failed to pause the playback of media - Failed to set the volume No connection to the cast device is present Connection to the cast device has been lost. Application is trying to re-establish the connection, if possible. Please wait for a few seconds and try again. @@ -786,7 +786,6 @@ Allows to control playback. This is the main notification you see while playing a podcast. Errors Shown if something went wrong, for example if download or gpodder sync fails. - Invalid/corrupt file Widget settings -- cgit v1.2.3 From f4cfe7bdcafad57ec2c6f92d8fe93e8b45474049 Mon Sep 17 00:00:00 2001 From: ByteHamster Date: Wed, 5 Feb 2020 09:51:29 +0100 Subject: Do not search in chapters This speeds up searching a LOT. I hope that most podcasts use good descriptions and we do not need to search for chapters. Podcasts outside of Germany use chapters only very infrequently. --- .../danoeh/antennapod/core/feed/SearchResult.java | 22 ------------ .../core/service/playback/PlaybackService.java | 23 ++++++------ .../antennapod/core/storage/FeedSearcher.java | 42 +++------------------- .../antennapod/core/storage/PodDBAdapter.java | 12 +++---- .../antennapod/core/storage/SearchLocation.java | 19 ---------- .../comparator/InReverseChronologicalOrder.java | 21 ----------- 6 files changed, 21 insertions(+), 118 deletions(-) delete mode 100644 core/src/main/java/de/danoeh/antennapod/core/feed/SearchResult.java delete mode 100644 core/src/main/java/de/danoeh/antennapod/core/storage/SearchLocation.java delete mode 100644 core/src/main/java/de/danoeh/antennapod/core/util/comparator/InReverseChronologicalOrder.java (limited to 'core/src') diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/SearchResult.java b/core/src/main/java/de/danoeh/antennapod/core/feed/SearchResult.java deleted file mode 100644 index 062a6abac..000000000 --- a/core/src/main/java/de/danoeh/antennapod/core/feed/SearchResult.java +++ /dev/null @@ -1,22 +0,0 @@ -package de.danoeh.antennapod.core.feed; - -import de.danoeh.antennapod.core.storage.SearchLocation; - -public class SearchResult { - private final FeedComponent component; - private SearchLocation location; - - public SearchResult(FeedComponent component, SearchLocation location) { - super(); - this.component = component; - this.location = location; - } - - public FeedComponent getComponent() { - return component; - } - - public SearchLocation getLocation() { - return location; - } -} diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java index 37deb6dc0..01e84d732 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java @@ -54,10 +54,10 @@ import de.danoeh.antennapod.core.event.settings.SpeedPresetChangedEvent; import de.danoeh.antennapod.core.event.settings.VolumeAdaptionChangedEvent; import de.danoeh.antennapod.core.feed.Chapter; import de.danoeh.antennapod.core.feed.Feed; +import de.danoeh.antennapod.core.feed.FeedComponent; import de.danoeh.antennapod.core.feed.FeedItem; import de.danoeh.antennapod.core.feed.FeedMedia; import de.danoeh.antennapod.core.feed.MediaType; -import de.danoeh.antennapod.core.feed.SearchResult; import de.danoeh.antennapod.core.glide.ApGlideSettings; import de.danoeh.antennapod.core.preferences.PlaybackPreferences; import de.danoeh.antennapod.core.preferences.SleepTimerPreferences; @@ -1634,16 +1634,17 @@ public class PlaybackService extends MediaBrowserServiceCompat { public void onPlayFromSearch(String query, Bundle extras) { Log.d(TAG, "onPlayFromSearch query=" + query + " extras=" + extras.toString()); - List results = FeedSearcher.performSearch(getBaseContext(), query, 0); - for (SearchResult result : results) { - try { - FeedMedia p = ((FeedItem) (result.getComponent())).getMedia(); - mediaPlayer.playMediaObject(p, !p.localFileAvailable(), true, true); - return; - } catch (Exception e) { - Log.d(TAG, e.getMessage()); - e.printStackTrace(); - continue; + List results = FeedSearcher.performSearch(getBaseContext(), query, 0); + for (FeedComponent result : results) { + if (result instanceof FeedItem) { + try { + FeedMedia media = ((FeedItem) result).getMedia(); + mediaPlayer.playMediaObject(media, !media.localFileAvailable(), true, true); + return; + } catch (Exception e) { + Log.d(TAG, e.getMessage()); + e.printStackTrace(); + } } } onPlay(); diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/FeedSearcher.java b/core/src/main/java/de/danoeh/antennapod/core/storage/FeedSearcher.java index 100d0e910..bbe8b26f1 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/FeedSearcher.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/FeedSearcher.java @@ -2,10 +2,9 @@ package de.danoeh.antennapod.core.storage; import android.content.Context; import androidx.annotation.NonNull; -import de.danoeh.antennapod.core.feed.Chapter; import de.danoeh.antennapod.core.feed.Feed; +import de.danoeh.antennapod.core.feed.FeedComponent; import de.danoeh.antennapod.core.feed.FeedItem; -import de.danoeh.antennapod.core.feed.SearchResult; import java.util.ArrayList; import java.util.List; @@ -32,50 +31,19 @@ public class FeedSearcher { * @return list of episodes containing the query */ @NonNull - public static List performSearch(final Context context, final String query, final long selectedFeed) { - final List result = new ArrayList<>(); + public static List performSearch(final Context context, final String query, final long selectedFeed) { + final List result = new ArrayList<>(); try { FutureTask> itemSearchTask = DBTasks.searchFeedItems(context, selectedFeed, query); FutureTask> feedSearchTask = DBTasks.searchFeeds(context, query); itemSearchTask.run(); feedSearchTask.run(); - final List feeds = feedSearchTask.get(); - for (Feed item : feeds) { - result.add(new SearchResult(item, null)); - } - - final List items = itemSearchTask.get(); - for (FeedItem item : items) { - SearchLocation location; - if (safeContains(item.getTitle(), query)) { - location = SearchLocation.TITLE; - } else if (safeContains(item.getChapters(), query)) { - location = SearchLocation.CHAPTERS; - } else { - location = SearchLocation.SHOWNOTES; - } - result.add(new SearchResult(item, location)); - } + result.addAll(feedSearchTask.get()); + result.addAll(itemSearchTask.get()); } catch (InterruptedException | ExecutionException e) { e.printStackTrace(); } return result; } - - private static boolean safeContains(String haystack, String needle) { - return haystack != null && haystack.contains(needle); - } - - private static boolean safeContains(List haystack, String needle) { - if (haystack == null) { - return false; - } - for (Chapter chapter : haystack) { - if (safeContains(chapter.getTitle(), needle)) { - return true; - } - } - return false; - } } diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java b/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java index 749597840..10daebedc 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java @@ -1276,15 +1276,11 @@ public class PodDBAdapter { queryFeedId = "1 = 1"; } - String query = "SELECT DISTINCT " + SEL_FI_SMALL_STR + " FROM " + TABLE_NAME_FEED_ITEMS - + " LEFT JOIN " + TABLE_NAME_SIMPLECHAPTERS - + " ON " + TABLE_NAME_SIMPLECHAPTERS + "." + KEY_FEEDITEM - + "=" + TABLE_NAME_FEED_ITEMS + "." + KEY_ID + String query = "SELECT " + SEL_FI_SMALL_STR + " FROM " + TABLE_NAME_FEED_ITEMS + " WHERE " + queryFeedId + " AND (" - + TABLE_NAME_FEED_ITEMS + "." + KEY_DESCRIPTION + " LIKE '%" + preparedQuery + "%' OR " - + TABLE_NAME_FEED_ITEMS + "." + KEY_CONTENT_ENCODED + " LIKE '%" + preparedQuery + "%' OR " - + TABLE_NAME_FEED_ITEMS + "." + KEY_TITLE + " LIKE '%" + preparedQuery + "%' OR " - + TABLE_NAME_SIMPLECHAPTERS + "." + KEY_TITLE + " LIKE '%" + preparedQuery + "%'" + + KEY_DESCRIPTION + " LIKE '%" + preparedQuery + "%' OR " + + KEY_CONTENT_ENCODED + " LIKE '%" + preparedQuery + "%' OR " + + KEY_TITLE + " LIKE '%" + preparedQuery + "%'" + ") ORDER BY " + KEY_PUBDATE + " DESC " + "LIMIT 300"; return db.rawQuery(query, null); diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/SearchLocation.java b/core/src/main/java/de/danoeh/antennapod/core/storage/SearchLocation.java deleted file mode 100644 index 078797bda..000000000 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/SearchLocation.java +++ /dev/null @@ -1,19 +0,0 @@ -package de.danoeh.antennapod.core.storage; - -import androidx.annotation.StringRes; -import de.danoeh.antennapod.core.R; - -public enum SearchLocation { - TITLE(R.string.found_in_title_label), - CHAPTERS(R.string.found_in_chapters_label), - SHOWNOTES(R.string.found_in_shownotes_label); - - private int description; - SearchLocation(@StringRes int description) { - this.description = description; - } - - public @StringRes int getDescription() { - return description; - } -} diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/comparator/InReverseChronologicalOrder.java b/core/src/main/java/de/danoeh/antennapod/core/util/comparator/InReverseChronologicalOrder.java deleted file mode 100644 index 80246af8f..000000000 --- a/core/src/main/java/de/danoeh/antennapod/core/util/comparator/InReverseChronologicalOrder.java +++ /dev/null @@ -1,21 +0,0 @@ -package de.danoeh.antennapod.core.util.comparator; - -import java.util.Comparator; - -import de.danoeh.antennapod.core.feed.FeedItem; -import de.danoeh.antennapod.core.feed.SearchResult; - -public class InReverseChronologicalOrder implements Comparator { - /** - * Compare items and sort it on chronological order. - */ - @Override - public int compare(SearchResult o1, SearchResult o2) { - if ((o1.getComponent() instanceof FeedItem) && (o2.getComponent() instanceof FeedItem)) { - FeedItem item1 = (FeedItem) o1.getComponent(); - FeedItem item2 = (FeedItem) o2.getComponent(); - return item2.getPubDate().compareTo(item1.getPubDate()); - } - return 0; - } -} -- cgit v1.2.3 From 3be4f80a5cf466f92eb3844d556ad4ea784b5f06 Mon Sep 17 00:00:00 2001 From: ByteHamster Date: Wed, 5 Feb 2020 09:55:55 +0100 Subject: Removed search strings --- core/src/main/res/values/strings.xml | 6 ------ 1 file changed, 6 deletions(-) (limited to 'core/src') diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index bd52dfa1e..e436285e1 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -536,14 +536,8 @@ AntennaPod uses other great software - Search for episodes - Found in show notes - Found in chapters - Found in author(s) - Found in podcast No results were found Search - Found in title No results were found for \"%1$s\" -- cgit v1.2.3 From f3cbaee61b2fbffdc76c782cb04457c17dc5d7d7 Mon Sep 17 00:00:00 2001 From: ByteHamster Date: Wed, 5 Feb 2020 10:07:01 +0100 Subject: Replaced eye icon with video cam --- .../main/res/drawable-hdpi/ic_hearing_grey600_18dp.png | Bin 478 -> 0 bytes core/src/main/res/drawable-hdpi/ic_hearing_white_18dp.png | Bin 449 -> 0 bytes .../res/drawable-hdpi/ic_remove_red_eye_grey600_18dp.png | Bin 380 -> 0 bytes .../res/drawable-hdpi/ic_remove_red_eye_white_18dp.png | Bin 358 -> 0 bytes .../main/res/drawable-mdpi/ic_hearing_grey600_18dp.png | Bin 324 -> 0 bytes core/src/main/res/drawable-mdpi/ic_hearing_white_18dp.png | Bin 301 -> 0 bytes .../res/drawable-mdpi/ic_remove_red_eye_grey600_18dp.png | Bin 265 -> 0 bytes .../res/drawable-mdpi/ic_remove_red_eye_white_18dp.png | Bin 259 -> 0 bytes .../main/res/drawable-xhdpi/ic_hearing_grey600_18dp.png | Bin 621 -> 0 bytes .../src/main/res/drawable-xhdpi/ic_hearing_white_18dp.png | Bin 588 -> 0 bytes .../res/drawable-xhdpi/ic_remove_red_eye_grey600_18dp.png | Bin 492 -> 0 bytes .../res/drawable-xhdpi/ic_remove_red_eye_white_18dp.png | Bin 472 -> 0 bytes .../main/res/drawable-xxhdpi/ic_hearing_grey600_18dp.png | Bin 885 -> 0 bytes .../main/res/drawable-xxhdpi/ic_hearing_white_18dp.png | Bin 840 -> 0 bytes .../drawable-xxhdpi/ic_remove_red_eye_grey600_18dp.png | Bin 697 -> 0 bytes .../res/drawable-xxhdpi/ic_remove_red_eye_white_18dp.png | Bin 669 -> 0 bytes core/src/main/res/drawable/ic_videocam_grey600_24dp.xml | 8 ++++++++ core/src/main/res/drawable/ic_videocam_white_24dp.xml | 8 ++++++++ core/src/main/res/values/attrs.xml | 1 - core/src/main/res/values/styles.xml | 6 ++---- 20 files changed, 18 insertions(+), 5 deletions(-) delete mode 100644 core/src/main/res/drawable-hdpi/ic_hearing_grey600_18dp.png delete mode 100644 core/src/main/res/drawable-hdpi/ic_hearing_white_18dp.png delete mode 100644 core/src/main/res/drawable-hdpi/ic_remove_red_eye_grey600_18dp.png delete mode 100644 core/src/main/res/drawable-hdpi/ic_remove_red_eye_white_18dp.png delete mode 100644 core/src/main/res/drawable-mdpi/ic_hearing_grey600_18dp.png delete mode 100644 core/src/main/res/drawable-mdpi/ic_hearing_white_18dp.png delete mode 100644 core/src/main/res/drawable-mdpi/ic_remove_red_eye_grey600_18dp.png delete mode 100644 core/src/main/res/drawable-mdpi/ic_remove_red_eye_white_18dp.png delete mode 100644 core/src/main/res/drawable-xhdpi/ic_hearing_grey600_18dp.png delete mode 100644 core/src/main/res/drawable-xhdpi/ic_hearing_white_18dp.png delete mode 100644 core/src/main/res/drawable-xhdpi/ic_remove_red_eye_grey600_18dp.png delete mode 100644 core/src/main/res/drawable-xhdpi/ic_remove_red_eye_white_18dp.png delete mode 100644 core/src/main/res/drawable-xxhdpi/ic_hearing_grey600_18dp.png delete mode 100644 core/src/main/res/drawable-xxhdpi/ic_hearing_white_18dp.png delete mode 100644 core/src/main/res/drawable-xxhdpi/ic_remove_red_eye_grey600_18dp.png delete mode 100644 core/src/main/res/drawable-xxhdpi/ic_remove_red_eye_white_18dp.png create mode 100644 core/src/main/res/drawable/ic_videocam_grey600_24dp.xml create mode 100644 core/src/main/res/drawable/ic_videocam_white_24dp.xml (limited to 'core/src') diff --git a/core/src/main/res/drawable-hdpi/ic_hearing_grey600_18dp.png b/core/src/main/res/drawable-hdpi/ic_hearing_grey600_18dp.png deleted file mode 100644 index 2452cfa92..000000000 Binary files a/core/src/main/res/drawable-hdpi/ic_hearing_grey600_18dp.png and /dev/null differ diff --git a/core/src/main/res/drawable-hdpi/ic_hearing_white_18dp.png b/core/src/main/res/drawable-hdpi/ic_hearing_white_18dp.png deleted file mode 100644 index 96a06141a..000000000 Binary files a/core/src/main/res/drawable-hdpi/ic_hearing_white_18dp.png and /dev/null differ diff --git a/core/src/main/res/drawable-hdpi/ic_remove_red_eye_grey600_18dp.png b/core/src/main/res/drawable-hdpi/ic_remove_red_eye_grey600_18dp.png deleted file mode 100644 index 4f1af39ab..000000000 Binary files a/core/src/main/res/drawable-hdpi/ic_remove_red_eye_grey600_18dp.png and /dev/null differ diff --git a/core/src/main/res/drawable-hdpi/ic_remove_red_eye_white_18dp.png b/core/src/main/res/drawable-hdpi/ic_remove_red_eye_white_18dp.png deleted file mode 100644 index abc338d51..000000000 Binary files a/core/src/main/res/drawable-hdpi/ic_remove_red_eye_white_18dp.png and /dev/null differ diff --git a/core/src/main/res/drawable-mdpi/ic_hearing_grey600_18dp.png b/core/src/main/res/drawable-mdpi/ic_hearing_grey600_18dp.png deleted file mode 100644 index ea44e3f07..000000000 Binary files a/core/src/main/res/drawable-mdpi/ic_hearing_grey600_18dp.png and /dev/null differ diff --git a/core/src/main/res/drawable-mdpi/ic_hearing_white_18dp.png b/core/src/main/res/drawable-mdpi/ic_hearing_white_18dp.png deleted file mode 100644 index 78e98fe8d..000000000 Binary files a/core/src/main/res/drawable-mdpi/ic_hearing_white_18dp.png and /dev/null differ diff --git a/core/src/main/res/drawable-mdpi/ic_remove_red_eye_grey600_18dp.png b/core/src/main/res/drawable-mdpi/ic_remove_red_eye_grey600_18dp.png deleted file mode 100644 index daa8e568e..000000000 Binary files a/core/src/main/res/drawable-mdpi/ic_remove_red_eye_grey600_18dp.png and /dev/null differ diff --git a/core/src/main/res/drawable-mdpi/ic_remove_red_eye_white_18dp.png b/core/src/main/res/drawable-mdpi/ic_remove_red_eye_white_18dp.png deleted file mode 100644 index a6b4ff0da..000000000 Binary files a/core/src/main/res/drawable-mdpi/ic_remove_red_eye_white_18dp.png and /dev/null differ diff --git a/core/src/main/res/drawable-xhdpi/ic_hearing_grey600_18dp.png b/core/src/main/res/drawable-xhdpi/ic_hearing_grey600_18dp.png deleted file mode 100644 index d014684e1..000000000 Binary files a/core/src/main/res/drawable-xhdpi/ic_hearing_grey600_18dp.png and /dev/null differ diff --git a/core/src/main/res/drawable-xhdpi/ic_hearing_white_18dp.png b/core/src/main/res/drawable-xhdpi/ic_hearing_white_18dp.png deleted file mode 100644 index 91adb4437..000000000 Binary files a/core/src/main/res/drawable-xhdpi/ic_hearing_white_18dp.png and /dev/null differ diff --git a/core/src/main/res/drawable-xhdpi/ic_remove_red_eye_grey600_18dp.png b/core/src/main/res/drawable-xhdpi/ic_remove_red_eye_grey600_18dp.png deleted file mode 100644 index 2039d9ce8..000000000 Binary files a/core/src/main/res/drawable-xhdpi/ic_remove_red_eye_grey600_18dp.png and /dev/null differ diff --git a/core/src/main/res/drawable-xhdpi/ic_remove_red_eye_white_18dp.png b/core/src/main/res/drawable-xhdpi/ic_remove_red_eye_white_18dp.png deleted file mode 100644 index 6dd240bca..000000000 Binary files a/core/src/main/res/drawable-xhdpi/ic_remove_red_eye_white_18dp.png and /dev/null differ diff --git a/core/src/main/res/drawable-xxhdpi/ic_hearing_grey600_18dp.png b/core/src/main/res/drawable-xxhdpi/ic_hearing_grey600_18dp.png deleted file mode 100644 index 19456de04..000000000 Binary files a/core/src/main/res/drawable-xxhdpi/ic_hearing_grey600_18dp.png and /dev/null differ diff --git a/core/src/main/res/drawable-xxhdpi/ic_hearing_white_18dp.png b/core/src/main/res/drawable-xxhdpi/ic_hearing_white_18dp.png deleted file mode 100644 index 82de8bb65..000000000 Binary files a/core/src/main/res/drawable-xxhdpi/ic_hearing_white_18dp.png and /dev/null differ diff --git a/core/src/main/res/drawable-xxhdpi/ic_remove_red_eye_grey600_18dp.png b/core/src/main/res/drawable-xxhdpi/ic_remove_red_eye_grey600_18dp.png deleted file mode 100644 index 16cdc31c1..000000000 Binary files a/core/src/main/res/drawable-xxhdpi/ic_remove_red_eye_grey600_18dp.png and /dev/null differ diff --git a/core/src/main/res/drawable-xxhdpi/ic_remove_red_eye_white_18dp.png b/core/src/main/res/drawable-xxhdpi/ic_remove_red_eye_white_18dp.png deleted file mode 100644 index 695eb950e..000000000 Binary files a/core/src/main/res/drawable-xxhdpi/ic_remove_red_eye_white_18dp.png and /dev/null differ diff --git a/core/src/main/res/drawable/ic_videocam_grey600_24dp.xml b/core/src/main/res/drawable/ic_videocam_grey600_24dp.xml new file mode 100644 index 000000000..40c893883 --- /dev/null +++ b/core/src/main/res/drawable/ic_videocam_grey600_24dp.xml @@ -0,0 +1,8 @@ + + + diff --git a/core/src/main/res/drawable/ic_videocam_white_24dp.xml b/core/src/main/res/drawable/ic_videocam_white_24dp.xml new file mode 100644 index 000000000..a8cfd71e3 --- /dev/null +++ b/core/src/main/res/drawable/ic_videocam_white_24dp.xml @@ -0,0 +1,8 @@ + + + diff --git a/core/src/main/res/values/attrs.xml b/core/src/main/res/values/attrs.xml index 53cf7b211..066594f3d 100644 --- a/core/src/main/res/values/attrs.xml +++ b/core/src/main/res/values/attrs.xml @@ -26,7 +26,6 @@ - diff --git a/core/src/main/res/values/styles.xml b/core/src/main/res/values/styles.xml index f5b43629c..d341048ff 100644 --- a/core/src/main/res/values/styles.xml +++ b/core/src/main/res/values/styles.xml @@ -38,8 +38,7 @@ @drawable/navigation_up @drawable/ic_share_grey600_24dp @drawable/ic_list_grey600_24dp - @drawable/ic_hearing_grey600_18dp - @drawable/ic_remove_red_eye_grey600_18dp + @drawable/ic_videocam_grey600_24dp @color/white @color/overlay_light @drawable/overlay_drawable @@ -127,8 +126,7 @@ @drawable/navigation_up_dark @drawable/ic_share_white_24dp @drawable/ic_list_white_24dp - @drawable/ic_hearing_white_18dp - @drawable/ic_remove_red_eye_white_18dp + @drawable/ic_videocam_white_24dp @color/black @color/overlay_dark @drawable/overlay_drawable_dark -- cgit v1.2.3 From 3ca6be8b04cf3c96517cb5ca9c16d2b0b67eead5 Mon Sep 17 00:00:00 2001 From: ByteHamster Date: Wed, 5 Feb 2020 11:38:30 +0100 Subject: Increase touchable area --- core/src/main/java/de/danoeh/antennapod/core/util/ThemeUtils.java | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'core/src') diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/ThemeUtils.java b/core/src/main/java/de/danoeh/antennapod/core/util/ThemeUtils.java index eabaaa828..44b31f0be 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/ThemeUtils.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/ThemeUtils.java @@ -4,6 +4,7 @@ import android.content.Context; import androidx.annotation.AttrRes; import androidx.annotation.ColorInt; import android.util.TypedValue; +import androidx.annotation.DrawableRes; public class ThemeUtils { private ThemeUtils() { @@ -15,4 +16,10 @@ public class ThemeUtils { context.getTheme().resolveAttribute(attr, typedValue, true); return typedValue.data; } + + public static @DrawableRes int getDrawableFromAttr(Context context, @AttrRes int attr) { + TypedValue typedValue = new TypedValue(); + context.getTheme().resolveAttribute(attr, typedValue, true); + return typedValue.resourceId; + } } -- cgit v1.2.3 From c3e1f8afbbb798c2bc1fde2d835d19cce5ebfc31 Mon Sep 17 00:00:00 2001 From: ByteHamster Date: Wed, 5 Feb 2020 16:43:41 +0100 Subject: Made a bit more space --- core/src/main/res/values/dimens.xml | 2 +- core/src/main/res/values/styles.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'core/src') diff --git a/core/src/main/res/values/dimens.xml b/core/src/main/res/values/dimens.xml index d9d1bc6fe..34cbe1b72 100644 --- a/core/src/main/res/values/dimens.xml +++ b/core/src/main/res/values/dimens.xml @@ -23,7 +23,7 @@ 16dp 8dp - 16dp + 8dp 16dp 8dp diff --git a/core/src/main/res/values/styles.xml b/core/src/main/res/values/styles.xml index d341048ff..c7f45a29e 100644 --- a/core/src/main/res/values/styles.xml +++ b/core/src/main/res/values/styles.xml @@ -285,7 +285,7 @@ -- cgit v1.2.3 From 2e6fc7a0a5b185e3d0c077daa80404aa99e8a432 Mon Sep 17 00:00:00 2001 From: ByteHamster Date: Wed, 5 Feb 2020 18:18:10 +0100 Subject: Using unified item view in search fragment --- .../java/de/danoeh/antennapod/core/storage/FeedSearcher.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'core/src') diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/FeedSearcher.java b/core/src/main/java/de/danoeh/antennapod/core/storage/FeedSearcher.java index bbe8b26f1..77c8d3b7f 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/FeedSearcher.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/FeedSearcher.java @@ -35,11 +35,12 @@ public class FeedSearcher { final List result = new ArrayList<>(); try { FutureTask> itemSearchTask = DBTasks.searchFeedItems(context, selectedFeed, query); - FutureTask> feedSearchTask = DBTasks.searchFeeds(context, query); itemSearchTask.run(); - feedSearchTask.run(); - - result.addAll(feedSearchTask.get()); + if (selectedFeed == 0) { + FutureTask> feedSearchTask = DBTasks.searchFeeds(context, query); + feedSearchTask.run(); + result.addAll(feedSearchTask.get()); + } result.addAll(itemSearchTask.get()); } catch (InterruptedException | ExecutionException e) { e.printStackTrace(); -- cgit v1.2.3 From 24a51062e0c59b5ef2acea42d7536209254a37a1 Mon Sep 17 00:00:00 2001 From: ByteHamster Date: Thu, 6 Feb 2020 12:49:13 +0100 Subject: Updated download log list --- core/src/main/res/values/colors.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'core/src') diff --git a/core/src/main/res/values/colors.xml b/core/src/main/res/values/colors.xml index fea7da4a4..b162038cf 100644 --- a/core/src/main/res/values/colors.xml +++ b/core/src/main/res/values/colors.xml @@ -7,8 +7,8 @@ #000000 #33B5E5 #0099CC - #669900 - #CC0000 + #248800 + #B00020 #E033B5E5 #2C2C2C #FFFFFF -- cgit v1.2.3 From 7ec9b00e8b080df831adeafdccf3633a26de1836 Mon Sep 17 00:00:00 2001 From: ByteHamster Date: Thu, 6 Feb 2020 22:51:58 +0100 Subject: Updated running downloads list --- core/src/main/res/values/strings.xml | 1 + 1 file changed, 1 insertion(+) (limited to 'core/src') diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index e5d8247bc..8cb9f7b84 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -102,6 +102,7 @@ Light Heavy \u0020parallel downloads + Download queued Global default Always Never -- cgit v1.2.3 From aa48cdb14c6ce23e07199ab706ae97d11af8035b Mon Sep 17 00:00:00 2001 From: ByteHamster Date: Sat, 8 Feb 2020 00:12:33 +0100 Subject: Do not return true in handleKeycode if nothing was done --- .../antennapod/core/service/playback/PlaybackService.java | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'core/src') diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java index fbd8d65d8..bf59b0ffd 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java @@ -573,6 +573,8 @@ public class PlaybackService extends MediaBrowserServiceCompat { mediaPlayer.prepare(); } else if (mediaPlayer.getPlayable() == null) { startPlayingFromPreferences(); + } else { + return false; } taskManager.restartSleepTimer(); return true; @@ -584,18 +586,19 @@ public class PlaybackService extends MediaBrowserServiceCompat { mediaPlayer.prepare(); } else if (mediaPlayer.getPlayable() == null) { startPlayingFromPreferences(); + } else { + return false; } taskManager.restartSleepTimer(); return true; case KeyEvent.KEYCODE_MEDIA_PAUSE: if (status == PlayerStatus.PLAYING) { mediaPlayer.pause(!UserPreferences.isPersistNotify(), false); + return true; } - - return true; + return false; case KeyEvent.KEYCODE_MEDIA_NEXT: - if (notificationButton || - UserPreferences.shouldHardwareButtonSkip()) { + if (notificationButton || UserPreferences.shouldHardwareButtonSkip()) { // assume the skip command comes from a notification or the lockscreen // a >| skip button should actually skip mediaPlayer.skip(); -- cgit v1.2.3 From ca4e5500f68f466e95fbf8fd682bc887de3a57e9 Mon Sep 17 00:00:00 2001 From: ByteHamster Date: Sat, 8 Feb 2020 00:32:50 +0100 Subject: Set file size after downlaod Fixes media size being unknown even if item is downloaded --- .../core/service/download/handler/MediaDownloadedHandler.java | 2 ++ 1 file changed, 2 insertions(+) (limited to 'core/src') 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 40be2895c..9ecabd14b 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 @@ -6,6 +6,7 @@ import android.util.Log; import androidx.annotation.NonNull; +import java.io.File; import java.util.concurrent.ExecutionException; import de.danoeh.antennapod.core.event.UnreadItemsUpdateEvent; @@ -50,6 +51,7 @@ public class MediaDownloadedHandler implements Runnable { boolean broadcastUnreadStateUpdate = media.getItem() != null && media.getItem().isNew(); media.setDownloaded(true); media.setFile_url(request.getDestination()); + media.setSize(new File(request.getDestination()).length()); media.checkEmbeddedPicture(); // enforce check // check if file has chapters -- cgit v1.2.3 From 332c4657e501374c4277923984035802cc344993 Mon Sep 17 00:00:00 2001 From: Tony Tam Date: Sat, 8 Feb 2020 19:12:00 -0800 Subject: do not infinite download on 410, 400 --- .../danoeh/antennapod/core/service/download/DownloadService.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'core/src') diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java b/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java index f7c338729..10e271bb0 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java @@ -336,7 +336,12 @@ public class DownloadService extends Service { && String.valueOf(HttpURLConnection.HTTP_FORBIDDEN).equals(status.getReasonDetailed()); boolean notEnoughSpace = status.getReason() == DownloadError.ERROR_NOT_ENOUGH_SPACE; boolean wrongFileType = status.getReason() == DownloadError.ERROR_FILE_TYPE; - if (httpNotFound || forbidden || notEnoughSpace || wrongFileType) { + boolean httpGone = status.getReason() == DownloadError.ERROR_HTTP_DATA_ERROR + && String.valueOf(HttpURLConnection.HTTP_GONE).equals(status.getReasonDetailed()); + boolean httpBadReq = status.getReason() == DownloadError.ERROR_HTTP_DATA_ERROR + && String.valueOf(HttpURLConnection.HTTP_BAD_REQUEST).equals(status.getReasonDetailed()); + + if (httpNotFound || forbidden || notEnoughSpace || wrongFileType || httpGone || httpBadReq ) { try { DBWriter.saveFeedItemAutoDownloadFailed(item).get(); } catch (ExecutionException | InterruptedException e) { -- cgit v1.2.3 From 3676644389f09d8d52e3b5da9ddf38c1d4e4a2d7 Mon Sep 17 00:00:00 2001 From: Tony Tam Date: Mon, 10 Feb 2020 00:32:18 -0800 Subject: 30dp buttons for notification / lock screen (play, fwd, rewind) buttons (#3840) --- core/src/main/res/drawable/ic_notification_cast_off.xml | 4 ++-- core/src/main/res/drawable/ic_notification_fast_forward.xml | 4 ++-- core/src/main/res/drawable/ic_notification_fast_rewind.xml | 4 ++-- core/src/main/res/drawable/ic_notification_pause.xml | 4 ++-- core/src/main/res/drawable/ic_notification_play.xml | 4 ++-- core/src/main/res/drawable/ic_notification_skip.xml | 4 ++-- 6 files changed, 12 insertions(+), 12 deletions(-) (limited to 'core/src') diff --git a/core/src/main/res/drawable/ic_notification_cast_off.xml b/core/src/main/res/drawable/ic_notification_cast_off.xml index 63a21fbe2..3e3accd0b 100644 --- a/core/src/main/res/drawable/ic_notification_cast_off.xml +++ b/core/src/main/res/drawable/ic_notification_cast_off.xml @@ -1,5 +1,5 @@ + android:height="30dp" android:viewportHeight="24.0" + android:viewportWidth="24.0" android:width="30dp"> \ No newline at end of file diff --git a/core/src/main/res/drawable/ic_notification_fast_forward.xml b/core/src/main/res/drawable/ic_notification_fast_forward.xml index bf564977c..8ee82f4ed 100644 --- a/core/src/main/res/drawable/ic_notification_fast_forward.xml +++ b/core/src/main/res/drawable/ic_notification_fast_forward.xml @@ -1,5 +1,5 @@ + android:height="30dp" android:viewportHeight="24.0" + android:viewportWidth="24.0" android:width="30dp"> diff --git a/core/src/main/res/drawable/ic_notification_fast_rewind.xml b/core/src/main/res/drawable/ic_notification_fast_rewind.xml index 847159cc5..261ed7e6f 100644 --- a/core/src/main/res/drawable/ic_notification_fast_rewind.xml +++ b/core/src/main/res/drawable/ic_notification_fast_rewind.xml @@ -1,5 +1,5 @@ + android:height="30dp" android:viewportHeight="24.0" + android:viewportWidth="24.0" android:width="30dp"> diff --git a/core/src/main/res/drawable/ic_notification_pause.xml b/core/src/main/res/drawable/ic_notification_pause.xml index d46efb2f5..16ebd4eab 100644 --- a/core/src/main/res/drawable/ic_notification_pause.xml +++ b/core/src/main/res/drawable/ic_notification_pause.xml @@ -1,5 +1,5 @@ + android:height="30dp" android:viewportHeight="24.0" + android:viewportWidth="24.0" android:width="30dp"> diff --git a/core/src/main/res/drawable/ic_notification_play.xml b/core/src/main/res/drawable/ic_notification_play.xml index d571460c6..eb4acd983 100644 --- a/core/src/main/res/drawable/ic_notification_play.xml +++ b/core/src/main/res/drawable/ic_notification_play.xml @@ -1,5 +1,5 @@ + android:height="30dp" android:viewportHeight="24.0" + android:viewportWidth="24.0" android:width="30dp"> diff --git a/core/src/main/res/drawable/ic_notification_skip.xml b/core/src/main/res/drawable/ic_notification_skip.xml index 0c65448cc..6bf03002a 100644 --- a/core/src/main/res/drawable/ic_notification_skip.xml +++ b/core/src/main/res/drawable/ic_notification_skip.xml @@ -1,5 +1,5 @@ + android:height="30dp" android:viewportHeight="24.0" + android:viewportWidth="24.0" android:width="30dp"> -- cgit v1.2.3 From f34430eb282eba37922a2022654e7b3eba26032f Mon Sep 17 00:00:00 2001 From: ByteHamster Date: Wed, 12 Feb 2020 12:21:16 +0100 Subject: Increase blurred image size Today's screens have a much better resolution than a few years ago when this code was created. Use 1/3 of the target size of the image instead of a fixed size. The transformed image is cached by Glide, so the transformation does not need to be done multiple times. This way, the images look a lot better (because they are not stretched to be displayed). --- .../core/glide/FastBlurTransformation.java | 24 +++++++++------------- 1 file changed, 10 insertions(+), 14 deletions(-) (limited to 'core/src') diff --git a/core/src/main/java/de/danoeh/antennapod/core/glide/FastBlurTransformation.java b/core/src/main/java/de/danoeh/antennapod/core/glide/FastBlurTransformation.java index 3cc906b7f..d2d9e5947 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/glide/FastBlurTransformation.java +++ b/core/src/main/java/de/danoeh/antennapod/core/glide/FastBlurTransformation.java @@ -14,19 +14,15 @@ public class FastBlurTransformation extends BitmapTransformation { private static final String TAG = FastBlurTransformation.class.getSimpleName(); - private static final int STACK_BLUR_RADIUS = 1; - private static final int BLUR_IMAGE_WIDTH = 150; + private static final int STACK_BLUR_RADIUS = 5; public FastBlurTransformation() { super(); } @Override - protected Bitmap transform(BitmapPool pool, Bitmap source, - int outWidth, int outHeight) { - int targetWidth = BLUR_IMAGE_WIDTH; - int targetHeight = (int) (1.0 * outHeight * targetWidth / outWidth); - Bitmap resized = ThumbnailUtils.extractThumbnail(source, targetWidth, targetHeight); + protected Bitmap transform(BitmapPool pool, Bitmap source, int outWidth, int outHeight) { + Bitmap resized = ThumbnailUtils.extractThumbnail(source, outWidth / 3, outHeight / 3); Bitmap result = fastBlur(resized, STACK_BLUR_RADIUS); if (result == null) { Log.w(TAG, "result was null"); @@ -80,9 +76,9 @@ public class FastBlurTransformation extends BitmapTransformation { int wh = w * h; int div = radius + radius + 1; - int r[] = new int[wh]; - int g[] = new int[wh]; - int b[] = new int[wh]; + int[] r = new int[wh]; + int[] g = new int[wh]; + int[] b = new int[wh]; int rsum; int gsum; int bsum; @@ -93,11 +89,11 @@ public class FastBlurTransformation extends BitmapTransformation { int yp; int yi; int yw; - int vmin[] = new int[Math.max(w, h)]; + int[] vmin = new int[Math.max(w, h)]; int divsum = (div + 1) >> 1; divsum *= divsum; - int dv[] = new int[256 * divsum]; + int[] dv = new int[256 * divsum]; for (i = 0; i < 256 * divsum; i++) { dv[i] = (i / divsum); } @@ -225,8 +221,8 @@ public class FastBlurTransformation extends BitmapTransformation { yi = x; stackpointer = radius; for (y = 0; y < h; y++) { - // Preserve alpha channel: ( 0xff000000 & pix[yi] ) - pix[yi] = (0xff000000 & pix[yi]) | (dv[rsum] << 16) | (dv[gsum] << 8) | dv[bsum]; + // Set alpha to 1 + pix[yi] = 0xff000000 | (dv[rsum] << 16) | (dv[gsum] << 8) | dv[bsum]; rsum -= routsum; gsum -= goutsum; -- cgit v1.2.3 From 0485102797c5e58af967e6b99f58fe6ea5149e44 Mon Sep 17 00:00:00 2001 From: ByteHamster Date: Wed, 12 Feb 2020 13:25:05 +0100 Subject: Updated player screen appearance --- core/src/main/res/values-h768dp/dimens.xml | 4 ---- core/src/main/res/values/dimens.xml | 2 -- 2 files changed, 6 deletions(-) delete mode 100644 core/src/main/res/values-h768dp/dimens.xml (limited to 'core/src') diff --git a/core/src/main/res/values-h768dp/dimens.xml b/core/src/main/res/values-h768dp/dimens.xml deleted file mode 100644 index fd744e422..000000000 --- a/core/src/main/res/values-h768dp/dimens.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - 12dp - \ No newline at end of file diff --git a/core/src/main/res/values/dimens.xml b/core/src/main/res/values/dimens.xml index 34cbe1b72..ee2c57ac4 100644 --- a/core/src/main/res/values/dimens.xml +++ b/core/src/main/res/values/dimens.xml @@ -37,6 +37,4 @@ 24dp 8dp - 0dp - -- cgit v1.2.3 From 5caaaa9e5a3305f25338eea72af7f413b9d43969 Mon Sep 17 00:00:00 2001 From: ByteHamster Date: Fri, 7 Feb 2020 00:41:44 +0100 Subject: Initial database support for chapter images --- .../de/danoeh/antennapod/core/feed/Chapter.java | 162 +++++++++--------- .../de/danoeh/antennapod/core/feed/ID3Chapter.java | 62 +++---- .../danoeh/antennapod/core/feed/SimpleChapter.java | 27 +-- .../antennapod/core/feed/VorbisCommentChapter.java | 181 +++++++++------------ .../danoeh/antennapod/core/storage/DBReader.java | 13 +- .../danoeh/antennapod/core/storage/DBUpgrader.java | 8 +- .../antennapod/core/storage/PodDBAdapter.java | 4 +- .../syndication/namespace/NSSimpleChapters.java | 9 +- 8 files changed, 221 insertions(+), 245 deletions(-) (limited to 'core/src') diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/Chapter.java b/core/src/main/java/de/danoeh/antennapod/core/feed/Chapter.java index f3dfdfdb6..2af946c67 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/feed/Chapter.java +++ b/core/src/main/java/de/danoeh/antennapod/core/feed/Chapter.java @@ -2,85 +2,99 @@ package de.danoeh.antennapod.core.feed; import android.database.Cursor; +import android.text.TextUtils; import de.danoeh.antennapod.core.storage.PodDBAdapter; +import java.util.Objects; + public abstract class Chapter extends FeedComponent { - /** Defines starting point in milliseconds. */ + /** Defines starting point in milliseconds. */ long start; - String title; - String link; - - Chapter() { - } - - Chapter(long start) { - super(); - this.start = start; - } - - Chapter(long start, String title, FeedItem item, String link) { - super(); - this.start = start; - this.title = title; - this.link = link; - } - - public static Chapter fromCursor(Cursor cursor, FeedItem item) { - int indexId = cursor.getColumnIndex(PodDBAdapter.KEY_ID); - int indexTitle = cursor.getColumnIndex(PodDBAdapter.KEY_TITLE); - int indexStart = cursor.getColumnIndex(PodDBAdapter.KEY_START); - int indexLink = cursor.getColumnIndex(PodDBAdapter.KEY_LINK); - int indexChapterType = cursor.getColumnIndex(PodDBAdapter.KEY_CHAPTER_TYPE); - - long id = cursor.getLong(indexId); - String title = cursor.getString(indexTitle); - long start = cursor.getLong(indexStart); - String link = cursor.getString(indexLink); - int chapterType = cursor.getInt(indexChapterType); - - Chapter chapter = null; - switch (chapterType) { - case SimpleChapter.CHAPTERTYPE_SIMPLECHAPTER: - chapter = new SimpleChapter(start, title, item, link); - break; - case ID3Chapter.CHAPTERTYPE_ID3CHAPTER: - chapter = new ID3Chapter(start, title, item, link); - break; - case VorbisCommentChapter.CHAPTERTYPE_VORBISCOMMENT_CHAPTER: - chapter = new VorbisCommentChapter(start, title, item, link); - break; - } - chapter.setId(id); - return chapter; - } - - - public abstract int getChapterType(); - - public long getStart() { - return start; - } - - public String getTitle() { - return title; - } - - public String getLink() { - return link; - } - - public void setStart(long start) { - this.start = start; - } - - public void setTitle(String title) { - this.title = title; - } - - public void setLink(String link) { - this.link = link; - } + String title; + String link; + String imageUrl; + + Chapter() { + } + + Chapter(long start) { + super(); + this.start = start; + } + + Chapter(long start, String title, String link, String imageUrl) { + super(); + this.start = start; + this.title = title; + this.link = link; + this.imageUrl = imageUrl; + } + + public static Chapter fromCursor(Cursor cursor) { + int indexId = cursor.getColumnIndex(PodDBAdapter.KEY_ID); + int indexTitle = cursor.getColumnIndex(PodDBAdapter.KEY_TITLE); + int indexStart = cursor.getColumnIndex(PodDBAdapter.KEY_START); + int indexLink = cursor.getColumnIndex(PodDBAdapter.KEY_LINK); + int indexImage = cursor.getColumnIndex(PodDBAdapter.KEY_IMAGE_URL); + int indexChapterType = cursor.getColumnIndex(PodDBAdapter.KEY_CHAPTER_TYPE); + + long id = cursor.getLong(indexId); + String title = cursor.getString(indexTitle); + long start = cursor.getLong(indexStart); + String link = cursor.getString(indexLink); + String imageUrl = cursor.getString(indexImage); + int chapterType = cursor.getInt(indexChapterType); + + Chapter chapter = null; + switch (chapterType) { + case SimpleChapter.CHAPTERTYPE_SIMPLECHAPTER: + chapter = new SimpleChapter(start, title, link, imageUrl); + break; + case ID3Chapter.CHAPTERTYPE_ID3CHAPTER: + chapter = new ID3Chapter(start, title, link, imageUrl); + break; + case VorbisCommentChapter.CHAPTERTYPE_VORBISCOMMENT_CHAPTER: + chapter = new VorbisCommentChapter(start, title, link, imageUrl); + break; + } + chapter.setId(id); + return chapter; + } + + public abstract int getChapterType(); + + public long getStart() { + return start; + } + + public String getTitle() { + return title; + } + + public String getLink() { + return link; + } + + public void setStart(long start) { + this.start = start; + } + + public void setTitle(String title) { + this.title = title; + } + + public void setLink(String link) { + this.link = link; + } + + public String getImageUrl() { + return imageUrl; + } + + public void setImageUrl(String imageUrl) { + this.imageUrl = imageUrl; + } @Override public String getHumanReadableIdentifier() { diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/ID3Chapter.java b/core/src/main/java/de/danoeh/antennapod/core/feed/ID3Chapter.java index f0ff03a93..b69d537fb 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/feed/ID3Chapter.java +++ b/core/src/main/java/de/danoeh/antennapod/core/feed/ID3Chapter.java @@ -1,36 +1,36 @@ package de.danoeh.antennapod.core.feed; public class ID3Chapter extends Chapter { - public static final int CHAPTERTYPE_ID3CHAPTER = 2; - - /** - * Identifies the chapter in its ID3 tag. This attribute does not have to be - * store in the DB and is only used for parsing. - */ - private String id3ID; - - public ID3Chapter(String id3ID, long start) { - super(start); - this.id3ID = id3ID; - } - - public ID3Chapter(long start, String title, FeedItem item, String link) { - super(start, title, item, link); - } - - @Override - public String toString() { - return "ID3Chapter [id3ID=" + id3ID + ", title=" + title + ", start=" - + start + ", url=" + link + "]"; - } - - @Override - public int getChapterType() { - return CHAPTERTYPE_ID3CHAPTER; - } - - public String getId3ID() { - return id3ID; - } + public static final int CHAPTERTYPE_ID3CHAPTER = 2; + + /** + * Identifies the chapter in its ID3 tag. This attribute does not have to be + * store in the DB and is only used for parsing. + */ + private String id3ID; + + public ID3Chapter(String id3ID, long start) { + super(start); + this.id3ID = id3ID; + } + + public ID3Chapter(long start, String title, String link, String imageUrl) { + super(start, title, link, imageUrl); + } + + @Override + public String toString() { + return "ID3Chapter [id3ID=" + id3ID + ", title=" + title + ", start=" + + start + ", url=" + link + "]"; + } + + @Override + public int getChapterType() { + return CHAPTERTYPE_ID3CHAPTER; + } + + public String getId3ID() { + return id3ID; + } } diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/SimpleChapter.java b/core/src/main/java/de/danoeh/antennapod/core/feed/SimpleChapter.java index 2dadd3ec8..45c71a014 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/feed/SimpleChapter.java +++ b/core/src/main/java/de/danoeh/antennapod/core/feed/SimpleChapter.java @@ -1,25 +1,14 @@ package de.danoeh.antennapod.core.feed; public class SimpleChapter extends Chapter { - public static final int CHAPTERTYPE_SIMPLECHAPTER = 0; - - public SimpleChapter(long start, String title, FeedItem item, String link) { - super(start, title, item, link); - } + public static final int CHAPTERTYPE_SIMPLECHAPTER = 0; - @Override - public int getChapterType() { - return CHAPTERTYPE_SIMPLECHAPTER; - } + public SimpleChapter(long start, String title, String link, String imageUrl) { + super(start, title, link, imageUrl); + } - public void updateFromOther(SimpleChapter other) { - super.updateFromOther(other); - start = other.start; - if (other.title != null) { - title = other.title; - } - if (other.link != null) { - link = other.link; - } - } + @Override + public int getChapterType() { + return CHAPTERTYPE_SIMPLECHAPTER; + } } diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/VorbisCommentChapter.java b/core/src/main/java/de/danoeh/antennapod/core/feed/VorbisCommentChapter.java index 5ab9868a6..eac50aed8 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/feed/VorbisCommentChapter.java +++ b/core/src/main/java/de/danoeh/antennapod/core/feed/VorbisCommentChapter.java @@ -5,105 +5,84 @@ import java.util.concurrent.TimeUnit; import de.danoeh.antennapod.core.util.vorbiscommentreader.VorbisCommentReaderException; public class VorbisCommentChapter extends Chapter { - public static final int CHAPTERTYPE_VORBISCOMMENT_CHAPTER = 3; - - private static final int CHAPTERXXX_LENGTH = "chapterxxx".length(); - - private int vorbisCommentId; - - public VorbisCommentChapter(int vorbisCommentId) { - this.vorbisCommentId = vorbisCommentId; - } - - public VorbisCommentChapter(long start, String title, FeedItem item, - String link) { - super(start, title, item, link); - } - - @Override - public String toString() { - return "VorbisCommentChapter [id=" + id + ", title=" + title - + ", link=" + link + ", start=" + start + "]"; - } - - public static long getStartTimeFromValue(String value) - throws VorbisCommentReaderException { - String[] parts = value.split(":"); - if (parts.length >= 3) { - try { - long hours = TimeUnit.MILLISECONDS.convert( - Long.parseLong(parts[0]), TimeUnit.HOURS); - long minutes = TimeUnit.MILLISECONDS.convert( - Long.parseLong(parts[1]), TimeUnit.MINUTES); - if (parts[2].contains("-->")) { - parts[2] = parts[2].substring(0, parts[2].indexOf("-->")); - } - long seconds = TimeUnit.MILLISECONDS.convert( - ((long) Float.parseFloat(parts[2])), TimeUnit.SECONDS); - return hours + minutes + seconds; - } catch (NumberFormatException e) { - throw new VorbisCommentReaderException(e); - } - } else { - throw new VorbisCommentReaderException("Invalid time string"); - } - } - - /** - * Return the id of a vorbiscomment chapter from a string like CHAPTERxxx* - * - * @return the id of the chapter key or -1 if the id couldn't be read. - * @throws VorbisCommentReaderException - * */ - public static int getIDFromKey(String key) - throws VorbisCommentReaderException { - if (key.length() >= CHAPTERXXX_LENGTH) { // >= CHAPTERxxx - try { - String strId = key.substring(8, 10); - return Integer.parseInt(strId); - } catch (NumberFormatException e) { - throw new VorbisCommentReaderException(e); - } - } - throw new VorbisCommentReaderException("key is too short (" + key + ")"); - } - - /** - * Get the string that comes after 'CHAPTERxxx', for example 'name' or - * 'url'. - */ - public static String getAttributeTypeFromKey(String key) { - if (key.length() > CHAPTERXXX_LENGTH) { - return key.substring(CHAPTERXXX_LENGTH, key.length()); - } - return null; - } - - @Override - public int getChapterType() { - return CHAPTERTYPE_VORBISCOMMENT_CHAPTER; - } - - public void setTitle(String title) { - this.title = title; - } - - public void setLink(String link) { - this.link = link; - } - - public void setStart(long start) { - this.start = start; - } - - public int getVorbisCommentId() { - return vorbisCommentId; - } - - public void setVorbisCommentId(int vorbisCommentId) { - this.vorbisCommentId = vorbisCommentId; - } - - - + public static final int CHAPTERTYPE_VORBISCOMMENT_CHAPTER = 3; + + private static final int CHAPTERXXX_LENGTH = "chapterxxx".length(); + + private int vorbisCommentId; + + public VorbisCommentChapter(int vorbisCommentId) { + this.vorbisCommentId = vorbisCommentId; + } + + public VorbisCommentChapter(long start, String title, String link, String imageUrl) { + super(start, title, link, imageUrl); + } + + @Override + public String toString() { + return "VorbisCommentChapter [id=" + id + ", title=" + title + + ", link=" + link + ", start=" + start + "]"; + } + + public static long getStartTimeFromValue(String value) + throws VorbisCommentReaderException { + String[] parts = value.split(":"); + if (parts.length >= 3) { + try { + long hours = TimeUnit.MILLISECONDS.convert( + Long.parseLong(parts[0]), TimeUnit.HOURS); + long minutes = TimeUnit.MILLISECONDS.convert( + Long.parseLong(parts[1]), TimeUnit.MINUTES); + if (parts[2].contains("-->")) { + parts[2] = parts[2].substring(0, parts[2].indexOf("-->")); + } + long seconds = TimeUnit.MILLISECONDS.convert( + ((long) Float.parseFloat(parts[2])), TimeUnit.SECONDS); + return hours + minutes + seconds; + } catch (NumberFormatException e) { + throw new VorbisCommentReaderException(e); + } + } else { + throw new VorbisCommentReaderException("Invalid time string"); + } + } + + /** + * Return the id of a vorbiscomment chapter from a string like CHAPTERxxx* + * + * @return the id of the chapter key or -1 if the id couldn't be read. + * @throws VorbisCommentReaderException + * */ + public static int getIDFromKey(String key) throws VorbisCommentReaderException { + if (key.length() >= CHAPTERXXX_LENGTH) { // >= CHAPTERxxx + try { + String strId = key.substring(8, 10); + return Integer.parseInt(strId); + } catch (NumberFormatException e) { + throw new VorbisCommentReaderException(e); + } + } + throw new VorbisCommentReaderException("key is too short (" + key + ")"); + } + + /** + * Get the string that comes after 'CHAPTERxxx', for example 'name' or + * 'url'. + */ + public static String getAttributeTypeFromKey(String key) { + if (key.length() > CHAPTERXXX_LENGTH) { + return key.substring(CHAPTERXXX_LENGTH); + } + return null; + } + + @Override + public int getChapterType() { + return CHAPTERTYPE_VORBISCOMMENT_CHAPTER; + } + + public int getVorbisCommentId() { + return vorbisCommentId; + } } 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 4f4ee4721..e818f3072 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 @@ -795,9 +795,7 @@ public final class DBReader { } private static void loadChaptersOfFeedItem(PodDBAdapter adapter, FeedItem item) { - Cursor cursor = null; - try { - cursor = adapter.getSimpleChaptersOfFeedItemCursor(item); + try (Cursor cursor = adapter.getSimpleChaptersOfFeedItemCursor(item)) { int chaptersCount = cursor.getCount(); if (chaptersCount == 0) { item.setChapters(null); @@ -805,14 +803,7 @@ public final class DBReader { } item.setChapters(new ArrayList<>(chaptersCount)); while (cursor.moveToNext()) { - Chapter chapter = Chapter.fromCursor(cursor, item); - if (chapter != null) { - item.getChapters().add(chapter); - } - } - } finally { - if (cursor != null) { - cursor.close(); + item.getChapters().add(Chapter.fromCursor(cursor)); } } } diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DBUpgrader.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DBUpgrader.java index 234ce8367..ee31c8cc4 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/DBUpgrader.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DBUpgrader.java @@ -95,7 +95,7 @@ class DBUpgrader { + " ADD COLUMN " + PodDBAdapter.KEY_PASSWORD + " TEXT"); db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEED_ITEMS - + " ADD COLUMN " + PodDBAdapter.KEY_IMAGE + + " ADD COLUMN image" + " INTEGER"); } if (oldVersion <= 12) { @@ -280,13 +280,13 @@ class DBUpgrader { + " SELECT " + PodDBAdapter.KEY_DOWNLOAD_URL + " FROM " + PodDBAdapter.TABLE_NAME_FEED_IMAGES + " WHERE " + PodDBAdapter.TABLE_NAME_FEED_IMAGES + "." + PodDBAdapter.KEY_ID - + " = " + PodDBAdapter.TABLE_NAME_FEED_ITEMS + "." + PodDBAdapter.KEY_IMAGE + ")"); + + " = " + PodDBAdapter.TABLE_NAME_FEED_ITEMS + ".image)"); db.execSQL("UPDATE " + PodDBAdapter.TABLE_NAME_FEEDS + " SET " + PodDBAdapter.KEY_IMAGE_URL + " = (" + " SELECT " + PodDBAdapter.KEY_DOWNLOAD_URL + " FROM " + PodDBAdapter.TABLE_NAME_FEED_IMAGES + " WHERE " + PodDBAdapter.TABLE_NAME_FEED_IMAGES + "." + PodDBAdapter.KEY_ID - + " = " + PodDBAdapter.TABLE_NAME_FEEDS + "." + PodDBAdapter.KEY_IMAGE + ")"); + + " = " + PodDBAdapter.TABLE_NAME_FEEDS + ".image)"); db.execSQL("DROP TABLE " + PodDBAdapter.TABLE_NAME_FEED_IMAGES); } @@ -301,6 +301,8 @@ class DBUpgrader { if (oldVersion < 1090000) { db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS + " ADD COLUMN " + PodDBAdapter.KEY_FEED_VOLUME_ADAPTION + " INTEGER DEFAULT 0"); + db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_SIMPLECHAPTERS + + " ADD COLUMN " + PodDBAdapter.KEY_IMAGE_URL + " TEXT DEFAULT NULL"); } } diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java b/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java index 4e2588f22..af6a8ef81 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java @@ -69,7 +69,6 @@ public class PodDBAdapter { public static final String KEY_POSITION = "position"; public static final String KEY_SIZE = "filesize"; public static final String KEY_MIME_TYPE = "mime_type"; - public static final String KEY_IMAGE = "image"; public static final String KEY_IMAGE_URL = "image_url"; public static final String KEY_FEED = "feed"; public static final String KEY_MEDIA = "media"; @@ -183,7 +182,7 @@ public class PodDBAdapter { private static final String CREATE_TABLE_SIMPLECHAPTERS = "CREATE TABLE " + TABLE_NAME_SIMPLECHAPTERS + " (" + TABLE_PRIMARY_KEY + KEY_TITLE + " TEXT," + KEY_START + " INTEGER," + KEY_FEEDITEM + " INTEGER," - + KEY_LINK + " TEXT," + KEY_CHAPTER_TYPE + " INTEGER)"; + + KEY_LINK + " TEXT," + KEY_IMAGE_URL + " TEXT," + KEY_CHAPTER_TYPE + " INTEGER)"; // SQL Statements for creating indexes static final String CREATE_INDEX_FEEDITEMS_FEED = "CREATE INDEX " @@ -674,6 +673,7 @@ public class PodDBAdapter { values.put(KEY_START, chapter.getStart()); values.put(KEY_FEEDITEM, item.getId()); values.put(KEY_LINK, chapter.getLink()); + values.put(KEY_IMAGE_URL, chapter.getImageUrl()); values.put(KEY_CHAPTER_TYPE, chapter.getChapterType()); if (chapter.getId() == 0) { chapter.setId(db.insert(TABLE_NAME_SIMPLECHAPTERS, null, values)); diff --git a/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSSimpleChapters.java b/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSSimpleChapters.java index 45266569a..5761f37c8 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSSimpleChapters.java +++ b/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSSimpleChapters.java @@ -22,12 +22,12 @@ public class NSSimpleChapters extends Namespace { private static final String START = "start"; private static final String TITLE = "title"; private static final String HREF = "href"; + private static final String IMAGE = "image"; @Override - public SyndElement handleElementStart(String localName, HandlerState state, - Attributes attributes) { + public SyndElement handleElementStart(String localName, HandlerState state, Attributes attributes) { FeedItem currentItem = state.getCurrentItem(); - if(currentItem != null) { + if (currentItem != null) { if (localName.equals(CHAPTERS)) { currentItem.setChapters(new ArrayList<>()); } else if (localName.equals(CHAPTER)) { @@ -35,7 +35,8 @@ public class NSSimpleChapters extends Namespace { long start = DateUtils.parseTimeString(attributes.getValue(START)); String title = attributes.getValue(TITLE); String link = attributes.getValue(HREF); - SimpleChapter chapter = new SimpleChapter(start, title, currentItem, link); + String imageUrl = attributes.getValue(IMAGE); + SimpleChapter chapter = new SimpleChapter(start, title, link, imageUrl); currentItem.getChapters().add(chapter); } catch (NumberFormatException e) { Log.e(TAG, "Unable to read chapter", e); -- cgit v1.2.3 From a980281d4794a867e9c972b53c87e6355182a916 Mon Sep 17 00:00:00 2001 From: ByteHamster Date: Mon, 10 Feb 2020 00:14:16 +0100 Subject: Added id3 chapter image reader --- .../core/util/id3reader/ChapterReader.java | 260 +++++++++++++-------- .../antennapod/core/util/id3reader/ID3Reader.java | 25 +- 2 files changed, 176 insertions(+), 109 deletions(-) (limited to 'core/src') diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/id3reader/ChapterReader.java b/core/src/main/java/de/danoeh/antennapod/core/util/id3reader/ChapterReader.java index a3f747e09..f7c5bfec7 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/id3reader/ChapterReader.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/id3reader/ChapterReader.java @@ -1,11 +1,17 @@ package de.danoeh.antennapod.core.util.id3reader; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.util.Base64; import android.util.Log; import de.danoeh.antennapod.core.feed.Chapter; import de.danoeh.antennapod.core.feed.ID3Chapter; +import de.danoeh.antennapod.core.preferences.UserPreferences; import de.danoeh.antennapod.core.util.id3reader.model.FrameHeader; import de.danoeh.antennapod.core.util.id3reader.model.TagHeader; +import java.io.File; +import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.net.URLDecoder; @@ -15,110 +21,158 @@ import java.util.List; public class ChapterReader extends ID3Reader { private static final String TAG = "ID3ChapterReader"; - private static final String FRAME_ID_CHAPTER = "CHAP"; - private static final String FRAME_ID_TITLE = "TIT2"; + private static final String FRAME_ID_CHAPTER = "CHAP"; + private static final String FRAME_ID_TITLE = "TIT2"; private static final String FRAME_ID_LINK = "WXXX"; - private List chapters; - private ID3Chapter currentChapter; - - @Override - public int onStartTagHeader(TagHeader header) { - chapters = new ArrayList<>(); - Log.d(TAG, "header: " + header); - return ID3Reader.ACTION_DONT_SKIP; - } - - @Override - public int onStartFrameHeader(FrameHeader header, InputStream input) - throws IOException, ID3ReaderException { - Log.d(TAG, "header: " + header); - switch (header.getId()) { - case FRAME_ID_CHAPTER: - if (currentChapter != null) { - if (!hasId3Chapter(currentChapter)) { - chapters.add(currentChapter); - Log.d(TAG, "Found chapter: " + currentChapter); - currentChapter = null; - } - } - StringBuilder elementId = new StringBuilder(); - readISOString(elementId, input, Integer.MAX_VALUE); - char[] startTimeSource = readBytes(input, 4); - long startTime = ((int) startTimeSource[0] << 24) - | ((int) startTimeSource[1] << 16) - | ((int) startTimeSource[2] << 8) | startTimeSource[3]; - currentChapter = new ID3Chapter(elementId.toString(), startTime); - skipBytes(input, 12); - return ID3Reader.ACTION_DONT_SKIP; - case FRAME_ID_TITLE: - if (currentChapter != null && currentChapter.getTitle() == null) { - StringBuilder title = new StringBuilder(); - readString(title, input, header.getSize()); - currentChapter - .setTitle(title.toString()); - Log.d(TAG, "Found title: " + currentChapter.getTitle()); - - return ID3Reader.ACTION_DONT_SKIP; - } - break; - case FRAME_ID_LINK: - if (currentChapter != null) { - // skip description - int descriptionLength = readString(null, input, header.getSize()); - StringBuilder link = new StringBuilder(); - readISOString(link, input, header.getSize() - descriptionLength); - try { - String decodedLink = URLDecoder.decode(link.toString(), "UTF-8"); - currentChapter.setLink(decodedLink); - Log.d(TAG, "Found link: " + currentChapter.getLink()); - } catch (IllegalArgumentException iae) { - Log.w(TAG, "Bad URL found in ID3 data"); - } - - return ID3Reader.ACTION_DONT_SKIP; - } - break; - case "APIC": - Log.d(TAG, header.toString()); - break; - } - - return super.onStartFrameHeader(header, input); - } - - private boolean hasId3Chapter(ID3Chapter chapter) { - for (Chapter c : chapters) { - if (((ID3Chapter) c).getId3ID().equals(chapter.getId3ID())) { - return true; - } - } - return false; - } - - @Override - public void onEndTag() { - if (currentChapter != null) { - if (!hasId3Chapter(currentChapter)) { - chapters.add(currentChapter); - } - } - Log.d(TAG, "Reached end of tag"); - if (chapters != null) { - for (Chapter c : chapters) { - Log.d(TAG, "chapter: " + c); - } - } - } - - @Override - public void onNoTagHeaderFound() { - Log.d(TAG, "No tag header found"); - super.onNoTagHeaderFound(); - } - - public List getChapters() { - return chapters; - } + private List chapters; + private ID3Chapter currentChapter; + + @Override + public int onStartTagHeader(TagHeader header) { + chapters = new ArrayList<>(); + Log.d(TAG, "header: " + header); + return ID3Reader.ACTION_DONT_SKIP; + } + + @Override + public int onStartFrameHeader(FrameHeader header, InputStream input) + throws IOException, ID3ReaderException { + Log.d(TAG, "header: " + header); + switch (header.getId()) { + case FRAME_ID_CHAPTER: + if (currentChapter != null) { + if (!hasId3Chapter(currentChapter)) { + chapters.add(currentChapter); + Log.d(TAG, "Found chapter: " + currentChapter); + currentChapter = null; + } + } + StringBuilder elementId = new StringBuilder(); + readISOString(elementId, input, Integer.MAX_VALUE); + char[] startTimeSource = readChars(input, 4); + long startTime = ((int) startTimeSource[0] << 24) + | ((int) startTimeSource[1] << 16) + | ((int) startTimeSource[2] << 8) | startTimeSource[3]; + currentChapter = new ID3Chapter(elementId.toString(), startTime); + skipBytes(input, 12); + return ID3Reader.ACTION_DONT_SKIP; + case FRAME_ID_TITLE: + if (currentChapter != null && currentChapter.getTitle() == null) { + StringBuilder title = new StringBuilder(); + readString(title, input, header.getSize()); + currentChapter + .setTitle(title.toString()); + Log.d(TAG, "Found title: " + currentChapter.getTitle()); + + return ID3Reader.ACTION_DONT_SKIP; + } + break; + case FRAME_ID_LINK: + if (currentChapter != null) { + // skip description + int descriptionLength = readString(null, input, header.getSize()); + StringBuilder link = new StringBuilder(); + readISOString(link, input, header.getSize() - descriptionLength); + try { + String decodedLink = URLDecoder.decode(link.toString(), "UTF-8"); + currentChapter.setLink(decodedLink); + Log.d(TAG, "Found link: " + currentChapter.getLink()); + } catch (IllegalArgumentException iae) { + Log.w(TAG, "Bad URL found in ID3 data"); + } + + return ID3Reader.ACTION_DONT_SKIP; + } + break; + case "APIC": + Log.d(TAG, header.toString()); + StringBuilder mime = new StringBuilder(); + int read = readString(mime, input, header.getSize()); + byte type = (byte) input.read(); + // $00 Other + // $01 32x32 pixels 'file icon' (PNG only) + // $02 Other file icon + // $03 Cover (front) + // $04 Cover (back) + // $05 Leaflet page + // $06 Media (e.g. label side of CD) + // $07 Lead artist/lead performer/soloist + // $08 Artist/performer + // $09 Conductor + // $0A Band/Orchestra + // $0B Composer + // $0C Lyricist/text writer + // $0D Recording Location + // $0E During recording + // $0F During performance + // $10 Movie/video screen capture + // $11 A bright coloured fish + // $12 Illustration + // $13 Band/artist logotype + // $14 Publisher/Studio logotype + read++; + StringBuilder description = new StringBuilder(); + read += readISOString(description, input, header.getSize()); // Should use encoding from first string + + + Log.d(TAG, "Found apic: " + mime + "," + description); + if (mime.toString().equals("-->")) { + // Data contains a link to a picture + StringBuilder link = new StringBuilder(); + readISOString(link, input, header.getSize()); + Log.d(TAG, "link: " + link); + } else { + // Data contains the picture + byte[] imageData = readBytes(input, header.getSize() - read); + + Bitmap bmp = BitmapFactory.decodeByteArray(imageData, 0, imageData.length); + try (FileOutputStream out = new FileOutputStream(new File(UserPreferences.getDataFolder(null), + "chapter" + chapters.size() + ".jpg"))) { + bmp.compress(Bitmap.CompressFormat.PNG, 100, out); // bmp is your Bitmap instance + // PNG is a lossless format, the compression factor (100) is ignored + } catch (IOException e) { + e.printStackTrace(); + } + } + return ID3Reader.ACTION_DONT_SKIP; + } + + return super.onStartFrameHeader(header, input); + } + + private boolean hasId3Chapter(ID3Chapter chapter) { + for (Chapter c : chapters) { + if (((ID3Chapter) c).getId3ID().equals(chapter.getId3ID())) { + return true; + } + } + return false; + } + + @Override + public void onEndTag() { + if (currentChapter != null) { + if (!hasId3Chapter(currentChapter)) { + chapters.add(currentChapter); + } + } + Log.d(TAG, "Reached end of tag"); + if (chapters != null) { + for (Chapter c : chapters) { + Log.d(TAG, "chapter: " + c); + } + } + } + + @Override + public void onNoTagHeaderFound() { + Log.d(TAG, "No tag header found"); + super.onNoTagHeaderFound(); + } + + public List getChapters() { + return chapters; + } } diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/id3reader/ID3Reader.java b/core/src/main/java/de/danoeh/antennapod/core/util/id3reader/ID3Reader.java index 3f5993700..85538d94c 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/id3reader/ID3Reader.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/id3reader/ID3Reader.java @@ -37,7 +37,7 @@ public class ID3Reader { ID3ReaderException { int rc; readerPosition = 0; - char[] tagHeaderSource = readBytes(input, HEADER_LENGTH); + char[] tagHeaderSource = readChars(input, HEADER_LENGTH); tagHeader = createTagHeader(tagHeaderSource); if (tagHeader == null) { onNoTagHeaderFound(); @@ -47,7 +47,7 @@ public class ID3Reader { onEndTag(); } else { while (readerPosition < tagHeader.getSize()) { - FrameHeader frameHeader = createFrameHeader(readBytes(input, HEADER_LENGTH)); + FrameHeader frameHeader = createFrameHeader(readChars(input, HEADER_LENGTH)); if (checkForNullString(frameHeader.getId())) { break; } @@ -84,11 +84,10 @@ public class ID3Reader { } /** - * Read a certain number of bytes from the given input stream. This method + * Read a certain number of chars from the given input stream. This method * changes the readerPosition-attribute. */ - char[] readBytes(InputStream input, int number) - throws IOException, ID3ReaderException { + char[] readChars(InputStream input, int number) throws IOException, ID3ReaderException { char[] header = new char[number]; for (int i = 0; i < number; i++) { int b = input.read(); @@ -102,6 +101,20 @@ public class ID3Reader { return header; } + byte[] readBytes(InputStream input, int number) throws IOException, ID3ReaderException { + byte[] header = new byte[number]; + for (int i = 0; i < number; i++) { + int b = input.read(); + readerPosition++; + if (b != -1) { + header[i] = (byte) b; + } else { + throw new ID3ReaderException("Unexpected end of stream"); + } + } + return header; + } + /** * Skip a certain number of bytes on the given input stream. This method * changes the readerPosition-attribute. @@ -168,7 +181,7 @@ public class ID3Reader { protected int readString(StringBuilder buffer, InputStream input, int max) throws IOException, ID3ReaderException { if (max > 0) { - char[] encoding = readBytes(input, 1); + char[] encoding = readChars(input, 1); max--; if (encoding[0] == ENCODING_UTF16_WITH_BOM || encoding[0] == ENCODING_UTF16_WITHOUT_BOM) { -- cgit v1.2.3 From 9497a97289d7d798a09d3a155b402fc9495693a8 Mon Sep 17 00:00:00 2001 From: ByteHamster Date: Mon, 10 Feb 2020 11:29:32 +0100 Subject: Store embedded chapter information --- .../de/danoeh/antennapod/core/feed/Chapter.java | 3 - .../danoeh/antennapod/core/util/ChapterUtils.java | 15 ++-- .../core/util/id3reader/ChapterReader.java | 92 ++++++++-------------- .../antennapod/core/util/id3reader/ID3Reader.java | 21 +---- 4 files changed, 45 insertions(+), 86 deletions(-) (limited to 'core/src') diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/Chapter.java b/core/src/main/java/de/danoeh/antennapod/core/feed/Chapter.java index 2af946c67..08a531d17 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/feed/Chapter.java +++ b/core/src/main/java/de/danoeh/antennapod/core/feed/Chapter.java @@ -2,11 +2,8 @@ package de.danoeh.antennapod.core.feed; import android.database.Cursor; -import android.text.TextUtils; import de.danoeh.antennapod.core.storage.PodDBAdapter; -import java.util.Objects; - public abstract class Chapter extends FeedComponent { /** Defines starting point in milliseconds. */ 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 300e0038a..e69bb2863 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 @@ -4,6 +4,7 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import android.util.Log; +import java.util.zip.CheckedOutputStream; import org.apache.commons.io.IOUtils; import java.io.BufferedInputStream; @@ -23,6 +24,7 @@ import de.danoeh.antennapod.core.util.id3reader.ID3ReaderException; import de.danoeh.antennapod.core.util.playback.Playable; import de.danoeh.antennapod.core.util.vorbiscommentreader.VorbisCommentChapterReader; import de.danoeh.antennapod.core.util.vorbiscommentreader.VorbisCommentReaderException; +import org.apache.commons.io.input.CountingInputStream; /** * Utility class for getting chapter data from media files. @@ -82,13 +84,12 @@ public class ChapterUtils { return; } Log.d(TAG, "Reading id3 chapters from item " + p.getEpisodeTitle()); - InputStream in = null; + CountingInputStream in = null; try { URL url = new URL(p.getStreamUrl()); - - in = url.openStream(); + in = new CountingInputStream(url.openStream()); List chapters = readChaptersFrom(in); - if(!chapters.isEmpty()) { + if (!chapters.isEmpty()) { p.setChapters(chapters); } Log.i(TAG, "Chapters loaded"); @@ -114,9 +115,9 @@ public class ChapterUtils { return; } - InputStream in = null; + CountingInputStream in = null; try { - in = new BufferedInputStream(new FileInputStream(source)); + in = new CountingInputStream(new BufferedInputStream(new FileInputStream(source))); List chapters = readChaptersFrom(in); if (!chapters.isEmpty()) { p.setChapters(chapters); @@ -130,7 +131,7 @@ public class ChapterUtils { } @NonNull - private static List readChaptersFrom(InputStream in) throws IOException, ID3ReaderException { + private static List readChaptersFrom(CountingInputStream in) throws IOException, ID3ReaderException { ChapterReader reader = new ChapterReader(); reader.readInputStream(in); List chapters = reader.getChapters(); diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/id3reader/ChapterReader.java b/core/src/main/java/de/danoeh/antennapod/core/util/id3reader/ChapterReader.java index f7c5bfec7..b007967c1 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/id3reader/ChapterReader.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/id3reader/ChapterReader.java @@ -1,22 +1,17 @@ package de.danoeh.antennapod.core.util.id3reader; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.util.Base64; +import android.text.TextUtils; import android.util.Log; import de.danoeh.antennapod.core.feed.Chapter; import de.danoeh.antennapod.core.feed.ID3Chapter; -import de.danoeh.antennapod.core.preferences.UserPreferences; import de.danoeh.antennapod.core.util.id3reader.model.FrameHeader; import de.danoeh.antennapod.core.util.id3reader.model.TagHeader; -import java.io.File; -import java.io.FileOutputStream; import java.io.IOException; -import java.io.InputStream; import java.net.URLDecoder; import java.util.ArrayList; import java.util.List; +import org.apache.commons.io.input.CountingInputStream; public class ChapterReader extends ID3Reader { private static final String TAG = "ID3ChapterReader"; @@ -24,6 +19,8 @@ public class ChapterReader extends ID3Reader { private static final String FRAME_ID_CHAPTER = "CHAP"; private static final String FRAME_ID_TITLE = "TIT2"; private static final String FRAME_ID_LINK = "WXXX"; + private static final String FRAME_ID_PICTURE = "APIC"; + private static final int IMAGE_TYPE_COVER = 3; private List chapters; private ID3Chapter currentChapter; @@ -36,8 +33,7 @@ public class ChapterReader extends ID3Reader { } @Override - public int onStartFrameHeader(FrameHeader header, InputStream input) - throws IOException, ID3ReaderException { + public int onStartFrameHeader(FrameHeader header, CountingInputStream input) throws IOException, ID3ReaderException { Log.d(TAG, "header: " + header); switch (header.getId()) { case FRAME_ID_CHAPTER: @@ -85,57 +81,37 @@ public class ChapterReader extends ID3Reader { return ID3Reader.ACTION_DONT_SKIP; } break; - case "APIC": - Log.d(TAG, header.toString()); - StringBuilder mime = new StringBuilder(); - int read = readString(mime, input, header.getSize()); - byte type = (byte) input.read(); - // $00 Other - // $01 32x32 pixels 'file icon' (PNG only) - // $02 Other file icon - // $03 Cover (front) - // $04 Cover (back) - // $05 Leaflet page - // $06 Media (e.g. label side of CD) - // $07 Lead artist/lead performer/soloist - // $08 Artist/performer - // $09 Conductor - // $0A Band/Orchestra - // $0B Composer - // $0C Lyricist/text writer - // $0D Recording Location - // $0E During recording - // $0F During performance - // $10 Movie/video screen capture - // $11 A bright coloured fish - // $12 Illustration - // $13 Band/artist logotype - // $14 Publisher/Studio logotype - read++; - StringBuilder description = new StringBuilder(); - read += readISOString(description, input, header.getSize()); // Should use encoding from first string - - - Log.d(TAG, "Found apic: " + mime + "," + description); - if (mime.toString().equals("-->")) { - // Data contains a link to a picture - StringBuilder link = new StringBuilder(); - readISOString(link, input, header.getSize()); - Log.d(TAG, "link: " + link); - } else { - // Data contains the picture - byte[] imageData = readBytes(input, header.getSize() - read); - - Bitmap bmp = BitmapFactory.decodeByteArray(imageData, 0, imageData.length); - try (FileOutputStream out = new FileOutputStream(new File(UserPreferences.getDataFolder(null), - "chapter" + chapters.size() + ".jpg"))) { - bmp.compress(Bitmap.CompressFormat.PNG, 100, out); // bmp is your Bitmap instance - // PNG is a lossless format, the compression factor (100) is ignored - } catch (IOException e) { - e.printStackTrace(); + case FRAME_ID_PICTURE: + if (currentChapter != null) { + Log.d(TAG, header.toString()); + StringBuilder mime = new StringBuilder(); + int read = readString(mime, input, header.getSize()); + byte type = (byte) readChars(input, 1)[0]; + read++; + StringBuilder description = new StringBuilder(); + read += readISOString(description, input, header.getSize()); // Should use same encoding as mime + + Log.d(TAG, "Found apic: " + mime + "," + description); + if (mime.toString().equals("-->")) { + // Data contains a link to a picture + StringBuilder link = new StringBuilder(); + readISOString(link, input, header.getSize()); + Log.d(TAG, "link: " + link.toString()); + if (TextUtils.isEmpty(currentChapter.getImageUrl()) || type == IMAGE_TYPE_COVER) { + currentChapter.setImageUrl(link.toString()); + } + } else { + // Data contains the picture + int length = header.getSize() - read; + if (TextUtils.isEmpty(currentChapter.getImageUrl()) || type == IMAGE_TYPE_COVER) { + currentChapter.setImageUrl("embedded-image://" + mime.toString() + + "@" + input.getByteCount() + ":" + length); + } + skipBytes(input, length); } + return ID3Reader.ACTION_DONT_SKIP; } - return ID3Reader.ACTION_DONT_SKIP; + break; } return super.onStartFrameHeader(header, input); diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/id3reader/ID3Reader.java b/core/src/main/java/de/danoeh/antennapod/core/util/id3reader/ID3Reader.java index 85538d94c..dfc21a5f2 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/id3reader/ID3Reader.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/id3reader/ID3Reader.java @@ -9,6 +9,7 @@ import java.nio.charset.Charset; import de.danoeh.antennapod.core.util.id3reader.model.FrameHeader; import de.danoeh.antennapod.core.util.id3reader.model.TagHeader; +import org.apache.commons.io.input.CountingInputStream; /** * Reads the ID3 Tag of a given file. In order to use this class, you should @@ -33,8 +34,7 @@ public class ID3Reader { ID3Reader() { } - public final void readInputStream(InputStream input) throws IOException, - ID3ReaderException { + public final void readInputStream(CountingInputStream input) throws IOException, ID3ReaderException { int rc; readerPosition = 0; char[] tagHeaderSource = readChars(input, HEADER_LENGTH); @@ -101,20 +101,6 @@ public class ID3Reader { return header; } - byte[] readBytes(InputStream input, int number) throws IOException, ID3ReaderException { - byte[] header = new byte[number]; - for (int i = 0; i < number; i++) { - int b = input.read(); - readerPosition++; - if (b != -1) { - header[i] = (byte) b; - } else { - throw new ID3ReaderException("Unexpected end of stream"); - } - } - return header; - } - /** * Skip a certain number of bytes on the given input stream. This method * changes the readerPosition-attribute. @@ -243,8 +229,7 @@ public class ID3Reader { return ACTION_SKIP; } - int onStartFrameHeader(FrameHeader header, InputStream input) - throws IOException, ID3ReaderException { + int onStartFrameHeader(FrameHeader header, CountingInputStream input) throws IOException, ID3ReaderException { return ACTION_SKIP; } -- cgit v1.2.3 From 312cb845981466b2c1464e0b6227dfafe9848b2c Mon Sep 17 00:00:00 2001 From: ByteHamster Date: Mon, 10 Feb 2020 12:27:09 +0100 Subject: Added ChapterImageModelLoader --- .../antennapod/core/glide/ApGlideModule.java | 3 + .../core/glide/ChapterImageModelLoader.java | 98 ++++++++++++++++++++++ .../danoeh/antennapod/core/util/ChapterUtils.java | 21 ++--- .../antennapod/core/util/EmbeddedChapterImage.java | 58 +++++++++++++ .../core/util/id3reader/ChapterReader.java | 5 +- 5 files changed, 169 insertions(+), 16 deletions(-) create mode 100644 core/src/main/java/de/danoeh/antennapod/core/glide/ChapterImageModelLoader.java create mode 100644 core/src/main/java/de/danoeh/antennapod/core/util/EmbeddedChapterImage.java (limited to 'core/src') diff --git a/core/src/main/java/de/danoeh/antennapod/core/glide/ApGlideModule.java b/core/src/main/java/de/danoeh/antennapod/core/glide/ApGlideModule.java index b2c809e90..50511526f 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/glide/ApGlideModule.java +++ b/core/src/main/java/de/danoeh/antennapod/core/glide/ApGlideModule.java @@ -11,10 +11,12 @@ import com.bumptech.glide.load.DecodeFormat; import com.bumptech.glide.load.engine.cache.InternalCacheDiskCacheFactory; import com.bumptech.glide.module.AppGlideModule; +import de.danoeh.antennapod.core.util.EmbeddedChapterImage; import java.io.InputStream; import com.bumptech.glide.request.RequestOptions; import de.danoeh.antennapod.core.preferences.UserPreferences; +import java.nio.ByteBuffer; /** * {@see com.bumptech.glide.integration.okhttp.OkHttpGlideModule} @@ -32,5 +34,6 @@ public class ApGlideModule extends AppGlideModule { @Override public void registerComponents(@NonNull Context context, @NonNull Glide glide, @NonNull Registry registry) { registry.replace(String.class, InputStream.class, new ApOkHttpUrlLoader.Factory()); + registry.append(EmbeddedChapterImage.class, ByteBuffer.class, new ChapterImageModelLoader.Factory()); } } diff --git a/core/src/main/java/de/danoeh/antennapod/core/glide/ChapterImageModelLoader.java b/core/src/main/java/de/danoeh/antennapod/core/glide/ChapterImageModelLoader.java new file mode 100644 index 000000000..6548e9c5e --- /dev/null +++ b/core/src/main/java/de/danoeh/antennapod/core/glide/ChapterImageModelLoader.java @@ -0,0 +1,98 @@ +package de.danoeh.antennapod.core.glide; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import com.bumptech.glide.Priority; +import com.bumptech.glide.load.DataSource; +import com.bumptech.glide.load.Options; +import com.bumptech.glide.load.data.DataFetcher; +import com.bumptech.glide.load.model.ModelLoader; +import com.bumptech.glide.load.model.ModelLoaderFactory; +import com.bumptech.glide.load.model.MultiModelLoaderFactory; +import com.bumptech.glide.signature.ObjectKey; +import de.danoeh.antennapod.core.feed.Chapter; +import de.danoeh.antennapod.core.util.EmbeddedChapterImage; +import java.io.BufferedInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.net.URL; +import java.nio.ByteBuffer; +import org.apache.commons.io.IOUtils; + +public final class ChapterImageModelLoader implements ModelLoader { + + public static class Factory implements ModelLoaderFactory { + @Override + public ModelLoader build(MultiModelLoaderFactory unused) { + return new ChapterImageModelLoader(); + } + + @Override + public void teardown() { + // Do nothing. + } + } + + @Nullable + @Override + public LoadData buildLoadData(EmbeddedChapterImage model, int width, int height, Options options) { + return new LoadData<>(new ObjectKey(model), new EmbeddedImageFetcher(model)); + } + + @Override + public boolean handles(EmbeddedChapterImage model) { + return true; + } + + class EmbeddedImageFetcher implements DataFetcher { + private final EmbeddedChapterImage image; + + public EmbeddedImageFetcher(EmbeddedChapterImage image) { + this.image = image; + } + + @Override + public void loadData(@NonNull Priority priority, @NonNull DataCallback callback) { + + BufferedInputStream stream = null; + try { + if (image.getMedia().localFileAvailable()) { + File localFile = new File(image.getMedia().getLocalMediaUrl()); + stream = new BufferedInputStream(new FileInputStream(localFile)); + } else { + URL url = new URL(image.getMedia().getStreamUrl()); + stream = new BufferedInputStream(url.openStream()); + } + byte[] imageContent = new byte[image.getLength()]; + stream.skip(image.getPosition()); + stream.read(imageContent, 0, image.getLength()); + callback.onDataReady(ByteBuffer.wrap(imageContent)); + } catch (IOException e) { + callback.onLoadFailed(new IOException("Loading embedded cover did not work")); + e.printStackTrace(); + } finally { + IOUtils.closeQuietly(stream); + } + } + + @Override public void cleanup() { + // nothing to clean up + } + @Override public void cancel() { + // cannot cancel + } + + @NonNull + @Override + public Class getDataClass() { + return ByteBuffer.class; + } + + @NonNull + @Override + public DataSource getDataSource() { + return DataSource.LOCAL; + } + } +} 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 e69bb2863..b75887154 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 @@ -36,24 +36,17 @@ public class ChapterUtils { private ChapterUtils() { } - @Nullable - public static Chapter getCurrentChapter(Playable media) { - if (media.getChapters() == null) { - return null; + public static int getCurrentChapterIndex(Playable media, int position) { + if (media == null || media.getChapters() == null || media.getChapters().size() == 0) { + return -1; } List chapters = media.getChapters(); - if (chapters == null) { - return null; - } - Chapter current = chapters.get(0); - for (Chapter sc : chapters) { - if (sc.getStart() > media.getPosition()) { - break; - } else { - current = sc; + for (int i = 0; i < chapters.size(); i++) { + if (chapters.get(i).getStart() > position) { + return i - 1; } } - return current; + return chapters.size() - 1; } public static void loadChaptersFromStreamUrl(Playable media) { diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/EmbeddedChapterImage.java b/core/src/main/java/de/danoeh/antennapod/core/util/EmbeddedChapterImage.java new file mode 100644 index 000000000..5cb62e6c2 --- /dev/null +++ b/core/src/main/java/de/danoeh/antennapod/core/util/EmbeddedChapterImage.java @@ -0,0 +1,58 @@ +package de.danoeh.antennapod.core.util; + +import de.danoeh.antennapod.core.util.playback.Playable; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class EmbeddedChapterImage { + private static final Pattern EMBEDDED_IMAGE_MATCHER = Pattern.compile("embedded-image://(.*)@(\\d+):(\\d+)"); + final String mime; + final int position; + final int length; + final Playable media; + + public EmbeddedChapterImage(Playable media, String imageUrl) { + this.media = media; + Matcher m = EMBEDDED_IMAGE_MATCHER.matcher(imageUrl); + if (m.find()) { + this.mime = m.group(1); + this.position = Integer.parseInt(m.group(2)); + this.length = Integer.parseInt(m.group(3)); + } else { + throw new IllegalArgumentException("Not an embedded chapter"); + } + } + + public static String makeUrl(String mime, int position, int length) { + return "embedded-image://" + mime + "@" + position + ":" + length; + } + + public String getMime() { + return mime; + } + + public int getPosition() { + return position; + } + + public int getLength() { + return length; + } + + public Playable getMedia() { + return media; + } + + private static boolean isEmbeddedChapterImage(String imageUrl) { + return EMBEDDED_IMAGE_MATCHER.matcher(imageUrl).matches(); + } + + public static Object getModelFor(Playable media, int chapter) { + String imageUrl = media.getChapters().get(chapter).getImageUrl(); + if (isEmbeddedChapterImage(imageUrl)) { + return new EmbeddedChapterImage(media, imageUrl); + } else { + return imageUrl; + } + } +} diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/id3reader/ChapterReader.java b/core/src/main/java/de/danoeh/antennapod/core/util/id3reader/ChapterReader.java index b007967c1..934e0b00c 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/id3reader/ChapterReader.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/id3reader/ChapterReader.java @@ -4,6 +4,7 @@ import android.text.TextUtils; import android.util.Log; import de.danoeh.antennapod.core.feed.Chapter; import de.danoeh.antennapod.core.feed.ID3Chapter; +import de.danoeh.antennapod.core.util.EmbeddedChapterImage; import de.danoeh.antennapod.core.util.id3reader.model.FrameHeader; import de.danoeh.antennapod.core.util.id3reader.model.TagHeader; @@ -104,8 +105,8 @@ public class ChapterReader extends ID3Reader { // Data contains the picture int length = header.getSize() - read; if (TextUtils.isEmpty(currentChapter.getImageUrl()) || type == IMAGE_TYPE_COVER) { - currentChapter.setImageUrl("embedded-image://" + mime.toString() - + "@" + input.getByteCount() + ":" + length); + currentChapter.setImageUrl( + EmbeddedChapterImage.makeUrl(mime.toString(), input.getCount(), length)); } skipBytes(input, length); } -- cgit v1.2.3 From 419077043effff901729dcb875bc753b77ad680a Mon Sep 17 00:00:00 2001 From: ByteHamster Date: Wed, 12 Feb 2020 17:31:27 +0100 Subject: Fixed Glide not caching chapter images --- .../antennapod/core/util/EmbeddedChapterImage.java | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'core/src') diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/EmbeddedChapterImage.java b/core/src/main/java/de/danoeh/antennapod/core/util/EmbeddedChapterImage.java index 5cb62e6c2..ac55d0cfd 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/EmbeddedChapterImage.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/EmbeddedChapterImage.java @@ -1,6 +1,8 @@ package de.danoeh.antennapod.core.util; +import android.text.TextUtils; import de.danoeh.antennapod.core.util.playback.Playable; +import java.util.Objects; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -9,10 +11,12 @@ public class EmbeddedChapterImage { final String mime; final int position; final int length; + private final String imageUrl; final Playable media; public EmbeddedChapterImage(Playable media, String imageUrl) { this.media = media; + this.imageUrl = imageUrl; Matcher m = EMBEDDED_IMAGE_MATCHER.matcher(imageUrl); if (m.find()) { this.mime = m.group(1); @@ -43,6 +47,23 @@ public class EmbeddedChapterImage { return media; } + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + EmbeddedChapterImage that = (EmbeddedChapterImage) o; + return TextUtils.equals(imageUrl, that.imageUrl); + } + + @Override + public int hashCode() { + return imageUrl.hashCode(); + } + private static boolean isEmbeddedChapterImage(String imageUrl) { return EMBEDDED_IMAGE_MATCHER.matcher(imageUrl).matches(); } -- cgit v1.2.3 From d4948f91a1e38e64614d226a024c219acbceff22 Mon Sep 17 00:00:00 2001 From: ByteHamster Date: Wed, 12 Feb 2020 17:35:09 +0100 Subject: Removed mime type --- .../antennapod/core/util/EmbeddedChapterImage.java | 24 ++++++++-------------- .../core/util/id3reader/ChapterReader.java | 3 +-- 2 files changed, 10 insertions(+), 17 deletions(-) (limited to 'core/src') diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/EmbeddedChapterImage.java b/core/src/main/java/de/danoeh/antennapod/core/util/EmbeddedChapterImage.java index ac55d0cfd..deeba9238 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/EmbeddedChapterImage.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/EmbeddedChapterImage.java @@ -2,37 +2,31 @@ package de.danoeh.antennapod.core.util; import android.text.TextUtils; import de.danoeh.antennapod.core.util.playback.Playable; -import java.util.Objects; import java.util.regex.Matcher; import java.util.regex.Pattern; public class EmbeddedChapterImage { - private static final Pattern EMBEDDED_IMAGE_MATCHER = Pattern.compile("embedded-image://(.*)@(\\d+):(\\d+)"); - final String mime; - final int position; - final int length; + private static final Pattern EMBEDDED_IMAGE_MATCHER = Pattern.compile("embedded-image://(\\d+)/(\\d+)"); + + private final int position; + private final int length; private final String imageUrl; - final Playable media; + private final Playable media; public EmbeddedChapterImage(Playable media, String imageUrl) { this.media = media; this.imageUrl = imageUrl; Matcher m = EMBEDDED_IMAGE_MATCHER.matcher(imageUrl); if (m.find()) { - this.mime = m.group(1); - this.position = Integer.parseInt(m.group(2)); - this.length = Integer.parseInt(m.group(3)); + this.position = Integer.parseInt(m.group(1)); + this.length = Integer.parseInt(m.group(2)); } else { throw new IllegalArgumentException("Not an embedded chapter"); } } - public static String makeUrl(String mime, int position, int length) { - return "embedded-image://" + mime + "@" + position + ":" + length; - } - - public String getMime() { - return mime; + public static String makeUrl(int position, int length) { + return "embedded-image://" + position + "/" + length; } public int getPosition() { diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/id3reader/ChapterReader.java b/core/src/main/java/de/danoeh/antennapod/core/util/id3reader/ChapterReader.java index 934e0b00c..ce3577a9e 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/id3reader/ChapterReader.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/id3reader/ChapterReader.java @@ -105,8 +105,7 @@ public class ChapterReader extends ID3Reader { // Data contains the picture int length = header.getSize() - read; if (TextUtils.isEmpty(currentChapter.getImageUrl()) || type == IMAGE_TYPE_COVER) { - currentChapter.setImageUrl( - EmbeddedChapterImage.makeUrl(mime.toString(), input.getCount(), length)); + currentChapter.setImageUrl(EmbeddedChapterImage.makeUrl(input.getCount(), length)); } skipBytes(input, length); } -- cgit v1.2.3 From ddfb4de9cff67bd33a600a34cb2333fb0c9f6fc2 Mon Sep 17 00:00:00 2001 From: ByteHamster Date: Wed, 12 Feb 2020 18:09:25 +0100 Subject: Load range only --- .../core/glide/ChapterImageModelLoader.java | 31 +++++++++++++++------- 1 file changed, 22 insertions(+), 9 deletions(-) (limited to 'core/src') diff --git a/core/src/main/java/de/danoeh/antennapod/core/glide/ChapterImageModelLoader.java b/core/src/main/java/de/danoeh/antennapod/core/glide/ChapterImageModelLoader.java index 6548e9c5e..bc0a06a07 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/glide/ChapterImageModelLoader.java +++ b/core/src/main/java/de/danoeh/antennapod/core/glide/ChapterImageModelLoader.java @@ -10,7 +10,9 @@ import com.bumptech.glide.load.model.ModelLoader; import com.bumptech.glide.load.model.ModelLoaderFactory; import com.bumptech.glide.load.model.MultiModelLoaderFactory; import com.bumptech.glide.signature.ObjectKey; +import de.danoeh.antennapod.core.ClientConfig; import de.danoeh.antennapod.core.feed.Chapter; +import de.danoeh.antennapod.core.service.download.AntennapodHttpClient; import de.danoeh.antennapod.core.util.EmbeddedChapterImage; import java.io.BufferedInputStream; import java.io.File; @@ -18,6 +20,9 @@ import java.io.FileInputStream; import java.io.IOException; import java.net.URL; import java.nio.ByteBuffer; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.Response; import org.apache.commons.io.IOUtils; public final class ChapterImageModelLoader implements ModelLoader { @@ -45,7 +50,7 @@ public final class ChapterImageModelLoader implements ModelLoader { + static class EmbeddedImageFetcher implements DataFetcher { private final EmbeddedChapterImage image; public EmbeddedImageFetcher(EmbeddedChapterImage image) { @@ -60,17 +65,25 @@ public final class ChapterImageModelLoader implements ModelLoader Date: Wed, 12 Feb 2020 14:18:02 +0100 Subject: Replaced images with vector version --- .../core/service/PlayerWidgetJobService.java | 7 +++-- .../core/util/playback/PlaybackController.java | 16 +++++------ .../drawable-hdpi/ic_fast_forward_grey600_24dp.png | Bin 256 -> 0 bytes .../drawable-hdpi/ic_fast_forward_grey600_36dp.png | Bin 324 -> 0 bytes .../drawable-hdpi/ic_fast_forward_white_24dp.png | Bin 253 -> 0 bytes .../drawable-hdpi/ic_fast_forward_white_36dp.png | Bin 315 -> 0 bytes .../drawable-hdpi/ic_fast_rewind_grey600_24dp.png | Bin 267 -> 0 bytes .../drawable-hdpi/ic_fast_rewind_grey600_36dp.png | Bin 331 -> 0 bytes .../drawable-hdpi/ic_fast_rewind_white_24dp.png | Bin 261 -> 0 bytes .../drawable-hdpi/ic_fast_rewind_white_36dp.png | Bin 321 -> 0 bytes .../res/drawable-hdpi/ic_pause_grey600_24dp.png | Bin 103 -> 0 bytes .../res/drawable-hdpi/ic_pause_grey600_36dp.png | Bin 126 -> 0 bytes .../main/res/drawable-hdpi/ic_pause_white_24dp.png | Bin 103 -> 0 bytes .../main/res/drawable-hdpi/ic_pause_white_36dp.png | Bin 124 -> 0 bytes .../drawable-hdpi/ic_play_arrow_grey600_24dp.png | Bin 195 -> 0 bytes .../drawable-hdpi/ic_play_arrow_grey600_36dp.png | Bin 235 -> 0 bytes .../res/drawable-hdpi/ic_play_arrow_white_24dp.png | Bin 194 -> 0 bytes .../res/drawable-hdpi/ic_play_arrow_white_36dp.png | Bin 232 -> 0 bytes .../res/drawable-hdpi/ic_skip_grey600_36dp.png | Bin 256 -> 0 bytes .../main/res/drawable-hdpi/ic_skip_white_36dp.png | Bin 251 -> 0 bytes .../drawable-mdpi/ic_fast_forward_grey600_24dp.png | Bin 162 -> 0 bytes .../drawable-mdpi/ic_fast_forward_grey600_36dp.png | Bin 256 -> 0 bytes .../drawable-mdpi/ic_fast_forward_white_24dp.png | Bin 163 -> 0 bytes .../drawable-mdpi/ic_fast_forward_white_36dp.png | Bin 253 -> 0 bytes .../drawable-mdpi/ic_fast_rewind_grey600_24dp.png | Bin 167 -> 0 bytes .../drawable-mdpi/ic_fast_rewind_grey600_36dp.png | Bin 267 -> 0 bytes .../drawable-mdpi/ic_fast_rewind_white_24dp.png | Bin 162 -> 0 bytes .../drawable-mdpi/ic_fast_rewind_white_36dp.png | Bin 261 -> 0 bytes .../res/drawable-mdpi/ic_pause_grey600_24dp.png | Bin 84 -> 0 bytes .../res/drawable-mdpi/ic_pause_grey600_36dp.png | Bin 103 -> 0 bytes .../main/res/drawable-mdpi/ic_pause_white_24dp.png | Bin 83 -> 0 bytes .../main/res/drawable-mdpi/ic_pause_white_36dp.png | Bin 103 -> 0 bytes .../drawable-mdpi/ic_play_arrow_grey600_24dp.png | Bin 151 -> 0 bytes .../drawable-mdpi/ic_play_arrow_grey600_36dp.png | Bin 195 -> 0 bytes .../res/drawable-mdpi/ic_play_arrow_white_24dp.png | Bin 154 -> 0 bytes .../res/drawable-mdpi/ic_play_arrow_white_36dp.png | Bin 194 -> 0 bytes .../res/drawable-mdpi/ic_skip_grey600_36dp.png | Bin 183 -> 0 bytes .../main/res/drawable-mdpi/ic_skip_white_36dp.png | Bin 183 -> 0 bytes .../ic_fast_forward_grey600_24dp.png | Bin 252 -> 0 bytes .../ic_fast_forward_grey600_36dp.png | Bin 332 -> 0 bytes .../drawable-xhdpi/ic_fast_forward_white_24dp.png | Bin 253 -> 0 bytes .../drawable-xhdpi/ic_fast_forward_white_36dp.png | Bin 327 -> 0 bytes .../drawable-xhdpi/ic_fast_rewind_grey600_24dp.png | Bin 279 -> 0 bytes .../drawable-xhdpi/ic_fast_rewind_grey600_36dp.png | Bin 348 -> 0 bytes .../drawable-xhdpi/ic_fast_rewind_white_24dp.png | Bin 263 -> 0 bytes .../drawable-xhdpi/ic_fast_rewind_white_36dp.png | Bin 331 -> 0 bytes .../res/drawable-xhdpi/ic_pause_grey600_24dp.png | Bin 105 -> 0 bytes .../res/drawable-xhdpi/ic_pause_grey600_36dp.png | Bin 109 -> 0 bytes .../res/drawable-xhdpi/ic_pause_white_24dp.png | Bin 90 -> 0 bytes .../res/drawable-xhdpi/ic_pause_white_36dp.png | Bin 92 -> 0 bytes .../drawable-xhdpi/ic_play_arrow_grey600_24dp.png | Bin 211 -> 0 bytes .../drawable-xhdpi/ic_play_arrow_grey600_36dp.png | Bin 270 -> 0 bytes .../drawable-xhdpi/ic_play_arrow_white_24dp.png | Bin 206 -> 0 bytes .../drawable-xhdpi/ic_play_arrow_white_36dp.png | Bin 270 -> 0 bytes .../res/drawable-xhdpi/ic_skip_grey600_36dp.png | Bin 285 -> 0 bytes .../main/res/drawable-xhdpi/ic_skip_white_36dp.png | Bin 285 -> 0 bytes .../ic_fast_forward_grey600_24dp.png | Bin 332 -> 0 bytes .../ic_fast_forward_grey600_36dp.png | Bin 520 -> 0 bytes .../drawable-xxhdpi/ic_fast_forward_white_24dp.png | Bin 327 -> 0 bytes .../drawable-xxhdpi/ic_fast_forward_white_36dp.png | Bin 518 -> 0 bytes .../ic_fast_rewind_grey600_24dp.png | Bin 348 -> 0 bytes .../ic_fast_rewind_grey600_36dp.png | Bin 547 -> 0 bytes .../drawable-xxhdpi/ic_fast_rewind_white_24dp.png | Bin 331 -> 0 bytes .../drawable-xxhdpi/ic_fast_rewind_white_36dp.png | Bin 548 -> 0 bytes .../res/drawable-xxhdpi/ic_pause_grey600_24dp.png | Bin 109 -> 0 bytes .../res/drawable-xxhdpi/ic_pause_grey600_36dp.png | Bin 143 -> 0 bytes .../res/drawable-xxhdpi/ic_pause_white_24dp.png | Bin 92 -> 0 bytes .../res/drawable-xxhdpi/ic_pause_white_36dp.png | Bin 143 -> 0 bytes .../drawable-xxhdpi/ic_play_arrow_grey600_24dp.png | Bin 270 -> 0 bytes .../drawable-xxhdpi/ic_play_arrow_grey600_36dp.png | Bin 367 -> 0 bytes .../drawable-xxhdpi/ic_play_arrow_white_24dp.png | Bin 270 -> 0 bytes .../drawable-xxhdpi/ic_play_arrow_white_36dp.png | Bin 351 -> 0 bytes .../res/drawable-xxhdpi/ic_skip_grey600_36dp.png | Bin 369 -> 0 bytes .../res/drawable-xxhdpi/ic_skip_white_36dp.png | Bin 361 -> 0 bytes .../res/drawable-xxxhdpi/ic_skip_grey600_36dp.png | Bin 443 -> 0 bytes .../res/drawable-xxxhdpi/ic_skip_white_36dp.png | Bin 433 -> 0 bytes .../res/drawable/ic_av_fast_forward_dark_48dp.xml | 7 +++++ .../res/drawable/ic_av_fast_forward_white_48dp.xml | 7 +++++ .../res/drawable/ic_av_fast_rewind_dark_48dp.xml | 7 +++++ .../res/drawable/ic_av_fast_rewind_white_48dp.xml | 7 +++++ .../main/res/drawable/ic_av_pause_dark_48dp.xml | 7 +++++ .../main/res/drawable/ic_av_pause_white_48dp.xml | 7 +++++ .../src/main/res/drawable/ic_av_play_dark_24dp.xml | 7 +++++ .../src/main/res/drawable/ic_av_play_dark_48dp.xml | 7 +++++ .../main/res/drawable/ic_av_play_white_24dp.xml | 7 +++++ .../main/res/drawable/ic_av_play_white_48dp.xml | 7 +++++ .../src/main/res/drawable/ic_av_skip_dark_48dp.xml | 7 +++++ .../main/res/drawable/ic_av_skip_white_48dp.xml | 7 +++++ core/src/main/res/layout/player_widget.xml | 6 +++-- core/src/main/res/values/attrs.xml | 7 ++--- core/src/main/res/values/styles.xml | 30 +++++++++------------ 91 files changed, 111 insertions(+), 39 deletions(-) delete mode 100644 core/src/main/res/drawable-hdpi/ic_fast_forward_grey600_24dp.png delete mode 100644 core/src/main/res/drawable-hdpi/ic_fast_forward_grey600_36dp.png delete mode 100644 core/src/main/res/drawable-hdpi/ic_fast_forward_white_24dp.png delete mode 100644 core/src/main/res/drawable-hdpi/ic_fast_forward_white_36dp.png delete mode 100644 core/src/main/res/drawable-hdpi/ic_fast_rewind_grey600_24dp.png delete mode 100644 core/src/main/res/drawable-hdpi/ic_fast_rewind_grey600_36dp.png delete mode 100644 core/src/main/res/drawable-hdpi/ic_fast_rewind_white_24dp.png delete mode 100644 core/src/main/res/drawable-hdpi/ic_fast_rewind_white_36dp.png delete mode 100644 core/src/main/res/drawable-hdpi/ic_pause_grey600_24dp.png delete mode 100644 core/src/main/res/drawable-hdpi/ic_pause_grey600_36dp.png delete mode 100644 core/src/main/res/drawable-hdpi/ic_pause_white_24dp.png delete mode 100644 core/src/main/res/drawable-hdpi/ic_pause_white_36dp.png delete mode 100644 core/src/main/res/drawable-hdpi/ic_play_arrow_grey600_24dp.png delete mode 100644 core/src/main/res/drawable-hdpi/ic_play_arrow_grey600_36dp.png delete mode 100644 core/src/main/res/drawable-hdpi/ic_play_arrow_white_24dp.png delete mode 100644 core/src/main/res/drawable-hdpi/ic_play_arrow_white_36dp.png delete mode 100644 core/src/main/res/drawable-hdpi/ic_skip_grey600_36dp.png delete mode 100644 core/src/main/res/drawable-hdpi/ic_skip_white_36dp.png delete mode 100644 core/src/main/res/drawable-mdpi/ic_fast_forward_grey600_24dp.png delete mode 100644 core/src/main/res/drawable-mdpi/ic_fast_forward_grey600_36dp.png delete mode 100644 core/src/main/res/drawable-mdpi/ic_fast_forward_white_24dp.png delete mode 100644 core/src/main/res/drawable-mdpi/ic_fast_forward_white_36dp.png delete mode 100644 core/src/main/res/drawable-mdpi/ic_fast_rewind_grey600_24dp.png delete mode 100644 core/src/main/res/drawable-mdpi/ic_fast_rewind_grey600_36dp.png delete mode 100644 core/src/main/res/drawable-mdpi/ic_fast_rewind_white_24dp.png delete mode 100644 core/src/main/res/drawable-mdpi/ic_fast_rewind_white_36dp.png delete mode 100644 core/src/main/res/drawable-mdpi/ic_pause_grey600_24dp.png delete mode 100644 core/src/main/res/drawable-mdpi/ic_pause_grey600_36dp.png delete mode 100644 core/src/main/res/drawable-mdpi/ic_pause_white_24dp.png delete mode 100644 core/src/main/res/drawable-mdpi/ic_pause_white_36dp.png delete mode 100644 core/src/main/res/drawable-mdpi/ic_play_arrow_grey600_24dp.png delete mode 100644 core/src/main/res/drawable-mdpi/ic_play_arrow_grey600_36dp.png delete mode 100644 core/src/main/res/drawable-mdpi/ic_play_arrow_white_24dp.png delete mode 100644 core/src/main/res/drawable-mdpi/ic_play_arrow_white_36dp.png delete mode 100644 core/src/main/res/drawable-mdpi/ic_skip_grey600_36dp.png delete mode 100644 core/src/main/res/drawable-mdpi/ic_skip_white_36dp.png delete mode 100644 core/src/main/res/drawable-xhdpi/ic_fast_forward_grey600_24dp.png delete mode 100644 core/src/main/res/drawable-xhdpi/ic_fast_forward_grey600_36dp.png delete mode 100644 core/src/main/res/drawable-xhdpi/ic_fast_forward_white_24dp.png delete mode 100644 core/src/main/res/drawable-xhdpi/ic_fast_forward_white_36dp.png delete mode 100644 core/src/main/res/drawable-xhdpi/ic_fast_rewind_grey600_24dp.png delete mode 100644 core/src/main/res/drawable-xhdpi/ic_fast_rewind_grey600_36dp.png delete mode 100644 core/src/main/res/drawable-xhdpi/ic_fast_rewind_white_24dp.png delete mode 100644 core/src/main/res/drawable-xhdpi/ic_fast_rewind_white_36dp.png delete mode 100644 core/src/main/res/drawable-xhdpi/ic_pause_grey600_24dp.png delete mode 100644 core/src/main/res/drawable-xhdpi/ic_pause_grey600_36dp.png delete mode 100644 core/src/main/res/drawable-xhdpi/ic_pause_white_24dp.png delete mode 100644 core/src/main/res/drawable-xhdpi/ic_pause_white_36dp.png delete mode 100644 core/src/main/res/drawable-xhdpi/ic_play_arrow_grey600_24dp.png delete mode 100644 core/src/main/res/drawable-xhdpi/ic_play_arrow_grey600_36dp.png delete mode 100644 core/src/main/res/drawable-xhdpi/ic_play_arrow_white_24dp.png delete mode 100644 core/src/main/res/drawable-xhdpi/ic_play_arrow_white_36dp.png delete mode 100644 core/src/main/res/drawable-xhdpi/ic_skip_grey600_36dp.png delete mode 100644 core/src/main/res/drawable-xhdpi/ic_skip_white_36dp.png delete mode 100644 core/src/main/res/drawable-xxhdpi/ic_fast_forward_grey600_24dp.png delete mode 100644 core/src/main/res/drawable-xxhdpi/ic_fast_forward_grey600_36dp.png delete mode 100644 core/src/main/res/drawable-xxhdpi/ic_fast_forward_white_24dp.png delete mode 100644 core/src/main/res/drawable-xxhdpi/ic_fast_forward_white_36dp.png delete mode 100644 core/src/main/res/drawable-xxhdpi/ic_fast_rewind_grey600_24dp.png delete mode 100644 core/src/main/res/drawable-xxhdpi/ic_fast_rewind_grey600_36dp.png delete mode 100644 core/src/main/res/drawable-xxhdpi/ic_fast_rewind_white_24dp.png delete mode 100644 core/src/main/res/drawable-xxhdpi/ic_fast_rewind_white_36dp.png delete mode 100644 core/src/main/res/drawable-xxhdpi/ic_pause_grey600_24dp.png delete mode 100644 core/src/main/res/drawable-xxhdpi/ic_pause_grey600_36dp.png delete mode 100644 core/src/main/res/drawable-xxhdpi/ic_pause_white_24dp.png delete mode 100644 core/src/main/res/drawable-xxhdpi/ic_pause_white_36dp.png delete mode 100644 core/src/main/res/drawable-xxhdpi/ic_play_arrow_grey600_24dp.png delete mode 100644 core/src/main/res/drawable-xxhdpi/ic_play_arrow_grey600_36dp.png delete mode 100644 core/src/main/res/drawable-xxhdpi/ic_play_arrow_white_24dp.png delete mode 100644 core/src/main/res/drawable-xxhdpi/ic_play_arrow_white_36dp.png delete mode 100644 core/src/main/res/drawable-xxhdpi/ic_skip_grey600_36dp.png delete mode 100644 core/src/main/res/drawable-xxhdpi/ic_skip_white_36dp.png delete mode 100644 core/src/main/res/drawable-xxxhdpi/ic_skip_grey600_36dp.png delete mode 100644 core/src/main/res/drawable-xxxhdpi/ic_skip_white_36dp.png create mode 100644 core/src/main/res/drawable/ic_av_fast_forward_dark_48dp.xml create mode 100644 core/src/main/res/drawable/ic_av_fast_forward_white_48dp.xml create mode 100644 core/src/main/res/drawable/ic_av_fast_rewind_dark_48dp.xml create mode 100644 core/src/main/res/drawable/ic_av_fast_rewind_white_48dp.xml create mode 100644 core/src/main/res/drawable/ic_av_pause_dark_48dp.xml create mode 100644 core/src/main/res/drawable/ic_av_pause_white_48dp.xml create mode 100644 core/src/main/res/drawable/ic_av_play_dark_24dp.xml create mode 100644 core/src/main/res/drawable/ic_av_play_dark_48dp.xml create mode 100644 core/src/main/res/drawable/ic_av_play_white_24dp.xml create mode 100644 core/src/main/res/drawable/ic_av_play_white_48dp.xml create mode 100644 core/src/main/res/drawable/ic_av_skip_dark_48dp.xml create mode 100644 core/src/main/res/drawable/ic_av_skip_white_48dp.xml (limited to 'core/src') diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/PlayerWidgetJobService.java b/core/src/main/java/de/danoeh/antennapod/core/service/PlayerWidgetJobService.java index e6f2176f7..4562f1393 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/PlayerWidgetJobService.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/PlayerWidgetJobService.java @@ -8,7 +8,6 @@ import android.content.Intent; import android.content.ServiceConnection; import android.content.SharedPreferences; import android.graphics.Bitmap; -import android.os.Build; import android.os.Bundle; import android.os.IBinder; import androidx.annotation.NonNull; @@ -158,10 +157,10 @@ public class PlayerWidgetJobService extends SafeJobIntentService { } if (status == PlayerStatus.PLAYING) { - views.setImageViewResource(R.id.butPlay, R.drawable.ic_pause_white_24dp); + views.setImageViewResource(R.id.butPlay, R.drawable.ic_av_pause_white_48dp); views.setContentDescription(R.id.butPlay, getString(R.string.pause_label)); } else { - views.setImageViewResource(R.id.butPlay, R.drawable.ic_play_arrow_white_24dp); + views.setImageViewResource(R.id.butPlay, R.drawable.ic_av_play_white_48dp); views.setContentDescription(R.id.butPlay, getString(R.string.play_label)); } views.setOnClickPendingIntent(R.id.butPlay, createMediaButtonIntent()); @@ -177,7 +176,7 @@ public class PlayerWidgetJobService extends SafeJobIntentService { views.setViewVisibility(R.id.txtvTitle, View.GONE); views.setViewVisibility(R.id.txtNoPlaying, View.VISIBLE); views.setImageViewResource(R.id.imgvCover, R.mipmap.ic_launcher_foreground); - views.setImageViewResource(R.id.butPlay, R.drawable.ic_play_arrow_white_24dp); + views.setImageViewResource(R.id.butPlay, R.drawable.ic_av_play_white_48dp); } if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN) { diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/playback/PlaybackController.java b/core/src/main/java/de/danoeh/antennapod/core/util/playback/PlaybackController.java index cb22fbcc9..d9567e1e1 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/playback/PlaybackController.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/playback/PlaybackController.java @@ -21,6 +21,7 @@ import android.widget.ImageButton; import android.widget.SeekBar; import android.widget.TextView; +import de.danoeh.antennapod.core.util.ThemeUtils; import java.util.concurrent.ScheduledThreadPoolExecutor; import de.danoeh.antennapod.core.R; @@ -397,12 +398,10 @@ public class PlaybackController { final CharSequence playText = activity.getString(R.string.play_label); final CharSequence pauseText = activity.getString(R.string.pause_label); - if (PlaybackService.getCurrentMediaType() == MediaType.AUDIO || - PlaybackService.isCasting()) { - TypedArray res = activity.obtainStyledAttributes(new int[]{ - R.attr.av_play_big, R.attr.av_pause_big}); - playResource = res.getResourceId(0, R.drawable.ic_play_arrow_grey600_36dp); - pauseResource = res.getResourceId(1, R.drawable.ic_pause_grey600_36dp); + if (PlaybackService.getCurrentMediaType() == MediaType.AUDIO || PlaybackService.isCasting()) { + TypedArray res = activity.obtainStyledAttributes(new int[]{ R.attr.av_play, R.attr.av_pause}); + playResource = res.getResourceId(0, R.drawable.ic_av_play_dark_48dp); + pauseResource = res.getResourceId(1, R.drawable.ic_av_pause_dark_48dp); res.recycle(); } else { playResource = R.drawable.ic_av_play_white_80dp; @@ -779,11 +778,8 @@ public class PlaybackController { .observeOn(AndroidSchedulers.mainThread()) .subscribe(media -> { if (media.getMediaType() == MediaType.AUDIO) { - TypedArray res = activity.obtainStyledAttributes(new int[]{ - de.danoeh.antennapod.core.R.attr.av_play_big}); getPlayButton().setImageResource( - res.getResourceId(0, de.danoeh.antennapod.core.R.drawable.ic_play_arrow_grey600_36dp)); - res.recycle(); + ThemeUtils.getDrawableFromAttr(activity, de.danoeh.antennapod.core.R.attr.av_play)); } else { getPlayButton().setImageResource(R.drawable.ic_av_play_white_80dp); } diff --git a/core/src/main/res/drawable-hdpi/ic_fast_forward_grey600_24dp.png b/core/src/main/res/drawable-hdpi/ic_fast_forward_grey600_24dp.png deleted file mode 100644 index df9e662c1..000000000 Binary files a/core/src/main/res/drawable-hdpi/ic_fast_forward_grey600_24dp.png and /dev/null differ diff --git a/core/src/main/res/drawable-hdpi/ic_fast_forward_grey600_36dp.png b/core/src/main/res/drawable-hdpi/ic_fast_forward_grey600_36dp.png deleted file mode 100644 index 59ae40266..000000000 Binary files a/core/src/main/res/drawable-hdpi/ic_fast_forward_grey600_36dp.png and /dev/null differ diff --git a/core/src/main/res/drawable-hdpi/ic_fast_forward_white_24dp.png b/core/src/main/res/drawable-hdpi/ic_fast_forward_white_24dp.png deleted file mode 100644 index 2d61b31f1..000000000 Binary files a/core/src/main/res/drawable-hdpi/ic_fast_forward_white_24dp.png and /dev/null differ diff --git a/core/src/main/res/drawable-hdpi/ic_fast_forward_white_36dp.png b/core/src/main/res/drawable-hdpi/ic_fast_forward_white_36dp.png deleted file mode 100644 index e5ae251d3..000000000 Binary files a/core/src/main/res/drawable-hdpi/ic_fast_forward_white_36dp.png and /dev/null differ diff --git a/core/src/main/res/drawable-hdpi/ic_fast_rewind_grey600_24dp.png b/core/src/main/res/drawable-hdpi/ic_fast_rewind_grey600_24dp.png deleted file mode 100644 index f661ca723..000000000 Binary files a/core/src/main/res/drawable-hdpi/ic_fast_rewind_grey600_24dp.png and /dev/null differ diff --git a/core/src/main/res/drawable-hdpi/ic_fast_rewind_grey600_36dp.png b/core/src/main/res/drawable-hdpi/ic_fast_rewind_grey600_36dp.png deleted file mode 100644 index d36891a8d..000000000 Binary files a/core/src/main/res/drawable-hdpi/ic_fast_rewind_grey600_36dp.png and /dev/null differ diff --git a/core/src/main/res/drawable-hdpi/ic_fast_rewind_white_24dp.png b/core/src/main/res/drawable-hdpi/ic_fast_rewind_white_24dp.png deleted file mode 100644 index ab8b48ec3..000000000 Binary files a/core/src/main/res/drawable-hdpi/ic_fast_rewind_white_24dp.png and /dev/null differ diff --git a/core/src/main/res/drawable-hdpi/ic_fast_rewind_white_36dp.png b/core/src/main/res/drawable-hdpi/ic_fast_rewind_white_36dp.png deleted file mode 100644 index 75796d7a9..000000000 Binary files a/core/src/main/res/drawable-hdpi/ic_fast_rewind_white_36dp.png and /dev/null differ diff --git a/core/src/main/res/drawable-hdpi/ic_pause_grey600_24dp.png b/core/src/main/res/drawable-hdpi/ic_pause_grey600_24dp.png deleted file mode 100644 index 7281f37e1..000000000 Binary files a/core/src/main/res/drawable-hdpi/ic_pause_grey600_24dp.png and /dev/null differ diff --git a/core/src/main/res/drawable-hdpi/ic_pause_grey600_36dp.png b/core/src/main/res/drawable-hdpi/ic_pause_grey600_36dp.png deleted file mode 100644 index dde9bb25c..000000000 Binary files a/core/src/main/res/drawable-hdpi/ic_pause_grey600_36dp.png and /dev/null differ diff --git a/core/src/main/res/drawable-hdpi/ic_pause_white_24dp.png b/core/src/main/res/drawable-hdpi/ic_pause_white_24dp.png deleted file mode 100644 index 1701f34b0..000000000 Binary files a/core/src/main/res/drawable-hdpi/ic_pause_white_24dp.png and /dev/null differ diff --git a/core/src/main/res/drawable-hdpi/ic_pause_white_36dp.png b/core/src/main/res/drawable-hdpi/ic_pause_white_36dp.png deleted file mode 100644 index 1d024393a..000000000 Binary files a/core/src/main/res/drawable-hdpi/ic_pause_white_36dp.png and /dev/null differ diff --git a/core/src/main/res/drawable-hdpi/ic_play_arrow_grey600_24dp.png b/core/src/main/res/drawable-hdpi/ic_play_arrow_grey600_24dp.png deleted file mode 100644 index b540e4a63..000000000 Binary files a/core/src/main/res/drawable-hdpi/ic_play_arrow_grey600_24dp.png and /dev/null differ diff --git a/core/src/main/res/drawable-hdpi/ic_play_arrow_grey600_36dp.png b/core/src/main/res/drawable-hdpi/ic_play_arrow_grey600_36dp.png deleted file mode 100644 index a12b921e4..000000000 Binary files a/core/src/main/res/drawable-hdpi/ic_play_arrow_grey600_36dp.png and /dev/null differ diff --git a/core/src/main/res/drawable-hdpi/ic_play_arrow_white_24dp.png b/core/src/main/res/drawable-hdpi/ic_play_arrow_white_24dp.png deleted file mode 100644 index f77ad6b57..000000000 Binary files a/core/src/main/res/drawable-hdpi/ic_play_arrow_white_24dp.png and /dev/null differ diff --git a/core/src/main/res/drawable-hdpi/ic_play_arrow_white_36dp.png b/core/src/main/res/drawable-hdpi/ic_play_arrow_white_36dp.png deleted file mode 100644 index 2b8e3513f..000000000 Binary files a/core/src/main/res/drawable-hdpi/ic_play_arrow_white_36dp.png and /dev/null differ diff --git a/core/src/main/res/drawable-hdpi/ic_skip_grey600_36dp.png b/core/src/main/res/drawable-hdpi/ic_skip_grey600_36dp.png deleted file mode 100644 index 6e1dffc93..000000000 Binary files a/core/src/main/res/drawable-hdpi/ic_skip_grey600_36dp.png and /dev/null differ diff --git a/core/src/main/res/drawable-hdpi/ic_skip_white_36dp.png b/core/src/main/res/drawable-hdpi/ic_skip_white_36dp.png deleted file mode 100644 index 760ec9987..000000000 Binary files a/core/src/main/res/drawable-hdpi/ic_skip_white_36dp.png and /dev/null differ diff --git a/core/src/main/res/drawable-mdpi/ic_fast_forward_grey600_24dp.png b/core/src/main/res/drawable-mdpi/ic_fast_forward_grey600_24dp.png deleted file mode 100644 index c67fc25f1..000000000 Binary files a/core/src/main/res/drawable-mdpi/ic_fast_forward_grey600_24dp.png and /dev/null differ diff --git a/core/src/main/res/drawable-mdpi/ic_fast_forward_grey600_36dp.png b/core/src/main/res/drawable-mdpi/ic_fast_forward_grey600_36dp.png deleted file mode 100644 index df9e662c1..000000000 Binary files a/core/src/main/res/drawable-mdpi/ic_fast_forward_grey600_36dp.png and /dev/null differ diff --git a/core/src/main/res/drawable-mdpi/ic_fast_forward_white_24dp.png b/core/src/main/res/drawable-mdpi/ic_fast_forward_white_24dp.png deleted file mode 100644 index fceffcb7b..000000000 Binary files a/core/src/main/res/drawable-mdpi/ic_fast_forward_white_24dp.png and /dev/null differ diff --git a/core/src/main/res/drawable-mdpi/ic_fast_forward_white_36dp.png b/core/src/main/res/drawable-mdpi/ic_fast_forward_white_36dp.png deleted file mode 100644 index 2d61b31f1..000000000 Binary files a/core/src/main/res/drawable-mdpi/ic_fast_forward_white_36dp.png and /dev/null differ diff --git a/core/src/main/res/drawable-mdpi/ic_fast_rewind_grey600_24dp.png b/core/src/main/res/drawable-mdpi/ic_fast_rewind_grey600_24dp.png deleted file mode 100644 index de04575da..000000000 Binary files a/core/src/main/res/drawable-mdpi/ic_fast_rewind_grey600_24dp.png and /dev/null differ diff --git a/core/src/main/res/drawable-mdpi/ic_fast_rewind_grey600_36dp.png b/core/src/main/res/drawable-mdpi/ic_fast_rewind_grey600_36dp.png deleted file mode 100644 index f661ca723..000000000 Binary files a/core/src/main/res/drawable-mdpi/ic_fast_rewind_grey600_36dp.png and /dev/null differ diff --git a/core/src/main/res/drawable-mdpi/ic_fast_rewind_white_24dp.png b/core/src/main/res/drawable-mdpi/ic_fast_rewind_white_24dp.png deleted file mode 100644 index bfb476b4a..000000000 Binary files a/core/src/main/res/drawable-mdpi/ic_fast_rewind_white_24dp.png and /dev/null differ diff --git a/core/src/main/res/drawable-mdpi/ic_fast_rewind_white_36dp.png b/core/src/main/res/drawable-mdpi/ic_fast_rewind_white_36dp.png deleted file mode 100644 index ab8b48ec3..000000000 Binary files a/core/src/main/res/drawable-mdpi/ic_fast_rewind_white_36dp.png and /dev/null differ diff --git a/core/src/main/res/drawable-mdpi/ic_pause_grey600_24dp.png b/core/src/main/res/drawable-mdpi/ic_pause_grey600_24dp.png deleted file mode 100644 index 126ee03ef..000000000 Binary files a/core/src/main/res/drawable-mdpi/ic_pause_grey600_24dp.png and /dev/null differ diff --git a/core/src/main/res/drawable-mdpi/ic_pause_grey600_36dp.png b/core/src/main/res/drawable-mdpi/ic_pause_grey600_36dp.png deleted file mode 100644 index 7281f37e1..000000000 Binary files a/core/src/main/res/drawable-mdpi/ic_pause_grey600_36dp.png and /dev/null differ diff --git a/core/src/main/res/drawable-mdpi/ic_pause_white_24dp.png b/core/src/main/res/drawable-mdpi/ic_pause_white_24dp.png deleted file mode 100644 index 2272d478c..000000000 Binary files a/core/src/main/res/drawable-mdpi/ic_pause_white_24dp.png and /dev/null differ diff --git a/core/src/main/res/drawable-mdpi/ic_pause_white_36dp.png b/core/src/main/res/drawable-mdpi/ic_pause_white_36dp.png deleted file mode 100644 index 1701f34b0..000000000 Binary files a/core/src/main/res/drawable-mdpi/ic_pause_white_36dp.png and /dev/null differ diff --git a/core/src/main/res/drawable-mdpi/ic_play_arrow_grey600_24dp.png b/core/src/main/res/drawable-mdpi/ic_play_arrow_grey600_24dp.png deleted file mode 100644 index 9c8f2c555..000000000 Binary files a/core/src/main/res/drawable-mdpi/ic_play_arrow_grey600_24dp.png and /dev/null differ diff --git a/core/src/main/res/drawable-mdpi/ic_play_arrow_grey600_36dp.png b/core/src/main/res/drawable-mdpi/ic_play_arrow_grey600_36dp.png deleted file mode 100644 index b540e4a63..000000000 Binary files a/core/src/main/res/drawable-mdpi/ic_play_arrow_grey600_36dp.png and /dev/null differ diff --git a/core/src/main/res/drawable-mdpi/ic_play_arrow_white_24dp.png b/core/src/main/res/drawable-mdpi/ic_play_arrow_white_24dp.png deleted file mode 100644 index 172c211ab..000000000 Binary files a/core/src/main/res/drawable-mdpi/ic_play_arrow_white_24dp.png and /dev/null differ diff --git a/core/src/main/res/drawable-mdpi/ic_play_arrow_white_36dp.png b/core/src/main/res/drawable-mdpi/ic_play_arrow_white_36dp.png deleted file mode 100644 index f77ad6b57..000000000 Binary files a/core/src/main/res/drawable-mdpi/ic_play_arrow_white_36dp.png and /dev/null differ diff --git a/core/src/main/res/drawable-mdpi/ic_skip_grey600_36dp.png b/core/src/main/res/drawable-mdpi/ic_skip_grey600_36dp.png deleted file mode 100644 index 229eeca47..000000000 Binary files a/core/src/main/res/drawable-mdpi/ic_skip_grey600_36dp.png and /dev/null differ diff --git a/core/src/main/res/drawable-mdpi/ic_skip_white_36dp.png b/core/src/main/res/drawable-mdpi/ic_skip_white_36dp.png deleted file mode 100644 index 9032328d4..000000000 Binary files a/core/src/main/res/drawable-mdpi/ic_skip_white_36dp.png and /dev/null differ diff --git a/core/src/main/res/drawable-xhdpi/ic_fast_forward_grey600_24dp.png b/core/src/main/res/drawable-xhdpi/ic_fast_forward_grey600_24dp.png deleted file mode 100644 index 6f8b42221..000000000 Binary files a/core/src/main/res/drawable-xhdpi/ic_fast_forward_grey600_24dp.png and /dev/null differ diff --git a/core/src/main/res/drawable-xhdpi/ic_fast_forward_grey600_36dp.png b/core/src/main/res/drawable-xhdpi/ic_fast_forward_grey600_36dp.png deleted file mode 100644 index 521f7490b..000000000 Binary files a/core/src/main/res/drawable-xhdpi/ic_fast_forward_grey600_36dp.png and /dev/null differ diff --git a/core/src/main/res/drawable-xhdpi/ic_fast_forward_white_24dp.png b/core/src/main/res/drawable-xhdpi/ic_fast_forward_white_24dp.png deleted file mode 100644 index 2b34fb82d..000000000 Binary files a/core/src/main/res/drawable-xhdpi/ic_fast_forward_white_24dp.png and /dev/null differ diff --git a/core/src/main/res/drawable-xhdpi/ic_fast_forward_white_36dp.png b/core/src/main/res/drawable-xhdpi/ic_fast_forward_white_36dp.png deleted file mode 100644 index 2d9a7e3c9..000000000 Binary files a/core/src/main/res/drawable-xhdpi/ic_fast_forward_white_36dp.png and /dev/null differ diff --git a/core/src/main/res/drawable-xhdpi/ic_fast_rewind_grey600_24dp.png b/core/src/main/res/drawable-xhdpi/ic_fast_rewind_grey600_24dp.png deleted file mode 100644 index 9468020b7..000000000 Binary files a/core/src/main/res/drawable-xhdpi/ic_fast_rewind_grey600_24dp.png and /dev/null differ diff --git a/core/src/main/res/drawable-xhdpi/ic_fast_rewind_grey600_36dp.png b/core/src/main/res/drawable-xhdpi/ic_fast_rewind_grey600_36dp.png deleted file mode 100644 index ea5493251..000000000 Binary files a/core/src/main/res/drawable-xhdpi/ic_fast_rewind_grey600_36dp.png and /dev/null differ diff --git a/core/src/main/res/drawable-xhdpi/ic_fast_rewind_white_24dp.png b/core/src/main/res/drawable-xhdpi/ic_fast_rewind_white_24dp.png deleted file mode 100644 index f4182f174..000000000 Binary files a/core/src/main/res/drawable-xhdpi/ic_fast_rewind_white_24dp.png and /dev/null differ diff --git a/core/src/main/res/drawable-xhdpi/ic_fast_rewind_white_36dp.png b/core/src/main/res/drawable-xhdpi/ic_fast_rewind_white_36dp.png deleted file mode 100644 index de9ec1d90..000000000 Binary files a/core/src/main/res/drawable-xhdpi/ic_fast_rewind_white_36dp.png and /dev/null differ diff --git a/core/src/main/res/drawable-xhdpi/ic_pause_grey600_24dp.png b/core/src/main/res/drawable-xhdpi/ic_pause_grey600_24dp.png deleted file mode 100644 index 6708b4161..000000000 Binary files a/core/src/main/res/drawable-xhdpi/ic_pause_grey600_24dp.png and /dev/null differ diff --git a/core/src/main/res/drawable-xhdpi/ic_pause_grey600_36dp.png b/core/src/main/res/drawable-xhdpi/ic_pause_grey600_36dp.png deleted file mode 100644 index aeb13ebc4..000000000 Binary files a/core/src/main/res/drawable-xhdpi/ic_pause_grey600_36dp.png and /dev/null differ diff --git a/core/src/main/res/drawable-xhdpi/ic_pause_white_24dp.png b/core/src/main/res/drawable-xhdpi/ic_pause_white_24dp.png deleted file mode 100644 index f49aed757..000000000 Binary files a/core/src/main/res/drawable-xhdpi/ic_pause_white_24dp.png and /dev/null differ diff --git a/core/src/main/res/drawable-xhdpi/ic_pause_white_36dp.png b/core/src/main/res/drawable-xhdpi/ic_pause_white_36dp.png deleted file mode 100644 index 7192ad487..000000000 Binary files a/core/src/main/res/drawable-xhdpi/ic_pause_white_36dp.png and /dev/null differ diff --git a/core/src/main/res/drawable-xhdpi/ic_play_arrow_grey600_24dp.png b/core/src/main/res/drawable-xhdpi/ic_play_arrow_grey600_24dp.png deleted file mode 100644 index 6874b8236..000000000 Binary files a/core/src/main/res/drawable-xhdpi/ic_play_arrow_grey600_24dp.png and /dev/null differ diff --git a/core/src/main/res/drawable-xhdpi/ic_play_arrow_grey600_36dp.png b/core/src/main/res/drawable-xhdpi/ic_play_arrow_grey600_36dp.png deleted file mode 100644 index dabd252ee..000000000 Binary files a/core/src/main/res/drawable-xhdpi/ic_play_arrow_grey600_36dp.png and /dev/null differ diff --git a/core/src/main/res/drawable-xhdpi/ic_play_arrow_white_24dp.png b/core/src/main/res/drawable-xhdpi/ic_play_arrow_white_24dp.png deleted file mode 100644 index 5b0110454..000000000 Binary files a/core/src/main/res/drawable-xhdpi/ic_play_arrow_white_24dp.png and /dev/null differ diff --git a/core/src/main/res/drawable-xhdpi/ic_play_arrow_white_36dp.png b/core/src/main/res/drawable-xhdpi/ic_play_arrow_white_36dp.png deleted file mode 100644 index fff3e1f56..000000000 Binary files a/core/src/main/res/drawable-xhdpi/ic_play_arrow_white_36dp.png and /dev/null differ diff --git a/core/src/main/res/drawable-xhdpi/ic_skip_grey600_36dp.png b/core/src/main/res/drawable-xhdpi/ic_skip_grey600_36dp.png deleted file mode 100644 index 31aa09ca2..000000000 Binary files a/core/src/main/res/drawable-xhdpi/ic_skip_grey600_36dp.png and /dev/null differ diff --git a/core/src/main/res/drawable-xhdpi/ic_skip_white_36dp.png b/core/src/main/res/drawable-xhdpi/ic_skip_white_36dp.png deleted file mode 100644 index e664f607c..000000000 Binary files a/core/src/main/res/drawable-xhdpi/ic_skip_white_36dp.png and /dev/null differ diff --git a/core/src/main/res/drawable-xxhdpi/ic_fast_forward_grey600_24dp.png b/core/src/main/res/drawable-xxhdpi/ic_fast_forward_grey600_24dp.png deleted file mode 100644 index 521f7490b..000000000 Binary files a/core/src/main/res/drawable-xxhdpi/ic_fast_forward_grey600_24dp.png and /dev/null differ diff --git a/core/src/main/res/drawable-xxhdpi/ic_fast_forward_grey600_36dp.png b/core/src/main/res/drawable-xxhdpi/ic_fast_forward_grey600_36dp.png deleted file mode 100644 index 644645c8b..000000000 Binary files a/core/src/main/res/drawable-xxhdpi/ic_fast_forward_grey600_36dp.png and /dev/null differ diff --git a/core/src/main/res/drawable-xxhdpi/ic_fast_forward_white_24dp.png b/core/src/main/res/drawable-xxhdpi/ic_fast_forward_white_24dp.png deleted file mode 100644 index 2d9a7e3c9..000000000 Binary files a/core/src/main/res/drawable-xxhdpi/ic_fast_forward_white_24dp.png and /dev/null differ diff --git a/core/src/main/res/drawable-xxhdpi/ic_fast_forward_white_36dp.png b/core/src/main/res/drawable-xxhdpi/ic_fast_forward_white_36dp.png deleted file mode 100644 index 76c94c3ba..000000000 Binary files a/core/src/main/res/drawable-xxhdpi/ic_fast_forward_white_36dp.png and /dev/null differ diff --git a/core/src/main/res/drawable-xxhdpi/ic_fast_rewind_grey600_24dp.png b/core/src/main/res/drawable-xxhdpi/ic_fast_rewind_grey600_24dp.png deleted file mode 100644 index ea5493251..000000000 Binary files a/core/src/main/res/drawable-xxhdpi/ic_fast_rewind_grey600_24dp.png and /dev/null differ diff --git a/core/src/main/res/drawable-xxhdpi/ic_fast_rewind_grey600_36dp.png b/core/src/main/res/drawable-xxhdpi/ic_fast_rewind_grey600_36dp.png deleted file mode 100644 index 831fda2ab..000000000 Binary files a/core/src/main/res/drawable-xxhdpi/ic_fast_rewind_grey600_36dp.png and /dev/null differ diff --git a/core/src/main/res/drawable-xxhdpi/ic_fast_rewind_white_24dp.png b/core/src/main/res/drawable-xxhdpi/ic_fast_rewind_white_24dp.png deleted file mode 100644 index de9ec1d90..000000000 Binary files a/core/src/main/res/drawable-xxhdpi/ic_fast_rewind_white_24dp.png and /dev/null differ diff --git a/core/src/main/res/drawable-xxhdpi/ic_fast_rewind_white_36dp.png b/core/src/main/res/drawable-xxhdpi/ic_fast_rewind_white_36dp.png deleted file mode 100644 index 8e11ac89e..000000000 Binary files a/core/src/main/res/drawable-xxhdpi/ic_fast_rewind_white_36dp.png and /dev/null differ diff --git a/core/src/main/res/drawable-xxhdpi/ic_pause_grey600_24dp.png b/core/src/main/res/drawable-xxhdpi/ic_pause_grey600_24dp.png deleted file mode 100644 index aeb13ebc4..000000000 Binary files a/core/src/main/res/drawable-xxhdpi/ic_pause_grey600_24dp.png and /dev/null differ diff --git a/core/src/main/res/drawable-xxhdpi/ic_pause_grey600_36dp.png b/core/src/main/res/drawable-xxhdpi/ic_pause_grey600_36dp.png deleted file mode 100644 index 8753d9c50..000000000 Binary files a/core/src/main/res/drawable-xxhdpi/ic_pause_grey600_36dp.png and /dev/null differ diff --git a/core/src/main/res/drawable-xxhdpi/ic_pause_white_24dp.png b/core/src/main/res/drawable-xxhdpi/ic_pause_white_24dp.png deleted file mode 100644 index 7192ad487..000000000 Binary files a/core/src/main/res/drawable-xxhdpi/ic_pause_white_24dp.png and /dev/null differ diff --git a/core/src/main/res/drawable-xxhdpi/ic_pause_white_36dp.png b/core/src/main/res/drawable-xxhdpi/ic_pause_white_36dp.png deleted file mode 100644 index fb63ddc5a..000000000 Binary files a/core/src/main/res/drawable-xxhdpi/ic_pause_white_36dp.png and /dev/null differ diff --git a/core/src/main/res/drawable-xxhdpi/ic_play_arrow_grey600_24dp.png b/core/src/main/res/drawable-xxhdpi/ic_play_arrow_grey600_24dp.png deleted file mode 100644 index dabd252ee..000000000 Binary files a/core/src/main/res/drawable-xxhdpi/ic_play_arrow_grey600_24dp.png and /dev/null differ diff --git a/core/src/main/res/drawable-xxhdpi/ic_play_arrow_grey600_36dp.png b/core/src/main/res/drawable-xxhdpi/ic_play_arrow_grey600_36dp.png deleted file mode 100644 index 9fcf99558..000000000 Binary files a/core/src/main/res/drawable-xxhdpi/ic_play_arrow_grey600_36dp.png and /dev/null differ diff --git a/core/src/main/res/drawable-xxhdpi/ic_play_arrow_white_24dp.png b/core/src/main/res/drawable-xxhdpi/ic_play_arrow_white_24dp.png deleted file mode 100644 index fff3e1f56..000000000 Binary files a/core/src/main/res/drawable-xxhdpi/ic_play_arrow_white_24dp.png and /dev/null differ diff --git a/core/src/main/res/drawable-xxhdpi/ic_play_arrow_white_36dp.png b/core/src/main/res/drawable-xxhdpi/ic_play_arrow_white_36dp.png deleted file mode 100644 index 9b31e2d19..000000000 Binary files a/core/src/main/res/drawable-xxhdpi/ic_play_arrow_white_36dp.png and /dev/null differ diff --git a/core/src/main/res/drawable-xxhdpi/ic_skip_grey600_36dp.png b/core/src/main/res/drawable-xxhdpi/ic_skip_grey600_36dp.png deleted file mode 100644 index 75a4a9545..000000000 Binary files a/core/src/main/res/drawable-xxhdpi/ic_skip_grey600_36dp.png and /dev/null differ diff --git a/core/src/main/res/drawable-xxhdpi/ic_skip_white_36dp.png b/core/src/main/res/drawable-xxhdpi/ic_skip_white_36dp.png deleted file mode 100644 index a31299c81..000000000 Binary files a/core/src/main/res/drawable-xxhdpi/ic_skip_white_36dp.png and /dev/null differ diff --git a/core/src/main/res/drawable-xxxhdpi/ic_skip_grey600_36dp.png b/core/src/main/res/drawable-xxxhdpi/ic_skip_grey600_36dp.png deleted file mode 100644 index b599c2207..000000000 Binary files a/core/src/main/res/drawable-xxxhdpi/ic_skip_grey600_36dp.png and /dev/null differ diff --git a/core/src/main/res/drawable-xxxhdpi/ic_skip_white_36dp.png b/core/src/main/res/drawable-xxxhdpi/ic_skip_white_36dp.png deleted file mode 100644 index a0dd670c3..000000000 Binary files a/core/src/main/res/drawable-xxxhdpi/ic_skip_white_36dp.png and /dev/null differ diff --git a/core/src/main/res/drawable/ic_av_fast_forward_dark_48dp.xml b/core/src/main/res/drawable/ic_av_fast_forward_dark_48dp.xml new file mode 100644 index 000000000..cf0faa33e --- /dev/null +++ b/core/src/main/res/drawable/ic_av_fast_forward_dark_48dp.xml @@ -0,0 +1,7 @@ + + + diff --git a/core/src/main/res/drawable/ic_av_fast_forward_white_48dp.xml b/core/src/main/res/drawable/ic_av_fast_forward_white_48dp.xml new file mode 100644 index 000000000..aca5bcf29 --- /dev/null +++ b/core/src/main/res/drawable/ic_av_fast_forward_white_48dp.xml @@ -0,0 +1,7 @@ + + + diff --git a/core/src/main/res/drawable/ic_av_fast_rewind_dark_48dp.xml b/core/src/main/res/drawable/ic_av_fast_rewind_dark_48dp.xml new file mode 100644 index 000000000..47d1189cb --- /dev/null +++ b/core/src/main/res/drawable/ic_av_fast_rewind_dark_48dp.xml @@ -0,0 +1,7 @@ + + + diff --git a/core/src/main/res/drawable/ic_av_fast_rewind_white_48dp.xml b/core/src/main/res/drawable/ic_av_fast_rewind_white_48dp.xml new file mode 100644 index 000000000..ba2b8ae4f --- /dev/null +++ b/core/src/main/res/drawable/ic_av_fast_rewind_white_48dp.xml @@ -0,0 +1,7 @@ + + + diff --git a/core/src/main/res/drawable/ic_av_pause_dark_48dp.xml b/core/src/main/res/drawable/ic_av_pause_dark_48dp.xml new file mode 100644 index 000000000..61fdd4b5b --- /dev/null +++ b/core/src/main/res/drawable/ic_av_pause_dark_48dp.xml @@ -0,0 +1,7 @@ + + + diff --git a/core/src/main/res/drawable/ic_av_pause_white_48dp.xml b/core/src/main/res/drawable/ic_av_pause_white_48dp.xml new file mode 100644 index 000000000..3512563ec --- /dev/null +++ b/core/src/main/res/drawable/ic_av_pause_white_48dp.xml @@ -0,0 +1,7 @@ + + + diff --git a/core/src/main/res/drawable/ic_av_play_dark_24dp.xml b/core/src/main/res/drawable/ic_av_play_dark_24dp.xml new file mode 100644 index 000000000..5bc12c0e1 --- /dev/null +++ b/core/src/main/res/drawable/ic_av_play_dark_24dp.xml @@ -0,0 +1,7 @@ + + + diff --git a/core/src/main/res/drawable/ic_av_play_dark_48dp.xml b/core/src/main/res/drawable/ic_av_play_dark_48dp.xml new file mode 100644 index 000000000..dbe5e7104 --- /dev/null +++ b/core/src/main/res/drawable/ic_av_play_dark_48dp.xml @@ -0,0 +1,7 @@ + + + diff --git a/core/src/main/res/drawable/ic_av_play_white_24dp.xml b/core/src/main/res/drawable/ic_av_play_white_24dp.xml new file mode 100644 index 000000000..0e896a8d4 --- /dev/null +++ b/core/src/main/res/drawable/ic_av_play_white_24dp.xml @@ -0,0 +1,7 @@ + + + diff --git a/core/src/main/res/drawable/ic_av_play_white_48dp.xml b/core/src/main/res/drawable/ic_av_play_white_48dp.xml new file mode 100644 index 000000000..bf94a000b --- /dev/null +++ b/core/src/main/res/drawable/ic_av_play_white_48dp.xml @@ -0,0 +1,7 @@ + + + diff --git a/core/src/main/res/drawable/ic_av_skip_dark_48dp.xml b/core/src/main/res/drawable/ic_av_skip_dark_48dp.xml new file mode 100644 index 000000000..2552f8d73 --- /dev/null +++ b/core/src/main/res/drawable/ic_av_skip_dark_48dp.xml @@ -0,0 +1,7 @@ + + + diff --git a/core/src/main/res/drawable/ic_av_skip_white_48dp.xml b/core/src/main/res/drawable/ic_av_skip_white_48dp.xml new file mode 100644 index 000000000..7e0073e88 --- /dev/null +++ b/core/src/main/res/drawable/ic_av_skip_white_48dp.xml @@ -0,0 +1,7 @@ + + + diff --git a/core/src/main/res/layout/player_widget.xml b/core/src/main/res/layout/player_widget.xml index 5f49fb7ef..b0e5e0fd8 100644 --- a/core/src/main/res/layout/player_widget.xml +++ b/core/src/main/res/layout/player_widget.xml @@ -19,8 +19,10 @@ android:layout_alignParentRight="true" android:layout_alignParentEnd="true" android:layout_margin="12dp" - android:background="@android:color/transparent" - android:src="@drawable/ic_play_arrow_white_24dp" /> + android:background="?android:attr/selectableItemBackground" + android:scaleType="fitCenter" + android:padding="8dp" + android:src="@drawable/ic_av_play_white_24dp" /> + @@ -32,11 +33,7 @@ - - - - - + diff --git a/core/src/main/res/values/styles.xml b/core/src/main/res/values/styles.xml index 33b736089..f6c31f652 100644 --- a/core/src/main/res/values/styles.xml +++ b/core/src/main/res/values/styles.xml @@ -20,12 +20,13 @@ @drawable/ic_search_grey600_24dp @drawable/ic_stream_grey600 @drawable/ic_file_download_grey600_24dp - @drawable/ic_fast_forward_grey600_24dp - @drawable/ic_pause_grey600_24dp - @drawable/ic_play_arrow_grey600_24dp + @drawable/ic_av_pause_dark_48dp + @drawable/ic_av_play_dark_48dp + @drawable/ic_av_fast_rewind_dark_48dp + @drawable/ic_av_fast_forward_dark_48dp + @drawable/ic_av_skip_dark_48dp @drawable/ic_playback_speed_dark_48dp @drawable/ic_playback_speed_dark_24dp - @drawable/ic_fast_rewind_grey600_24dp @drawable/ic_delete_grey600_24dp @drawable/ic_add_grey600_24dp @drawable/ic_remove_grey600 @@ -49,11 +50,7 @@ @drawable/ic_new_releases_grey600_24dp @drawable/ic_history_grey600_24dp @drawable/ic_folder_grey600_24dp - @drawable/ic_play_arrow_grey600_36dp - @drawable/ic_pause_grey600_36dp - @drawable/ic_fast_forward_grey600_36dp - @drawable/ic_fast_rewind_grey600_36dp - @drawable/ic_skip_grey600_36dp + @drawable/ic_av_play_dark_24dp @drawable/ic_star_border_grey600_24dp @drawable/ic_star_grey600_24dp @drawable/ic_settings_grey600_24dp @@ -108,12 +105,13 @@ @drawable/ic_search_white_24dp @drawable/ic_stream_white @drawable/ic_file_download_white_24dp - @drawable/ic_fast_forward_white_24dp - @drawable/ic_pause_white_24dp - @drawable/ic_play_arrow_white_24dp + @drawable/ic_av_fast_rewind_white_48dp + @drawable/ic_av_fast_forward_white_48dp + @drawable/ic_av_pause_white_48dp + @drawable/ic_av_play_white_48dp + @drawable/ic_av_skip_white_48dp @drawable/ic_playback_speed_white_48dp @drawable/ic_playback_speed_white_24dp - @drawable/ic_fast_rewind_white_24dp @drawable/ic_delete_white_24dp @drawable/ic_add_white_24dp @drawable/ic_remove_white @@ -137,11 +135,7 @@ @drawable/ic_new_releases_white_24dp @drawable/ic_history_white_24dp @drawable/ic_folder_white_24dp - @drawable/ic_play_arrow_white_36dp - @drawable/ic_pause_white_36dp - @drawable/ic_fast_forward_white_36dp - @drawable/ic_fast_rewind_white_36dp - @drawable/ic_skip_white_36dp + @drawable/ic_av_play_white_24dp @drawable/ic_star_border_white_24dp @drawable/ic_star_white_24dp @drawable/ic_settings_white_24dp -- cgit v1.2.3 From fe632a4f9f5dd5aa9ed8e54f42aa1496ce08f480 Mon Sep 17 00:00:00 2001 From: ByteHamster Date: Wed, 12 Feb 2020 13:38:18 +0100 Subject: Fixed other square images --- core/src/main/res/values/attrs.xml | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'core/src') diff --git a/core/src/main/res/values/attrs.xml b/core/src/main/res/values/attrs.xml index 066594f3d..77dd1fe47 100644 --- a/core/src/main/res/values/attrs.xml +++ b/core/src/main/res/values/attrs.xml @@ -77,4 +77,8 @@ + + + + -- cgit v1.2.3 From 246a2e650cedc25afe705d7b5422774b02c623e1 Mon Sep 17 00:00:00 2001 From: ByteHamster Date: Wed, 12 Feb 2020 23:26:30 +0100 Subject: Reformatted vorbis reader for readability --- .../VorbisCommentChapterReader.java | 174 ++++++----- .../vorbiscommentreader/VorbisCommentReader.java | 341 ++++++++++----------- 2 files changed, 247 insertions(+), 268 deletions(-) (limited to 'core/src') diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/vorbiscommentreader/VorbisCommentChapterReader.java b/core/src/main/java/de/danoeh/antennapod/core/util/vorbiscommentreader/VorbisCommentChapterReader.java index 569ff3438..c4fe76780 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/vorbiscommentreader/VorbisCommentChapterReader.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/vorbiscommentreader/VorbisCommentChapterReader.java @@ -10,93 +10,91 @@ import de.danoeh.antennapod.core.feed.Chapter; import de.danoeh.antennapod.core.feed.VorbisCommentChapter; public class VorbisCommentChapterReader extends VorbisCommentReader { - private static final String TAG = "VorbisCommentChptrReadr"; - - private static final String CHAPTER_KEY = "chapter\\d\\d\\d.*"; - private static final String CHAPTER_ATTRIBUTE_TITLE = "name"; - private static final String CHAPTER_ATTRIBUTE_LINK = "url"; - - private List chapters; - - public VorbisCommentChapterReader() { - } - - @Override - public void onVorbisCommentFound() { - System.out.println("Vorbis comment found"); - } - - @Override - public void onVorbisCommentHeaderFound(VorbisCommentHeader header) { - chapters = new ArrayList<>(); - System.out.println(header.toString()); - } - - @Override - public boolean onContentVectorKey(String content) { - return content.matches(CHAPTER_KEY); - } - - @Override - public void onContentVectorValue(String key, String value) - throws VorbisCommentReaderException { - if (BuildConfig.DEBUG) - Log.d(TAG, "Key: " + key + ", value: " + value); - String attribute = VorbisCommentChapter.getAttributeTypeFromKey(key); - int id = VorbisCommentChapter.getIDFromKey(key); - Chapter chapter = getChapterById(id); - if (attribute == null) { - if (getChapterById(id) == null) { - // new chapter - long start = VorbisCommentChapter.getStartTimeFromValue(value); - chapter = new VorbisCommentChapter(id); - chapter.setStart(start); - chapters.add(chapter); - } else { - throw new VorbisCommentReaderException( - "Found chapter with duplicate ID (" + key + ", " - + value + ")"); - } - } else if (attribute.equals(CHAPTER_ATTRIBUTE_TITLE)) { - if (chapter != null) { - chapter.setTitle(value); - } - } else if (attribute.equals(CHAPTER_ATTRIBUTE_LINK)) { - if (chapter != null) { - chapter.setLink(value); - } - } - } - - @Override - public void onNoVorbisCommentFound() { - System.out.println("No vorbis comment found"); - } - - @Override - public void onEndOfComment() { - System.out.println("End of comment"); - for (Chapter c : chapters) { - System.out.println(c.toString()); - } - } - - @Override - public void onError(VorbisCommentReaderException exception) { - exception.printStackTrace(); - } - - private Chapter getChapterById(long id) { - for (Chapter c : chapters) { - if (((VorbisCommentChapter) c).getVorbisCommentId() == id) { - return c; - } - } - return null; - } - - public List getChapters() { - return chapters; - } + private static final String TAG = "VorbisCommentChptrReadr"; + + private static final String CHAPTER_KEY = "chapter\\d\\d\\d.*"; + private static final String CHAPTER_ATTRIBUTE_TITLE = "name"; + private static final String CHAPTER_ATTRIBUTE_LINK = "url"; + + private List chapters; + + public VorbisCommentChapterReader() { + } + + @Override + public void onVorbisCommentFound() { + System.out.println("Vorbis comment found"); + } + + @Override + public void onVorbisCommentHeaderFound(VorbisCommentHeader header) { + chapters = new ArrayList<>(); + System.out.println(header.toString()); + } + + @Override + public boolean onContentVectorKey(String content) { + return content.matches(CHAPTER_KEY); + } + + @Override + public void onContentVectorValue(String key, String value) throws VorbisCommentReaderException { + if (BuildConfig.DEBUG) { + Log.d(TAG, "Key: " + key + ", value: " + value); + } + String attribute = VorbisCommentChapter.getAttributeTypeFromKey(key); + int id = VorbisCommentChapter.getIDFromKey(key); + Chapter chapter = getChapterById(id); + if (attribute == null) { + if (getChapterById(id) == null) { + // new chapter + long start = VorbisCommentChapter.getStartTimeFromValue(value); + chapter = new VorbisCommentChapter(id); + chapter.setStart(start); + chapters.add(chapter); + } else { + throw new VorbisCommentReaderException("Found chapter with duplicate ID (" + key + ", " + value + ")"); + } + } else if (attribute.equals(CHAPTER_ATTRIBUTE_TITLE)) { + if (chapter != null) { + chapter.setTitle(value); + } + } else if (attribute.equals(CHAPTER_ATTRIBUTE_LINK)) { + if (chapter != null) { + chapter.setLink(value); + } + } + } + + @Override + public void onNoVorbisCommentFound() { + System.out.println("No vorbis comment found"); + } + + @Override + public void onEndOfComment() { + System.out.println("End of comment"); + for (Chapter c : chapters) { + System.out.println(c.toString()); + } + } + + @Override + public void onError(VorbisCommentReaderException exception) { + exception.printStackTrace(); + } + + private Chapter getChapterById(long id) { + for (Chapter c : chapters) { + if (((VorbisCommentChapter) c).getVorbisCommentId() == id) { + return c; + } + } + return null; + } + + public List getChapters() { + return chapters; + } } diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/vorbiscommentreader/VorbisCommentReader.java b/core/src/main/java/de/danoeh/antennapod/core/util/vorbiscommentreader/VorbisCommentReader.java index 55498afcb..e5924b1ab 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/vorbiscommentreader/VorbisCommentReader.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/vorbiscommentreader/VorbisCommentReader.java @@ -1,5 +1,6 @@ package de.danoeh.antennapod.core.util.vorbiscommentreader; +import androidx.annotation.NonNull; import org.apache.commons.io.EndianUtils; import org.apache.commons.io.IOUtils; @@ -10,185 +11,165 @@ import java.nio.ByteBuffer; import java.nio.charset.Charset; import java.util.Arrays; - public abstract class VorbisCommentReader { - /** Length of first page in an ogg file in bytes. */ - private static final int FIRST_PAGE_LENGTH = 58; - private static final int SECOND_PAGE_MAX_LENGTH = 64 * 1024 * 1024; - private static final int PACKET_TYPE_IDENTIFICATION = 1; - private static final int PACKET_TYPE_COMMENT = 3; - - /** Called when Reader finds identification header. */ - protected abstract void onVorbisCommentFound(); - - protected abstract void onVorbisCommentHeaderFound(VorbisCommentHeader header); - - /** - * Is called every time the Reader finds a content vector. The handler - * should return true if it wants to handle the content vector. - */ - protected abstract boolean onContentVectorKey(String content); - - /** - * Is called if onContentVectorKey returned true for the key. - * - * @throws VorbisCommentReaderException - */ - protected abstract void onContentVectorValue(String key, String value) - throws VorbisCommentReaderException; - - protected abstract void onNoVorbisCommentFound(); - - protected abstract void onEndOfComment(); - - protected abstract void onError(VorbisCommentReaderException exception); - - public void readInputStream(InputStream input) - throws VorbisCommentReaderException { - try { - // look for identification header - if (findIdentificationHeader(input)) { - - onVorbisCommentFound(); - input = new OggInputStream(input); - if (findCommentHeader(input)) { - VorbisCommentHeader commentHeader = readCommentHeader(input); - if (commentHeader != null) { - onVorbisCommentHeaderFound(commentHeader); - for (int i = 0; i < commentHeader - .getUserCommentLength(); i++) { - try { - long vectorLength = EndianUtils - .readSwappedUnsignedInteger(input); - String key = readContentVectorKey(input, - vectorLength).toLowerCase(); - boolean readValue = onContentVectorKey(key); - if (readValue) { - String value = readUTF8String( - input, - (int) (vectorLength - key.length() - 1)); - onContentVectorValue(key, value); - } else { - IOUtils.skipFully(input, - vectorLength - key.length() - 1); - } - } catch (IOException e) { - e.printStackTrace(); - } - } - onEndOfComment(); - } - - } else { - onError(new VorbisCommentReaderException( - "No comment header found")); - } - } else { - onNoVorbisCommentFound(); - } - } catch (IOException e) { - onError(new VorbisCommentReaderException(e)); - } - } - - private String readUTF8String(InputStream input, long length) - throws IOException { - byte[] buffer = new byte[(int) length]; - - IOUtils.readFully(input, buffer); - Charset charset = Charset.forName("UTF-8"); - return charset.newDecoder().decode(ByteBuffer.wrap(buffer)).toString(); - } - - /** - * Looks for an identification header in the first page of the file. If an - * identification header is found, it will be skipped completely and the - * method will return true, otherwise false. - * - * @throws IOException - */ - private boolean findIdentificationHeader(InputStream input) - throws IOException { - byte[] buffer = new byte[FIRST_PAGE_LENGTH]; - IOUtils.readFully(input, buffer); - int i; - for (i = 6; i < buffer.length; i++) { - if (buffer[i - 5] == 'v' && buffer[i - 4] == 'o' - && buffer[i - 3] == 'r' && buffer[i - 2] == 'b' - && buffer[i - 1] == 'i' && buffer[i] == 's' - && buffer[i - 6] == PACKET_TYPE_IDENTIFICATION) { - return true; - } - } - return false; - } - - private boolean findCommentHeader(InputStream input) throws IOException { - char[] buffer = new char["vorbis".length() + 1]; - for (int bytesRead = 0; bytesRead < SECOND_PAGE_MAX_LENGTH; bytesRead++) { - char c = (char) input.read(); - int dest = -1; - switch (c) { - case PACKET_TYPE_COMMENT: - dest = 0; - break; - case 'v': - dest = 1; - break; - case 'o': - dest = 2; - break; - case 'r': - dest = 3; - break; - case 'b': - dest = 4; - break; - case 'i': - dest = 5; - break; - case 's': - dest = 6; - break; - } - if (dest >= 0) { - buffer[dest] = c; - if (buffer[1] == 'v' && buffer[2] == 'o' && buffer[3] == 'r' - && buffer[4] == 'b' && buffer[5] == 'i' - && buffer[6] == 's' && buffer[0] == PACKET_TYPE_COMMENT) { - return true; - } - } else { - Arrays.fill(buffer, (char) 0); - } - } - return false; - } - - private VorbisCommentHeader readCommentHeader(InputStream input) - throws IOException, VorbisCommentReaderException { - try { - long vendorLength = EndianUtils.readSwappedUnsignedInteger(input); - String vendorName = readUTF8String(input, vendorLength); - long userCommentLength = EndianUtils - .readSwappedUnsignedInteger(input); - return new VorbisCommentHeader(vendorName, userCommentLength); - } catch (UnsupportedEncodingException e) { - throw new VorbisCommentReaderException(e); - } - } - - private String readContentVectorKey(InputStream input, long vectorLength) - throws IOException { - StringBuilder builder = new StringBuilder(); - for (int i = 0; i < vectorLength; i++) { - char c = (char) input.read(); - if (c == '=') { - return builder.toString(); - } else { - builder.append(c); - } - } - return null; // no key found - } + /** Length of first page in an ogg file in bytes. */ + private static final int FIRST_PAGE_LENGTH = 58; + private static final int SECOND_PAGE_MAX_LENGTH = 64 * 1024 * 1024; + private static final int PACKET_TYPE_IDENTIFICATION = 1; + private static final int PACKET_TYPE_COMMENT = 3; + + /** Called when Reader finds identification header. */ + protected abstract void onVorbisCommentFound(); + + protected abstract void onVorbisCommentHeaderFound(VorbisCommentHeader header); + + /** + * Is called every time the Reader finds a content vector. The handler + * should return true if it wants to handle the content vector. + */ + protected abstract boolean onContentVectorKey(String content); + + /** + * Is called if onContentVectorKey returned true for the key. + */ + protected abstract void onContentVectorValue(String key, String value) throws VorbisCommentReaderException; + + protected abstract void onNoVorbisCommentFound(); + + protected abstract void onEndOfComment(); + + protected abstract void onError(VorbisCommentReaderException exception); + + public void readInputStream(InputStream input) throws VorbisCommentReaderException { + try { + // look for identification header + if (findIdentificationHeader(input)) { + onVorbisCommentFound(); + input = new OggInputStream(input); + if (findCommentHeader(input)) { + VorbisCommentHeader commentHeader = readCommentHeader(input); + onVorbisCommentHeaderFound(commentHeader); + for (int i = 0; i < commentHeader.getUserCommentLength(); i++) { + readUserComment(input); + } + onEndOfComment(); + } else { + onError(new VorbisCommentReaderException("No comment header found")); + } + } else { + onNoVorbisCommentFound(); + } + } catch (IOException e) { + onError(new VorbisCommentReaderException(e)); + } + } + + private void readUserComment(InputStream input) throws VorbisCommentReaderException { + try { + long vectorLength = EndianUtils.readSwappedUnsignedInteger(input); + String key = readContentVectorKey(input, vectorLength).toLowerCase(); + boolean readValue = onContentVectorKey(key); + if (readValue) { + String value = readUtf8String(input, (int) (vectorLength - key.length() - 1)); + onContentVectorValue(key, value); + } else { + IOUtils.skipFully(input, vectorLength - key.length() - 1); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + + private String readUtf8String(InputStream input, long length) throws IOException { + byte[] buffer = new byte[(int) length]; + IOUtils.readFully(input, buffer); + Charset charset = Charset.forName("UTF-8"); + return charset.newDecoder().decode(ByteBuffer.wrap(buffer)).toString(); + } + + /** + * Looks for an identification header in the first page of the file. If an + * identification header is found, it will be skipped completely and the + * method will return true, otherwise false. + */ + private boolean findIdentificationHeader(InputStream input) throws IOException { + byte[] buffer = new byte[FIRST_PAGE_LENGTH]; + IOUtils.readFully(input, buffer); + for (int i = 6; i < buffer.length; i++) { + if (buffer[i - 5] == 'v' && buffer[i - 4] == 'o' + && buffer[i - 3] == 'r' && buffer[i - 2] == 'b' + && buffer[i - 1] == 'i' && buffer[i] == 's' + && buffer[i - 6] == PACKET_TYPE_IDENTIFICATION) { + return true; + } + } + return false; + } + + private boolean findCommentHeader(InputStream input) throws IOException { + char[] buffer = new char["vorbis".length() + 1]; + for (int bytesRead = 0; bytesRead < SECOND_PAGE_MAX_LENGTH; bytesRead++) { + char c = (char) input.read(); + int dest = -1; + switch (c) { + case PACKET_TYPE_COMMENT: + dest = 0; + break; + case 'v': + dest = 1; + break; + case 'o': + dest = 2; + break; + case 'r': + dest = 3; + break; + case 'b': + dest = 4; + break; + case 'i': + dest = 5; + break; + case 's': + dest = 6; + break; + } + if (dest >= 0) { + buffer[dest] = c; + if (buffer[1] == 'v' && buffer[2] == 'o' && buffer[3] == 'r' + && buffer[4] == 'b' && buffer[5] == 'i' + && buffer[6] == 's' && buffer[0] == PACKET_TYPE_COMMENT) { + return true; + } + } else { + Arrays.fill(buffer, (char) 0); + } + } + return false; + } + + @NonNull + private VorbisCommentHeader readCommentHeader(InputStream input) throws IOException, VorbisCommentReaderException { + try { + long vendorLength = EndianUtils.readSwappedUnsignedInteger(input); + String vendorName = readUtf8String(input, vendorLength); + long userCommentLength = EndianUtils.readSwappedUnsignedInteger(input); + return new VorbisCommentHeader(vendorName, userCommentLength); + } catch (UnsupportedEncodingException e) { + throw new VorbisCommentReaderException(e); + } + } + + private String readContentVectorKey(InputStream input, long vectorLength) throws IOException { + StringBuilder builder = new StringBuilder(); + for (int i = 0; i < vectorLength; i++) { + char c = (char) input.read(); + if (c == '=') { + return builder.toString(); + } else { + builder.append(c); + } + } + return null; // no key found + } } -- cgit v1.2.3 From d0cc0359506b481d09f7d51b083f46ac914bb25f Mon Sep 17 00:00:00 2001 From: ByteHamster Date: Thu, 13 Feb 2020 01:07:31 +0100 Subject: Added support for opus files --- .../vorbiscommentreader/VorbisCommentReader.java | 75 ++++++++++------------ 1 file changed, 33 insertions(+), 42 deletions(-) (limited to 'core/src') diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/vorbiscommentreader/VorbisCommentReader.java b/core/src/main/java/de/danoeh/antennapod/core/util/vorbiscommentreader/VorbisCommentReader.java index e5924b1ab..e910e2be4 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/vorbiscommentreader/VorbisCommentReader.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/vorbiscommentreader/VorbisCommentReader.java @@ -9,11 +9,11 @@ import java.io.InputStream; import java.io.UnsupportedEncodingException; import java.nio.ByteBuffer; import java.nio.charset.Charset; -import java.util.Arrays; public abstract class VorbisCommentReader { /** Length of first page in an ogg file in bytes. */ - private static final int FIRST_PAGE_LENGTH = 58; + private static final int FIRST_OGG_PAGE_LENGTH = 58; + private static final int FIRST_OPUS_PAGE_LENGTH = 47; private static final int SECOND_PAGE_MAX_LENGTH = 64 * 1024 * 1024; private static final int PACKET_TYPE_IDENTIFICATION = 1; private static final int PACKET_TYPE_COMMENT = 3; @@ -93,13 +93,14 @@ public abstract class VorbisCommentReader { * method will return true, otherwise false. */ private boolean findIdentificationHeader(InputStream input) throws IOException { - byte[] buffer = new byte[FIRST_PAGE_LENGTH]; + byte[] buffer = new byte[FIRST_OPUS_PAGE_LENGTH]; IOUtils.readFully(input, buffer); + final byte[] oggIdentificationHeader = new byte[]{ PACKET_TYPE_IDENTIFICATION, 'v', 'o', 'r', 'b', 'i', 's' }; for (int i = 6; i < buffer.length; i++) { - if (buffer[i - 5] == 'v' && buffer[i - 4] == 'o' - && buffer[i - 3] == 'r' && buffer[i - 2] == 'b' - && buffer[i - 1] == 'i' && buffer[i] == 's' - && buffer[i - 6] == PACKET_TYPE_IDENTIFICATION) { + if (bufferMatches(buffer, oggIdentificationHeader, i)) { + IOUtils.skip(input, FIRST_OGG_PAGE_LENGTH - FIRST_OPUS_PAGE_LENGTH); + return true; + } else if (bufferMatches(buffer, "OpusHead".getBytes(), i)) { return true; } } @@ -107,47 +108,37 @@ public abstract class VorbisCommentReader { } private boolean findCommentHeader(InputStream input) throws IOException { - char[] buffer = new char["vorbis".length() + 1]; + byte[] buffer = new byte[64]; // Enough space for some bytes. Used circularly. + final byte[] oggCommentHeader = new byte[]{ PACKET_TYPE_COMMENT, 'v', 'o', 'r', 'b', 'i', 's' }; for (int bytesRead = 0; bytesRead < SECOND_PAGE_MAX_LENGTH; bytesRead++) { - char c = (char) input.read(); - int dest = -1; - switch (c) { - case PACKET_TYPE_COMMENT: - dest = 0; - break; - case 'v': - dest = 1; - break; - case 'o': - dest = 2; - break; - case 'r': - dest = 3; - break; - case 'b': - dest = 4; - break; - case 'i': - dest = 5; - break; - case 's': - dest = 6; - break; - } - if (dest >= 0) { - buffer[dest] = c; - if (buffer[1] == 'v' && buffer[2] == 'o' && buffer[3] == 'r' - && buffer[4] == 'b' && buffer[5] == 'i' - && buffer[6] == 's' && buffer[0] == PACKET_TYPE_COMMENT) { - return true; - } - } else { - Arrays.fill(buffer, (char) 0); + buffer[bytesRead % buffer.length] = (byte) input.read(); + if (bufferMatches(buffer, oggCommentHeader, bytesRead)) { + return true; + } else if (bufferMatches(buffer, "OpusTags".getBytes(), bytesRead)) { + return true; } } return false; } + /** + * Reads backwards in haystack, starting at position. Checks if the bytes match needle. + * Uses haystack circularly, so when reading at (-1), it reads at (length - 1). + */ + boolean bufferMatches(byte[] haystack, byte[] needle, int position) { + for (int i = 0; i < needle.length; i++) { + int posInHaystack = position - i; + while (posInHaystack < 0) { + posInHaystack += haystack.length; + } + posInHaystack = posInHaystack % haystack.length; + if (haystack[posInHaystack] != needle[needle.length - 1 - i]) { + return false; + } + } + return true; + } + @NonNull private VorbisCommentHeader readCommentHeader(InputStream input) throws IOException, VorbisCommentReaderException { try { -- cgit v1.2.3 From 3c6fd072e346da1f6649025c96aa29548c043ba4 Mon Sep 17 00:00:00 2001 From: ByteHamster Date: Thu, 13 Feb 2020 13:43:13 +0100 Subject: Added border to play button --- core/src/main/res/values/dimens.xml | 1 + 1 file changed, 1 insertion(+) (limited to 'core/src') diff --git a/core/src/main/res/values/dimens.xml b/core/src/main/res/values/dimens.xml index ee2c57ac4..bef2d311c 100644 --- a/core/src/main/res/values/dimens.xml +++ b/core/src/main/res/values/dimens.xml @@ -31,6 +31,7 @@ 16dp 48dp + 64dp 16dp 12dp -- cgit v1.2.3 From 5f9c70df0f5b9a3ad81fbf3f0789ede57757babf Mon Sep 17 00:00:00 2001 From: ByteHamster Date: Thu, 13 Feb 2020 13:47:30 +0100 Subject: Fixed seeking when streaming Sometimes, `media` does not know the duration. `getDuration()` loads directly from the `PlaybackService`. --- .../de/danoeh/antennapod/core/util/playback/PlaybackController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'core/src') diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/playback/PlaybackController.java b/core/src/main/java/de/danoeh/antennapod/core/util/playback/PlaybackController.java index cb22fbcc9..15b1f4432 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/playback/PlaybackController.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/playback/PlaybackController.java @@ -547,7 +547,7 @@ public class PlaybackController { */ public void onSeekBarStopTrackingTouch(SeekBar seekBar, float prog) { if (playbackService != null && media != null) { - playbackService.seekTo((int) (prog * media.getDuration())); + seekTo((int) (prog * getDuration())); } } -- cgit v1.2.3 From d7aa3f862acbb55a6ea15bde7fe549356b4daea6 Mon Sep 17 00:00:00 2001 From: ByteHamster Date: Tue, 18 Feb 2020 13:16:03 +0100 Subject: Removed some unused attrs --- core/src/main/res/drawable/overlay_drawable.xml | 20 -------------------- .../main/res/drawable/overlay_drawable_dark.xml | 15 --------------- .../drawable/overlay_drawable_dark_trueblack.xml | 15 --------------- core/src/main/res/values/attrs.xml | 12 ------------ core/src/main/res/values/styles.xml | 22 ---------------------- 5 files changed, 84 deletions(-) delete mode 100644 core/src/main/res/drawable/overlay_drawable.xml delete mode 100644 core/src/main/res/drawable/overlay_drawable_dark.xml delete mode 100644 core/src/main/res/drawable/overlay_drawable_dark_trueblack.xml (limited to 'core/src') diff --git a/core/src/main/res/drawable/overlay_drawable.xml b/core/src/main/res/drawable/overlay_drawable.xml deleted file mode 100644 index 185ffefc1..000000000 --- a/core/src/main/res/drawable/overlay_drawable.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/core/src/main/res/drawable/overlay_drawable_dark.xml b/core/src/main/res/drawable/overlay_drawable_dark.xml deleted file mode 100644 index fb78f5633..000000000 --- a/core/src/main/res/drawable/overlay_drawable_dark.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/core/src/main/res/drawable/overlay_drawable_dark_trueblack.xml b/core/src/main/res/drawable/overlay_drawable_dark_trueblack.xml deleted file mode 100644 index 5f58e8421..000000000 --- a/core/src/main/res/drawable/overlay_drawable_dark_trueblack.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/core/src/main/res/values/attrs.xml b/core/src/main/res/values/attrs.xml index 44c79567c..392365314 100644 --- a/core/src/main/res/values/attrs.xml +++ b/core/src/main/res/values/attrs.xml @@ -28,9 +28,7 @@ - - @@ -61,18 +59,8 @@ - - - - - - - - - - diff --git a/core/src/main/res/values/styles.xml b/core/src/main/res/values/styles.xml index f6c31f652..6eb72a8be 100644 --- a/core/src/main/res/values/styles.xml +++ b/core/src/main/res/values/styles.xml @@ -40,11 +40,7 @@ @drawable/ic_share_grey600_24dp @drawable/ic_list_grey600_24dp @drawable/ic_videocam_grey600_24dp - @color/white - @color/overlay_light - @drawable/overlay_drawable @drawable/ic_drag_vertical_grey600_48dp - @color/white @color/white @color/highlight_light @drawable/ic_new_releases_grey600_24dp @@ -77,11 +73,6 @@ @color/highlight_light @style/PreferenceThemeOverlay.v14.Material - - #e5e5e5 - #ffffff - #d2d2d2 - #000000