summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--app/src/androidTest/java/de/test/antennapod/util/playback/TimelineTest.java60
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/util/playback/Timeline.java98
2 files changed, 118 insertions, 40 deletions
diff --git a/app/src/androidTest/java/de/test/antennapod/util/playback/TimelineTest.java b/app/src/androidTest/java/de/test/antennapod/util/playback/TimelineTest.java
index 40e6605d7..dcec1c61f 100644
--- a/app/src/androidTest/java/de/test/antennapod/util/playback/TimelineTest.java
+++ b/app/src/androidTest/java/de/test/antennapod/util/playback/TimelineTest.java
@@ -30,12 +30,12 @@ public class TimelineTest extends InstrumentationTestCase {
context = getInstrumentation().getTargetContext();
}
- private Playable newTestPlayable(List<Chapter> chapters, String shownotes) {
+ private Playable newTestPlayable(List<Chapter> chapters, String shownotes, int duration) {
FeedItem item = new FeedItem(0, "Item", "item-id", "http://example.com/item", new Date(), FeedItem.PLAYED, null);
item.setChapters(chapters);
item.setContentEncoded(shownotes);
FeedMedia media = new FeedMedia(item, "http://example.com/episode", 100, "audio/mp3");
- media.setDuration(Integer.MAX_VALUE);
+ media.setDuration(duration);
item.setMedia(media);
return media;
}
@@ -44,7 +44,27 @@ public class TimelineTest extends InstrumentationTestCase {
final String timeStr = "10:11:12";
final long time = 3600 * 1000 * 10 + 60 * 1000 * 11 + 12 * 1000;
- Playable p = newTestPlayable(null, "<p> Some test text with a timecode " + timeStr + " here.</p>");
+ Playable p = newTestPlayable(null, "<p> Some test text with a timecode " + timeStr + " here.</p>", Integer.MAX_VALUE);
+ Timeline t = new Timeline(context, p);
+ String res = t.processShownotes(true);
+ checkLinkCorrect(res, new long[]{time}, new String[]{timeStr});
+ }
+
+ public void testProcessShownotesAddTimecodeHHMMNoChapters() throws Exception {
+ final String timeStr = "10:11";
+ final long time = 3600 * 1000 * 10 + 60 * 1000 * 11;
+
+ Playable p = newTestPlayable(null, "<p> Some test text with a timecode " + timeStr + " here.</p>", Integer.MAX_VALUE);
+ Timeline t = new Timeline(context, p);
+ String res = t.processShownotes(true);
+ checkLinkCorrect(res, new long[]{time}, new String[]{timeStr});
+ }
+
+ public void testProcessShownotesAddTimecodeMMSSNoChapters() throws Exception {
+ final String timeStr = "10:11";
+ final long time = 10 * 60 * 1000 + 11 * 1000;
+
+ Playable p = newTestPlayable(null, "<p> Some test text with a timecode " + timeStr + " here.</p>", 11 * 60 * 1000);
Timeline t = new Timeline(context, p);
String res = t.processShownotes(true);
checkLinkCorrect(res, new long[]{time}, new String[]{timeStr});
@@ -54,7 +74,7 @@ public class TimelineTest extends InstrumentationTestCase {
final String timeStr = "2:11:12";
final long time = 2 * 60 * 60 * 1000 + 11 * 60 * 1000 + 12 * 1000;
- Playable p = newTestPlayable(null, "<p> Some test text with a timecode " + timeStr + " here.</p>");
+ Playable p = newTestPlayable(null, "<p> Some test text with a timecode " + timeStr + " here.</p>", Integer.MAX_VALUE);
Timeline t = new Timeline(context, p);
String res = t.processShownotes(true);
checkLinkCorrect(res, new long[]{time}, new String[]{timeStr});
@@ -64,47 +84,55 @@ public class TimelineTest extends InstrumentationTestCase {
final String timeStr = "1:12";
final long time = 60 * 1000 + 12 * 1000;
- Playable p = newTestPlayable(null, "<p> Some test text with a timecode " + timeStr + " here.</p>");
+ Playable p = newTestPlayable(null, "<p> Some test text with a timecode " + timeStr + " here.</p>", 2 * 60 * 1000);
Timeline t = new Timeline(context, p);
String res = t.processShownotes(true);
checkLinkCorrect(res, new long[]{time}, new String[]{timeStr});
}
- public void testProcessShownotesAddTimecodeMMSSNoChapters() throws Exception {
- final String timeStr = "10:11";
- final long time = 60 * 1000 * 10 + 1000 * 11;
+ public void testProcessShownotesAddTimecodeMultipleFormatsNoChapters() throws Exception {
+ final String[] timeStrings = new String[]{ "10:12", "1:10:12" };
- Playable p = newTestPlayable(null, "<p> Some test text with a timecode " + timeStr + " here.</p>");
+ Playable p = newTestPlayable(null, "<p> Some test text with a timecode " + timeStrings[0] + " here. Hey look another one " + timeStrings[1] + " here!</p>", 2 * 60 * 60 * 1000);
Timeline t = new Timeline(context, p);
String res = t.processShownotes(true);
- checkLinkCorrect(res, new long[]{time}, new String[]{timeStr});
+ checkLinkCorrect(res, new long[]{ 10 * 60 * 1000 + 12 * 1000, 60 * 60 * 1000 + 10 * 60 * 1000 + 12 * 1000 }, timeStrings);
+ }
+
+ public void testProcessShownotesAddTimecodeMultipleShortFormatNoChapters() throws Exception {
+ final String[] timeStrings = new String[]{ "10:12", "2:12" };
+
+ Playable p = newTestPlayable(null, "<p> Some test text with a timecode " + timeStrings[0] + " here. Hey look another one " + timeStrings[1] + " here!</p>", 3 * 60 * 60 * 1000);
+ Timeline t = new Timeline(context, p);
+ String res = t.processShownotes(true);
+ checkLinkCorrect(res, new long[]{ 10 * 60 * 1000 + 12 * 1000, 2 * 60 * 60 * 1000 + 12 * 60 * 1000 }, timeStrings);
}
public void testProcessShownotesAddTimecodeParentheses() throws Exception {
- final String timeStr = "10:11:00";
+ final String timeStr = "10:11";
final long time = 3600 * 1000 * 10 + 60 * 1000 * 11;
- Playable p = newTestPlayable(null, "<p> Some test text with a timecode (" + timeStr + ") here.</p>");
+ Playable p = newTestPlayable(null, "<p> Some test text with a timecode (" + timeStr + ") here.</p>", Integer.MAX_VALUE);
Timeline t = new Timeline(context, p);
String res = t.processShownotes(true);
checkLinkCorrect(res, new long[]{time}, new String[]{timeStr});
}
public void testProcessShownotesAddTimecodeBrackets() throws Exception {
- final String timeStr = "10:11:00";
+ final String timeStr = "10:11";
final long time = 3600 * 1000 * 10 + 60 * 1000 * 11;
- Playable p = newTestPlayable(null, "<p> Some test text with a timecode [" + timeStr + "] here.</p>");
+ Playable p = newTestPlayable(null, "<p> Some test text with a timecode [" + timeStr + "] here.</p>", Integer.MAX_VALUE);
Timeline t = new Timeline(context, p);
String res = t.processShownotes(true);
checkLinkCorrect(res, new long[]{time}, new String[]{timeStr});
}
public void testProcessShownotesAddTimecodeAngleBrackets() throws Exception {
- final String timeStr = "10:11:00";
+ final String timeStr = "10:11";
final long time = 3600 * 1000 * 10 + 60 * 1000 * 11;
- Playable p = newTestPlayable(null, "<p> Some test text with a timecode <" + timeStr + "> here.</p>");
+ Playable p = newTestPlayable(null, "<p> Some test text with a timecode <" + timeStr + "> here.</p>", Integer.MAX_VALUE);
Timeline t = new Timeline(context, p);
String res = t.processShownotes(true);
checkLinkCorrect(res, new long[]{time}, new String[]{timeStr});
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 22349b029..5b58596f7 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
@@ -7,6 +7,7 @@ import android.support.annotation.ColorInt;
import android.support.annotation.NonNull;
import android.text.TextUtils;
import android.util.Log;
+import android.util.Pair;
import android.util.TypedValue;
import org.jsoup.Jsoup;
@@ -14,6 +15,7 @@ import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
+import java.util.ArrayList;
import java.util.Locale;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -127,35 +129,12 @@ public class Timeline {
// apply timecode links
if (addTimecodes) {
- Elements elementsWithTimeCodes = document.body().getElementsMatchingOwnText(TIMECODE_REGEX);
- Log.d(TAG, "Recognized " + elementsWithTimeCodes.size() + " timecodes");
- for (Element element : elementsWithTimeCodes) {
- Matcher matcherLong = TIMECODE_REGEX.matcher(element.html());
- StringBuffer buffer = new StringBuffer();
- while (matcherLong.find()) {
- String h = matcherLong.group(1);
- String group = matcherLong.group(0);
- int time = (h != null) ? Converter.durationStringLongToMs(group) :
- Converter.durationStringShortToMs(group);
-
- String rep;
- if (playable == null || playable.getDuration() > time) {
- rep = String.format(Locale.getDefault(), TIMECODE_LINK, time, group);
- } else {
- rep = group;
- }
- matcherLong.appendReplacement(buffer, rep);
- }
- matcherLong.appendTail(buffer);
-
- element.html(buffer.toString());
- }
+ addTimecodes(document, playable);
}
return document.toString();
}
-
/**
* Returns true if the given link is a timecode link.
*/
@@ -186,4 +165,75 @@ public class Timeline {
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");
+
+ // Assuming the timecodes are going to increase through the document loop through the
+ // elements backwards so we can determine when/if we need to shift from HH:MM to MM:SS
+ boolean useHourFormat = true;
+ for (int i = elementsWithTimeCodes.size() - 1; i >= 0 ; i--) {
+ Element element = elementsWithTimeCodes.get(i);
+ Matcher matcherLong = TIMECODE_REGEX.matcher(element.html());
+
+ // Get all matches and store in reverse order
+ ArrayList<Pair<Boolean, String>> matches = new ArrayList<>();
+ while (matcherLong.find()) {
+ matches.add(0, new Pair<>(matcherLong.group(1) != null, matcherLong.group(0)));
+ }
+
+ // Now loop through the reversed matches and get the replacements. Store them in
+ // non-reversed order.
+ ArrayList<String> replacements = new ArrayList<>();
+ for (Pair<Boolean, String> matchPair : matches) {
+ boolean isLongFormat = matchPair.first;
+ String group = matchPair.second;
+ int time = isLongFormat
+ ? Converter.durationStringLongToMs(group)
+ : Converter.durationStringShortToMs(group, useHourFormat);
+
+ String rep = group;
+ if (playable == null) {
+ rep = createTimeLink(time, group);
+ } else {
+ int duration = playable.getDuration();
+
+ if (duration > time) {
+ rep = createTimeLink(time, group);
+ } else if (!isLongFormat && useHourFormat) {
+
+ // The duration calculated in hours is too long and the timecode format is
+ // short. So try and see if it will work when treated as minutes.
+ time = Converter.durationStringShortToMs(group, false);
+
+ if (duration > time) {
+ // We have found the treating a short timecode as minutes works, do that
+ // from now on.
+ rep = createTimeLink(time, group);
+ useHourFormat = false;
+ }
+ }
+ }
+
+ replacements.add(0, rep);
+ }
+
+ // Now that we have all the replacements, replace.
+ StringBuffer buffer = new StringBuffer();
+ int index = 0;
+ matcherLong.reset();
+ while (matcherLong.find()) {
+ matcherLong.appendReplacement(buffer, replacements.get(index));
+ index++;
+ }
+
+ matcherLong.appendTail(buffer);
+ element.html(buffer.toString());
+ }
+ }
+
+ private String createTimeLink(int time, String group) {
+ return String.format(Locale.getDefault(), TIMECODE_LINK, time, group);
+ }
}