Use a single format for short timecodes
It is unlikely that multiple formats for short timecodes would be used in one document. Therefor we will parse all the short timecodes to see if they are all less then the duration as HH:MM. If they are we will use that, otherwise we will parse them as MM:SS.
This commit is contained in:
parent
c49e98b546
commit
e94e4bc3d0
@ -110,12 +110,14 @@ public class TimelineTest extends InstrumentationTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void testProcessShownotesAddTimecodeMultipleShortFormatNoChapters() throws Exception {
|
public void testProcessShownotesAddTimecodeMultipleShortFormatNoChapters() throws Exception {
|
||||||
|
|
||||||
|
// One of these timecodes fits as HH:MM and one does not so both should be parsed as MM:SS.
|
||||||
final String[] timeStrings = new String[]{ "10:12", "2:12" };
|
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);
|
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);
|
Timeline t = new Timeline(context, p);
|
||||||
String res = t.processShownotes(true);
|
String res = t.processShownotes(true);
|
||||||
checkLinkCorrect(res, new long[]{ 10 * 60 * 1000 + 12 * 1000, 2 * 60 * 60 * 1000 + 12 * 60 * 1000 }, timeStrings);
|
checkLinkCorrect(res, new long[]{ 10 * 60 * 1000 + 12 * 1000, 2 * 60 * 1000 + 12 * 1000 }, timeStrings);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testProcessShownotesAddTimecodeParentheses() throws Exception {
|
public void testProcessShownotesAddTimecodeParentheses() throws Exception {
|
||||||
|
@ -170,70 +170,64 @@ public class Timeline {
|
|||||||
Elements elementsWithTimeCodes = document.body().getElementsMatchingOwnText(TIMECODE_REGEX);
|
Elements elementsWithTimeCodes = document.body().getElementsMatchingOwnText(TIMECODE_REGEX);
|
||||||
Log.d(TAG, "Recognized " + elementsWithTimeCodes.size() + " timecodes");
|
Log.d(TAG, "Recognized " + elementsWithTimeCodes.size() + " timecodes");
|
||||||
|
|
||||||
// Assuming the timecodes are going to increase through the document loop through the
|
if (elementsWithTimeCodes.size() == 0) {
|
||||||
// elements backwards so we can determine when/if we need to shift from HH:MM to MM:SS
|
// No elements with timecodes
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int playableDuration = playable == null ? Integer.MAX_VALUE : playable.getDuration();
|
||||||
boolean useHourFormat = true;
|
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
|
if (playableDuration != Integer.MAX_VALUE) {
|
||||||
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
|
// We need to decide if we are going to treat short timecodes as HH:MM or MM:SS. To do
|
||||||
// non-reversed order.
|
// so we will parse all the short timecodes and see if they fit in the duration. If one
|
||||||
ArrayList<String> replacements = new ArrayList<>();
|
// does not we will use MM:SS, otherwise all will be parsed as HH:MM.
|
||||||
for (Pair<Boolean, String> matchPair : matches) {
|
for (Element element : elementsWithTimeCodes) {
|
||||||
boolean isLongFormat = matchPair.first;
|
Matcher matcherForElement = TIMECODE_REGEX.matcher(element.html());
|
||||||
String group = matchPair.second;
|
while (matcherForElement.find()) {
|
||||||
int time = isLongFormat
|
|
||||||
? Converter.durationStringLongToMs(group)
|
|
||||||
: Converter.durationStringShortToMs(group, useHourFormat);
|
|
||||||
|
|
||||||
String rep = group;
|
// We only want short timecodes right now.
|
||||||
if (playable == null) {
|
if (matcherForElement.group(1) == null) {
|
||||||
rep = createTimeLink(time, group);
|
int time = Converter.durationStringShortToMs(matcherForElement.group(0), true);
|
||||||
} else {
|
|
||||||
int duration = playable.getDuration();
|
|
||||||
|
|
||||||
if (duration > time) {
|
// If the parsed timecode is greater then the duration then we know we need to
|
||||||
rep = createTimeLink(time, group);
|
// use the minute format so we are done.
|
||||||
} else if (!isLongFormat && useHourFormat) {
|
if (time > playableDuration) {
|
||||||
|
|
||||||
// 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;
|
useHourFormat = false;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
replacements.add(0, rep);
|
if (!useHourFormat) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Now that we have all the replacements, replace.
|
for (Element element : elementsWithTimeCodes) {
|
||||||
|
|
||||||
|
Matcher matcherForElement = TIMECODE_REGEX.matcher(element.html());
|
||||||
StringBuffer buffer = new StringBuffer();
|
StringBuffer buffer = new StringBuffer();
|
||||||
int index = 0;
|
|
||||||
matcherLong.reset();
|
while (matcherForElement.find()) {
|
||||||
while (matcherLong.find()) {
|
String group = matcherForElement.group(0);
|
||||||
matcherLong.appendReplacement(buffer, replacements.get(index));
|
|
||||||
index++;
|
int time = matcherForElement.group(1) != null
|
||||||
|
? Converter.durationStringLongToMs(group)
|
||||||
|
: Converter.durationStringShortToMs(group, useHourFormat);
|
||||||
|
|
||||||
|
String replacementText = group;
|
||||||
|
if (time < playableDuration) {
|
||||||
|
replacementText = String.format(Locale.getDefault(), TIMECODE_LINK, time, group);
|
||||||
|
}
|
||||||
|
|
||||||
|
matcherForElement.appendReplacement(buffer, replacementText);
|
||||||
}
|
}
|
||||||
|
|
||||||
matcherLong.appendTail(buffer);
|
matcherForElement.appendTail(buffer);
|
||||||
element.html(buffer.toString());
|
element.html(buffer.toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private String createTimeLink(int time, String group) {
|
|
||||||
return String.format(Locale.getDefault(), TIMECODE_LINK, time, group);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user