summaryrefslogtreecommitdiff
path: root/src/de/danoeh/antennapod/util/playback
diff options
context:
space:
mode:
authordaniel oeh <daniel.oeh@gmail.com>2014-06-29 02:38:25 +0200
committerdaniel oeh <daniel.oeh@gmail.com>2014-06-29 02:50:09 +0200
commitc9c69aa7c796da59c29fad2c4d4c9464d353416b (patch)
tree57d0d94d11a46fda5ea38b85d35573393f89ed35 /src/de/danoeh/antennapod/util/playback
parent2633d17046ab2373d0f1a8976a16a3e0ee15a5cf (diff)
downloadAntennaPod-c9c69aa7c796da59c29fad2c4d4c9464d353416b.zip
Added first implementation of the Timeline class
Diffstat (limited to 'src/de/danoeh/antennapod/util/playback')
-rw-r--r--src/de/danoeh/antennapod/util/playback/Timeline.java152
1 files changed, 152 insertions, 0 deletions
diff --git a/src/de/danoeh/antennapod/util/playback/Timeline.java b/src/de/danoeh/antennapod/util/playback/Timeline.java
new file mode 100644
index 000000000..6e00f725c
--- /dev/null
+++ b/src/de/danoeh/antennapod/util/playback/Timeline.java
@@ -0,0 +1,152 @@
+package de.danoeh.antennapod.util.playback;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.util.Log;
+import android.util.TypedValue;
+
+import org.jsoup.Jsoup;
+import org.jsoup.nodes.Document;
+import org.jsoup.nodes.Element;
+import org.jsoup.select.Elements;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import de.danoeh.antennapod.BuildConfig;
+import de.danoeh.antennapod.util.Converter;
+import de.danoeh.antennapod.util.ShownotesProvider;
+
+/**
+ * Connects chapter information and shownotes of a shownotesProvider, for example by making it possible to use the
+ * shownotes to navigate to another position in the podcast or by highlighting certain parts of the shownotesProvider's
+ * shownotes.
+ * <p/>
+ * 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";
+
+ private static final String WEBVIEW_STYLE = "<style type=\"text/css\"> @font-face { font-family: 'Roboto-Light'; src: url('file:///android_asset/Roboto-Light.ttf'); } * { color: %s; font-family: roboto-Light; font-size: 11pt; } a { font-style: normal; text-decoration: none; font-weight: normal; color: #00A8DF; } img { display: block; margin: 10 auto; max-width: %s; height: auto; } body { margin: %dpx %dpx %dpx %dpx; }";
+
+
+ private ShownotesProvider shownotesProvider;
+
+
+ private final String colorString;
+ private final int pageMargin;
+
+ public Timeline(Context context, ShownotesProvider shownotesProvider) {
+ if (shownotesProvider == null) throw new IllegalArgumentException("shownotesProvider = null");
+ this.shownotesProvider = shownotesProvider;
+
+ TypedArray res = context
+ .getTheme()
+ .obtainStyledAttributes(
+ new int[]{android.R.attr.textColorPrimary});
+ int colorResource = res.getColor(0, 0);
+ colorString = String.format("#%06X",
+ 0xFFFFFF & colorResource);
+ res.recycle();
+
+ pageMargin = (int) TypedValue.applyDimension(
+ TypedValue.COMPLEX_UNIT_DIP, 8, context.getResources()
+ .getDisplayMetrics()
+ );
+ }
+
+ private static final Pattern TIMECODE_LINK_REGEX = Pattern.compile("antennapod://timecode/((\\d+))");
+ private static final String TIMECODE_LINK = "<a href=\"antennapod://timecode/%d\">%s</a>";
+ private static final Pattern TIMECODE_REGEX = Pattern.compile("\\b(?:(?:(([0-9][0-9])):))?(([0-9][0-9])):(([0-9][0-9]))\\b");
+
+ /**
+ * Applies an app-specific CSS stylesheet and adds timecode links (optional).
+ * <p/>
+ * 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.
+ */
+ public String processShownotes(final boolean addTimecodes) {
+
+ // load shownotes
+
+ String shownotes;
+ try {
+ shownotes = shownotesProvider.loadShownotes().call();
+ } catch (Exception e) {
+ e.printStackTrace();
+ return null;
+ }
+ if (shownotes == null) {
+ if (BuildConfig.DEBUG)
+ Log.d(TAG, "shownotesProvider contained no shownotes. Returning empty string");
+ return "";
+ }
+
+ Document document = Jsoup.parse(shownotes);
+
+ // apply style
+ String styleStr = String.format(WEBVIEW_STYLE, colorString, "100%", pageMargin,
+ pageMargin, pageMargin, pageMargin);
+ document.head().appendElement("style").attr("type", "text/css").text(styleStr);
+
+ // apply timecode links
+ if (addTimecodes) {
+ Elements elementsWithTimeCodes = document.body().getElementsMatchingOwnText(TIMECODE_REGEX);
+ if (BuildConfig.DEBUG)
+ Log.d(TAG, "Recognized " + elementsWithTimeCodes.size() + " timecodes");
+ for (Element element : elementsWithTimeCodes) {
+ Matcher matcherLong = TIMECODE_REGEX.matcher(element.text());
+ StringBuffer buffer = new StringBuffer();
+ while (matcherLong.find()) {
+ String h = matcherLong.group(1);
+ String group = matcherLong.group(0);
+ long time = (h != null) ? Converter.durationStringLongToMs(group) :
+ Converter.durationStringShortToMs(group);
+ String rep = String.format(TIMECODE_LINK, time, group);
+ matcherLong.appendReplacement(buffer, rep);
+ }
+
+ element.html(buffer.toString());
+ }
+ }
+
+ Log.i(TAG, "Out: " + document.toString());
+ return document.toString();
+ }
+
+
+ /**
+ * Returns true if the given link is a timecode link.
+ */
+ public static boolean isTimecodeLink(String link) {
+ return link != null && link.matches(TIMECODE_LINK_REGEX.pattern());
+ }
+
+ /**
+ * Returns the time in milliseconds that is attached to this link or -1
+ * if the link is no valid timecode link.
+ */
+ public static long getTimecodeLinkTime(String link) {
+ if (isTimecodeLink(link)) {
+ Matcher m = TIMECODE_LINK_REGEX.matcher(link);
+
+ try {
+ if (m.find()) {
+ return Long.valueOf(m.group(1));
+ }
+ } catch (NumberFormatException e) {
+ e.printStackTrace();
+ }
+ }
+ return -1;
+ }
+
+
+ public void setShownotesProvider(ShownotesProvider shownotesProvider) {
+ if (shownotesProvider == null) throw new IllegalArgumentException("shownotesProvider = null");
+ this.shownotesProvider = shownotesProvider;
+ }
+}