Skip to content

Commit

Permalink
some ttml legwork
Browse files Browse the repository at this point in the history
  • Loading branch information
nift4 committed Feb 6, 2025
1 parent 1197c39 commit f495e08
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -638,19 +638,83 @@ private val tt = "http://www.w3.org/ns/ttml"
private val ttm = "http://www.w3.org/ns/ttml#metadata"
private val itunes = "http://itunes.apple.com/lyric-ttml-extensions"
private val itunesInternal = "http://music.apple.com/lyric-ttml-internal"
private fun XmlPullParser.skipToEndOfTag() {
if (eventType != XmlPullParser.START_TAG)
throw XmlPullParserException("expected start tag in skipToEndOfTag()")
while (next() != XmlPullParser.END_TAG) {
// we have a child tag!
if (eventType == XmlPullParser.START_TAG)
skipToEndOfTag()
else if (eventType != XmlPullParser.TEXT)
throw XmlPullParserException("expected start tag or text in skipToEndOfTag()")
// else: we have some text, boring
}
}
private fun XmlPullParser.nextAndThrowIfNotEnd() {
if (next() != XmlPullParser.END_TAG)
throw XmlPullParserException("expected end tag in nextAndThrowIfNotEnd()")
}
private fun XmlPullParser.nextAndThrowIfNotText() {
if (next() != XmlPullParser.TEXT)
throw XmlPullParserException("expected end tag in nextAndThrowIfNotText()")
}
fun parseTtml(lyricText: String, trimEnabled: Boolean): SemanticLyrics? {
val parser = Xml.newPullParser()
parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true)
parser.setInput(StringReader(lyricText))
try {
parser.next()
parser.nextTag()
parser.require(XmlPullParser.START_TAG, tt, "tt")
} catch (_: XmlPullParserException) {
return null // not ttml
}
val lang = parser.getAttributeValue("http://www.w3.org/XML/1998/namespace", "lang")
val timing = parser.getAttributeValue(itunesInternal, "timing")
while (parser.next() != XmlPullParser.END_TAG) {
parser.nextTag()
parser.require(XmlPullParser.START_TAG, tt, "head")
// TODO parse and reject based on https://www.w3.org/TR/2018/REC-ttml2-20181108/#feature-profile-version-2 to be compliant
// TODO https://www.w3.org/TR/2018/REC-ttml2-20181108/#timing-attribute-dur
while (parser.nextTag() != XmlPullParser.END_TAG) {
if (parser.name == "metadata") {
while (parser.nextTag() != XmlPullParser.END_TAG) {
if (parser.namespace == ttm && parser.name == "agent") {
val id = parser.getAttributeValue("http://www.w3.org/XML/1998/namespace", "id")
val type = parser.getAttributeValue(ttm, "lang")
// TODO do something with this information
parser.nextAndThrowIfNotEnd()
}
if (parser.name == "iTunesMetadata") {
while (parser.nextTag() != XmlPullParser.END_TAG) {
if (parser.name == "songwriters") {
while (parser.nextTag() != XmlPullParser.END_TAG) {
if (parser.name == "songwriter") {
parser.nextAndThrowIfNotText()
val songwriter = parser.text
// TODO do something with this information
parser.nextAndThrowIfNotEnd()
} else {
throw XmlPullParserException("expected <songwriter>, got " +
"<${(parser.prefix?.plus(":") ?: "") + parser.name}> " +
"in <songwriters> in <iTunesMetadata>")
}
}
} else {
throw XmlPullParserException("unknown element " +
"<${(parser.prefix?.plus(":") ?: "") + parser.name}> in " +
"<iTunesMetadata>")
}
}
parser.nextAndThrowIfNotEnd()
}
}
} else // probably <styling> or <layout>
parser.skipToEndOfTag()
}
parser.require(XmlPullParser.END_TAG, tt, "head")
parser.next()
parser.require(XmlPullParser.START_TAG, tt, "body")
while (parser.nextTag() != XmlPullParser.END_TAG) {
parser.skipToEndOfTag() // TODO parse <body>
}
return null
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ class FullBottomSheet
}

override fun onStopTrackingTouch(seekBar: SeekBar?) {
val mediaId = instance?.currentMediaItem?.mediaId
val mediaId = instance?.currentMediaItem
if (mediaId != null) {
if (seekBar != null) {
instance?.seekTo((seekBar.progress.toLong()))
Expand All @@ -174,7 +174,7 @@ class FullBottomSheet
}

override fun onStopTrackingTouch(slider: Slider) {
val mediaId = instance?.currentMediaItem?.mediaId
val mediaId = instance?.currentMediaItem
if (mediaId != null) {
instance?.seekTo((slider.value.toLong()))
bottomSheetFullLyricView.updateLyricPositionFromPlaybackPos()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,19 @@ import android.view.View.VISIBLE
import android.view.ViewGroup
import android.view.animation.PathInterpolator
import android.widget.TextView
import androidx.annotation.OptIn
import androidx.core.animation.doOnEnd
import androidx.core.graphics.TypefaceCompat
import androidx.core.view.HapticFeedbackConstantsCompat
import androidx.core.view.ViewCompat
import androidx.core.view.doOnLayout
import androidx.media3.common.util.UnstableApi
import androidx.preference.PreferenceManager
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.card.MaterialCardView
import org.akanework.gramophone.R
import org.akanework.gramophone.logic.GramophonePlaybackService
import org.akanework.gramophone.logic.dpToPx
import org.akanework.gramophone.logic.getBooleanStrict
import org.akanework.gramophone.logic.ui.CustomSmoothScroller
Expand Down Expand Up @@ -55,6 +58,7 @@ class LegacyLyricsAdapter(
private var currentTranslationPos = -1
private var isBoldEnabled = false
private var isLyricCentered = false
private var forceNoAnimation = false
private val sizeFactor = 1f
private val defaultSizeFactor = .97f

Expand Down Expand Up @@ -198,6 +202,7 @@ class LegacyLyricsAdapter(
fun updateLyricStatus() {
isBoldEnabled = prefs.getBooleanStrict("lyric_bold", false)
isLyricCentered = prefs.getBooleanStrict("lyric_center", false)
forceNoAnimation = prefs.getBooleanStrict("lyric_no_animation", false)
}

override fun getItemCount(): Int = lyricList.size
Expand Down Expand Up @@ -310,7 +315,7 @@ class LegacyLyricsAdapter(
}

fun smoothScrollTo(position: Int, noAnimation: Boolean = false) {
val smoothScroller = createSmoothScroller(noAnimation)
val smoothScroller = createSmoothScroller(noAnimation || forceNoAnimation)
smoothScroller.targetPosition = position
recyclerView!!.layoutManager!!.startSmoothScroll(
smoothScroller
Expand Down Expand Up @@ -339,9 +344,12 @@ class LegacyLyricsAdapter(
}
}

// https://github.com/androidx/media/issues/1578
@OptIn(UnstableApi::class)
private fun updateNewIndex(): Int {
val filteredList = lyricList.filterIndexed { _, lyric ->
(lyric.timeStamp ?: 0) <= (instance?.currentPosition ?: 0)
(lyric.timeStamp ?: 0) <= (GramophonePlaybackService.instanceForWidgetAndLyricsOnly
?.endedWorkaroundPlayer?.currentPosition ?: instance?.currentPosition ?: 0)
}

return if (filteredList.isNotEmpty()) {
Expand Down

0 comments on commit f495e08

Please sign in to comment.