Skip to content

Commit

Permalink
fix:support for lyrics
Browse files Browse the repository at this point in the history
  • Loading branch information
ZTFtrue committed Feb 8, 2024
1 parent 2e210bf commit f77dcfb
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 39 deletions.
59 changes: 42 additions & 17 deletions app/src/main/java/com/ztftrue/music/MusicViewModel.kt
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,15 @@ import com.ztftrue.music.sqlData.model.DictionaryApp
import com.ztftrue.music.sqlData.model.MainTab
import com.ztftrue.music.sqlData.model.MusicItem
import com.ztftrue.music.ui.play.Lyrics
import com.ztftrue.music.utils.model.ListStringCaption
import com.ztftrue.music.utils.model.AnyListBase
import com.ztftrue.music.utils.model.Caption
import com.ztftrue.music.utils.CaptionUtils
import com.ztftrue.music.utils.model.EqualizerBand
import com.ztftrue.music.utils.LyricsType
import com.ztftrue.music.utils.PlayListType
import com.ztftrue.music.utils.ScrollDirectionType
import com.ztftrue.music.utils.Utils
import com.ztftrue.music.utils.model.AnyListBase
import com.ztftrue.music.utils.model.Caption
import com.ztftrue.music.utils.model.EqualizerBand
import com.ztftrue.music.utils.model.ListStringCaption
import java.io.File
import java.io.InputStream

Expand Down Expand Up @@ -93,7 +93,7 @@ class MusicViewModel : ViewModel() {

// lyrics
var itemDuration: Long = 1
var hasTime: LyricsType = LyricsType.TEXT
var lyricsType: LyricsType = LyricsType.TEXT
var currentCaptionList = mutableStateListOf<ListStringCaption>()

var fontSize = mutableIntStateOf(18)
Expand Down Expand Up @@ -152,18 +152,18 @@ class MusicViewModel : ViewModel() {
folder?.mkdirs()
val id = currentPlay.name.replace(regexPattern, "_")
val path = "${context.getExternalFilesDir(folderPath)?.absolutePath}/$id"
// context.getExternalFilesDir(folderPath)?.absolutePath + "/$id.lrc"
val text = File("$path.txt")
if (text.exists()) {
hasTime = LyricsType.TEXT
currentCaptionList.addAll(readLyricsOrText(text, context))
lyricsType = LyricsType.TEXT
currentCaptionList.addAll(readText(text, context))
} else if (File("$path.lrc").exists()) {
hasTime = LyricsType.LRC
lyricsType = LyricsType.LRC
currentCaptionList.addAll(readLyrics(File("$path.lrc"), context))
} else if (File("$path.srt").exists()) {
hasTime = LyricsType.SRT
lyricsType = LyricsType.SRT
currentCaptionList.addAll(readCaptions(File("$path.srt"), LyricsType.SRT))
} else if (File("$path.vtt").exists()) {
hasTime = LyricsType.VTT
lyricsType = LyricsType.VTT
currentCaptionList.addAll(readCaptions(File("$path.vtt"), LyricsType.VTT))
} else {
return
Expand All @@ -174,23 +174,48 @@ class MusicViewModel : ViewModel() {
itemDuration = duration / if (currentCaptionList.size == 0) 1 else currentCaptionList.size
}

private fun readLyricsOrText(file: File, context: Context): ArrayList<ListStringCaption> {
private fun readLyrics(file: File, context: Context): ArrayList<ListStringCaption> {
val arrayList = arrayListOf<ListStringCaption>()
val inputStream: InputStream = file.inputStream()
val inputString = inputStream.bufferedReader().use { it.readText() }
inputString.split("\n").forEach {
val lyricsHashMap: LinkedHashMap<Long, ListStringCaption> =
linkedMapOf()
inputString.split("\n").forEachIndexed { _, it ->
if (it.startsWith("offset:")) {
// TODO
// TODO
} else {
val captions = CaptionUtils.parseLyricLine(it, context)
val an = ListStringCaption(
text = captions.text.split(Regex("[\\n\\r\\s]+")),
text = ArrayList(captions.text.split(Regex("[\\r\\s]+"))),
timeStart = captions.timeStart,
timeEnd = captions.timeEnd
)
arrayList.add(an)
val temp = lyricsHashMap[captions.timeStart]
if (temp != null) {
temp.text.add("\n")
temp.text.addAll(captions.text.split("[\\r\\s]+"))
} else {
lyricsHashMap[captions.timeStart] = an
}
}
}
arrayList.addAll(lyricsHashMap.values)
return arrayList
}

private fun readText(file: File, context: Context): ArrayList<ListStringCaption> {
val arrayList = arrayListOf<ListStringCaption>()
val inputStream: InputStream = file.inputStream()
val inputString = inputStream.bufferedReader().use { it.readText() }
inputString.split("\n").forEach {
val captions = CaptionUtils.parseLyricLine(it, context)
val an = ListStringCaption(
text = ArrayList(captions.text.split(Regex("[\\n\\r\\s]+"))),
timeStart = captions.timeStart,
timeEnd = captions.timeEnd
)
arrayList.add(an)
}
return arrayList
}

Expand All @@ -207,7 +232,7 @@ class MusicViewModel : ViewModel() {
val arrayList = arrayListOf<ListStringCaption>()
captions.forEach {
val an = ListStringCaption(
text = it.text.split(Regex("[\\n\\r\\s]+")),
text = ArrayList(it.text.split(Regex("[\\n\\r\\s]+"))),
timeStart = it.timeStart,
timeEnd = it.timeEnd
)
Expand Down
43 changes: 23 additions & 20 deletions app/src/main/java/com/ztftrue/music/ui/play/LyricsView.kt
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,9 @@ import androidx.compose.ui.window.PopupProperties
import androidx.media3.common.util.UnstableApi
import com.ztftrue.music.MainActivity
import com.ztftrue.music.MusicViewModel
import com.ztftrue.music.utils.model.ListStringCaption
import com.ztftrue.music.utils.LyricsType
import com.ztftrue.music.utils.Utils
import com.ztftrue.music.utils.model.ListStringCaption
import com.ztftrue.music.utils.textToolbar.CustomTextToolbar
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
Expand All @@ -91,26 +91,29 @@ fun LyricsView(
var showMenu by remember { mutableStateOf(false) }
LaunchedEffect(musicViewModel.sliderPosition.floatValue) {
val timeState = musicViewModel.sliderPosition.floatValue

if (musicViewModel.hasTime == LyricsType.LRC) {
for ((index, entry) in musicViewModel.currentCaptionList.withIndex()) {
if (entry.timeStart > timeState) {
if (currentI != index) {
currentI = index
if (musicViewModel.autoScroll.value && isSelected && !showMenu) {
launch(Dispatchers.Main) {
// TODO calculate the scroll position by 
listState.scrollToItem(
if ((currentI - 1) < 0) 0 else (currentI - 1),
0
)
}
}
}
if (musicViewModel.lyricsType == LyricsType.LRC) {
var cIndex = 0;
for (index in musicViewModel.currentCaptionList.size - 1 downTo 0) {
val entry = musicViewModel.currentCaptionList[index]
if (timeState > entry.timeStart) {
cIndex = index
break
}
}
} else if (musicViewModel.hasTime == LyricsType.VTT || musicViewModel.hasTime == LyricsType.SRT) {
if (cIndex != currentI) {
currentI = cIndex
if (musicViewModel.autoScroll.value && isSelected && !showMenu) {
launch(Dispatchers.Main) {
// TODO calculate the scroll position by 
listState.scrollToItem(
if (currentI < 2) 0 else (currentI - 2),
0
)
}
}
}

} else if (musicViewModel.lyricsType == LyricsType.VTT || musicViewModel.lyricsType == LyricsType.SRT) {
val cIndex = musicViewModel.currentCaptionList.binarySearch {
if (it.timeStart <= timeState.toLong() && it.timeEnd >= timeState.toLong()) 0
else if (it.timeStart > timeState) {
Expand All @@ -124,7 +127,7 @@ fun LyricsView(
if (musicViewModel.autoScroll.value && isSelected && !showMenu) {
launch(Dispatchers.Main) {
// TODO calculate the scroll position by 
listState.scrollToItem(if ((currentI - 1) < 0) 0 else (currentI - 1), 0)
listState.scrollToItem(if (currentI < 2) 0 else (currentI - 2), 0)
}
}
}
Expand All @@ -135,7 +138,7 @@ fun LyricsView(
}.text.isNotEmpty()) {
if (musicViewModel.autoScroll.value && isSelected && !showMenu) {
launch(Dispatchers.Main) {
listState.scrollToItem(if ((currentI - 1) < 0) 0 else (currentI - 1), 0)
listState.scrollToItem(if (currentI <2) 0 else (currentI - 2), 0)
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions app/src/main/java/com/ztftrue/music/utils/model/Model.kt
Original file line number Diff line number Diff line change
Expand Up @@ -80,13 +80,13 @@ data class EqualizerBand(
) : Parcelable

data class Caption(
val text: String,
var text: String,
val timeStart: Long,
val timeEnd: Long=0
)

data class ListStringCaption(
val text: List<String>,
val text: ArrayList<String>,
val timeStart: Long,
val timeEnd: Long=0
)

0 comments on commit f77dcfb

Please sign in to comment.