Fixed lyrics crash

This commit is contained in:
Prathamesh More 2021-12-20 22:13:45 +05:30
parent 9fc25b71ce
commit ff2574fffc
9 changed files with 249 additions and 279 deletions

View file

@ -36,7 +36,6 @@ import code.name.monkey.retromusic.model.Song
import code.name.monkey.retromusic.util.MusicUtil import code.name.monkey.retromusic.util.MusicUtil
import code.name.monkey.retromusic.util.PreferenceUtil import code.name.monkey.retromusic.util.PreferenceUtil
import code.name.monkey.retromusic.util.color.MediaNotificationProcessor import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
import com.google.android.material.bottomsheet.BottomSheetBehavior.STATE_EXPANDED
import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.dialog.MaterialAlertDialogBuilder
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@ -108,11 +107,6 @@ class AlbumCoverPagerAdapter(
val view = inflater.inflate(getLayoutWithPlayerTheme(), container, false) val view = inflater.inflate(getLayoutWithPlayerTheme(), container, false)
ViewCompat.setTransitionName(view, "lyrics") ViewCompat.setTransitionName(view, "lyrics")
albumCover = view.findViewById(R.id.player_image) albumCover = view.findViewById(R.id.player_image)
view.setOnClickListener {
if (mainActivity.getBottomSheetBehavior().state == STATE_EXPANDED) {
showLyricsDialog()
}
}
return view return view
} }

View file

@ -85,6 +85,10 @@ abstract class AbsPlayerFragment(@LayoutRes layout: Int) : AbsMainActivityFragme
showLyricsIcon(item) showLyricsIcon(item)
return true return true
} }
R.id.action_go_to_lyrics -> {
goToLyrics(requireActivity())
return true
}
R.id.action_toggle_favorite -> { R.id.action_toggle_favorite -> {
toggleFavorite(song) toggleFavorite(song)
return true return true

View file

@ -231,13 +231,7 @@ class LyricsFragment : AbsMusicServiceFragment(R.layout.fragment_lyrics) {
@SuppressLint("CheckResult") @SuppressLint("CheckResult")
private fun editSyncedLyrics() { private fun editSyncedLyrics() {
var lrcFile: File? = null val content: String = LyricUtil.getStringFromLrc(LyricUtil.getSyncedLyricsFile(song))
if (LyricUtil.isLrcOriginalFileExist(song.data)) {
lrcFile = LyricUtil.getLocalLyricOriginalFile(song.data)
} else if (LyricUtil.isLrcFileExist(song.title, song.artistName)) {
lrcFile = LyricUtil.getLocalLyricFile(song.title, song.artistName)
}
val content: String = LyricUtil.getStringFromLrc(lrcFile)
MaterialDialog(requireContext(), BottomSheet(LayoutMode.WRAP_CONTENT)).show { MaterialDialog(requireContext(), BottomSheet(LayoutMode.WRAP_CONTENT)).show {
title(res = R.string.edit_synced_lyrics) title(res = R.string.edit_synced_lyrics)
@ -332,11 +326,8 @@ class LyricsFragment : AbsMusicServiceFragment(R.layout.fragment_lyrics) {
fun loadLRCLyrics() { fun loadLRCLyrics() {
binding.lyricsView.setLabel("Empty") binding.lyricsView.setLabel("Empty")
val song = MusicPlayerRemote.currentSong LyricUtil.getSyncedLyricsFile(MusicPlayerRemote.currentSong)?.let {
if (LyricUtil.isLrcOriginalFileExist(song.data)) { binding.lyricsView.loadLrc(it)
binding.lyricsView.loadLrc(LyricUtil.getLocalLyricOriginalFile(song.data))
} else if (LyricUtil.isLrcFileExist(song.title, song.artistName)) {
binding.lyricsView.loadLrc(LyricUtil.getLocalLyricFile(song.title, song.artistName))
} }
} }

View file

@ -34,7 +34,6 @@ import code.name.monkey.retromusic.extensions.surfaceColor
import code.name.monkey.retromusic.fragments.NowPlayingScreen.* import code.name.monkey.retromusic.fragments.NowPlayingScreen.*
import code.name.monkey.retromusic.fragments.base.AbsMusicServiceFragment import code.name.monkey.retromusic.fragments.base.AbsMusicServiceFragment
import code.name.monkey.retromusic.fragments.base.AbsPlayerFragment import code.name.monkey.retromusic.fragments.base.AbsPlayerFragment
import code.name.monkey.retromusic.fragments.base.goToLyrics
import code.name.monkey.retromusic.helper.MusicPlayerRemote import code.name.monkey.retromusic.helper.MusicPlayerRemote
import code.name.monkey.retromusic.helper.MusicProgressViewUpdateHelper import code.name.monkey.retromusic.helper.MusicProgressViewUpdateHelper
import code.name.monkey.retromusic.lyrics.CoverLrcView import code.name.monkey.retromusic.lyrics.CoverLrcView
@ -74,18 +73,16 @@ class PlayerAlbumCoverFragment : AbsMusicServiceFragment(R.layout.fragment_playe
} }
private fun updateLyrics() { private fun updateLyrics() {
binding.lyricsView.setLabel("Empty") binding.lyricsView.setLabel(context?.getString(R.string.no_lyrics_found))
val song = MusicPlayerRemote.currentSong val song = MusicPlayerRemote.currentSong
when { val lrcFile = LyricUtil.getSyncedLyricsFile(song)
LyricUtil.isLrcOriginalFileExist(song.data) -> { if (lrcFile != null) {
LyricUtil.getLocalLyricOriginalFile(song.data) binding.lyricsView.loadLrc(lrcFile)
?.let { binding.lyricsView.loadLrc(it) } } else {
} val embeddedLyrics = LyricUtil.getEmbeddedSyncedLyrics(song.data)
LyricUtil.isLrcFileExist(song.title, song.artistName) -> { if (embeddedLyrics != null) {
LyricUtil.getLocalLyricFile(song.title, song.artistName) binding.lyricsView.loadLrc(embeddedLyrics)
?.let { binding.lyricsView.loadLrc(it) } } else {
}
else -> {
binding.lyricsView.reset() binding.lyricsView.reset()
} }
} }
@ -126,16 +123,7 @@ class PlayerAlbumCoverFragment : AbsMusicServiceFragment(R.layout.fragment_playe
) )
} }
progressViewUpdateHelper = MusicProgressViewUpdateHelper(this, 500, 1000) progressViewUpdateHelper = MusicProgressViewUpdateHelper(this, 500, 1000)
// Don't show lyrics container for below conditions maybeInitLyrics()
if (!(nps == Circle || nps == Peak || nps == Tiny || !PreferenceUtil.showLyrics)) {
lrcView.isVisible = false
viewPager.isInvisible = false
progressViewUpdateHelper?.stop()
} else {
lrcView.isVisible = true
viewPager.isInvisible = true
progressViewUpdateHelper?.start()
}
lrcView.apply { lrcView.apply {
setDraggable(true, object : CoverLrcView.OnPlayClickListener { setDraggable(true, object : CoverLrcView.OnPlayClickListener {
override fun onPlayClick(time: Long): Boolean { override fun onPlayClick(time: Long): Boolean {
@ -145,25 +133,11 @@ class PlayerAlbumCoverFragment : AbsMusicServiceFragment(R.layout.fragment_playe
} }
}) })
} }
// Go to lyrics activity when clicked lyrics
lrcView.setOnClickListener {
goToLyrics(requireActivity())
}
} }
override fun onResume() { override fun onResume() {
super.onResume() super.onResume()
val nps = PreferenceUtil.nowPlayingScreen maybeInitLyrics()
// Don't show lyrics container for below conditions
if (nps == Circle || nps == Peak || nps == Tiny || !PreferenceUtil.showLyrics) {
lrcView.isVisible = false
viewPager.isInvisible = false
progressViewUpdateHelper?.stop()
} else {
lrcView.isVisible = true
viewPager.isInvisible = true
progressViewUpdateHelper?.start()
}
PreferenceManager.getDefaultSharedPreferences(requireContext()) PreferenceManager.getDefaultSharedPreferences(requireContext())
.registerOnSharedPreferenceChangeListener(this) .registerOnSharedPreferenceChangeListener(this)
} }
@ -194,22 +168,9 @@ class PlayerAlbumCoverFragment : AbsMusicServiceFragment(R.layout.fragment_playe
override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences, key: String?) { override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences, key: String?) {
if (key == SHOW_LYRICS) { if (key == SHOW_LYRICS) {
if (sharedPreferences.getBoolean(key, false)) { if (sharedPreferences.getBoolean(key, false)) {
val nps = PreferenceUtil.nowPlayingScreen maybeInitLyrics()
// Don't show lyrics container for below conditions
if (!(nps == Circle || nps == Peak || nps == Tiny || !PreferenceUtil.showLyrics)) {
lrcView.isVisible = true
viewPager.isInvisible = true
progressViewUpdateHelper?.start()
lrcView.animate().alpha(1f).duration =
AbsPlayerFragment.VISIBILITY_ANIM_DURATION
} else {
lrcView.isVisible = false
viewPager.isInvisible = false
progressViewUpdateHelper?.stop()
}
} else { } else {
lrcView.isVisible = false showLyrics(false)
viewPager.isInvisible = false
progressViewUpdateHelper?.stop() progressViewUpdateHelper?.stop()
} }
} }
@ -233,6 +194,25 @@ class PlayerAlbumCoverFragment : AbsMusicServiceFragment(R.layout.fragment_playe
} }
} }
private fun showLyrics(visible: Boolean) {
lrcView.isVisible = visible
viewPager.isInvisible = visible
}
private fun maybeInitLyrics() {
val nps = PreferenceUtil.nowPlayingScreen
// Don't show lyrics container for below conditions
if (nps != Circle && nps != Peak && nps != Tiny && PreferenceUtil.showLyrics) {
showLyrics(true)
progressViewUpdateHelper?.start()
lrcView.animate().alpha(1f).duration =
AbsPlayerFragment.VISIBILITY_ANIM_DURATION
} else {
showLyrics(false)
progressViewUpdateHelper?.stop()
}
}
private fun updatePlayingQueue() { private fun updatePlayingQueue() {
binding.viewPager.apply { binding.viewPager.apply {
adapter = AlbumCoverPagerAdapter(childFragmentManager, MusicPlayerRemote.playingQueue) adapter = AlbumCoverPagerAdapter(childFragmentManager, MusicPlayerRemote.playingQueue)
@ -266,15 +246,17 @@ class PlayerAlbumCoverFragment : AbsMusicServiceFragment(R.layout.fragment_playe
callbacks?.onColorChanged(color) callbacks?.onColorChanged(color)
setLRCViewColors( setLRCViewColors(
when (PreferenceUtil.nowPlayingScreen) { when (PreferenceUtil.nowPlayingScreen) {
Adaptive, Fit, Plain, Simple -> surfaceColor()
Flat, Normal -> if (PreferenceUtil.isAdaptiveColor) { Flat, Normal -> if (PreferenceUtil.isAdaptiveColor) {
color.backgroundColor color.backgroundColor
} else { } else {
surfaceColor() surfaceColor()
} }
Color, Gradient, Full ->color.backgroundColor Color -> color.backgroundColor
Blur -> Color.BLACK Blur -> Color.BLACK
else -> surfaceColor() else -> color.backgroundColor
}) }
)
} }
fun setCallbacks(listener: Callbacks) { fun setCallbacks(listener: Callbacks) {

View file

@ -91,10 +91,10 @@ class CoverLrcView @JvmOverloads constructor(
private val mSimpleOnGestureListener: SimpleOnGestureListener = private val mSimpleOnGestureListener: SimpleOnGestureListener =
object : SimpleOnGestureListener() { object : SimpleOnGestureListener() {
override fun onDown(e: MotionEvent): Boolean { override fun onDown(e: MotionEvent): Boolean {
if (mOffset != getOffset(0)) {
parent.requestDisallowInterceptTouchEvent(true)
}
if (hasLrc() && mOnPlayClickListener != null) { if (hasLrc() && mOnPlayClickListener != null) {
if (mOffset != getOffset(0)) {
parent.requestDisallowInterceptTouchEvent(true)
}
mScroller!!.forceFinished(true) mScroller!!.forceFinished(true)
removeCallbacks(hideTimelineRunnable) removeCallbacks(hideTimelineRunnable)
isTouching = true isTouching = true
@ -336,7 +336,7 @@ class CoverLrcView @JvmOverloads constructor(
* @param mainLrcFile 第一种语言歌词文件 * @param mainLrcFile 第一种语言歌词文件
* @param secondLrcFile 第二种语言歌词文件 * @param secondLrcFile 第二种语言歌词文件
*/ */
fun loadLrc(mainLrcFile: File, secondLrcFile: File?) { private fun loadLrc(mainLrcFile: File, secondLrcFile: File?) {
runOnUi { runOnUi {
reset() reset()
val sb = StringBuilder("file://") val sb = StringBuilder("file://")
@ -352,7 +352,7 @@ class CoverLrcView @JvmOverloads constructor(
} }
override fun onPostExecute(lrcEntries: List<LrcEntry>) { override fun onPostExecute(lrcEntries: List<LrcEntry>) {
if (flag === flag) { if (flag == flag) {
onLrcLoaded(lrcEntries) onLrcLoaded(lrcEntries)
this@CoverLrcView.flag = null this@CoverLrcView.flag = null
} }
@ -376,7 +376,7 @@ class CoverLrcView @JvmOverloads constructor(
* @param mainLrcText 第一种语言歌词文本 * @param mainLrcText 第一种语言歌词文本
* @param secondLrcText 第二种语言歌词文本 * @param secondLrcText 第二种语言歌词文本
*/ */
fun loadLrc(mainLrcText: String?, secondLrcText: String?) { private fun loadLrc(mainLrcText: String?, secondLrcText: String?) {
runOnUi { runOnUi {
reset() reset()
val sb = StringBuilder("file://") val sb = StringBuilder("file://")
@ -392,7 +392,7 @@ class CoverLrcView @JvmOverloads constructor(
} }
override fun onPostExecute(lrcEntries: List<LrcEntry>) { override fun onPostExecute(lrcEntries: List<LrcEntry>) {
if (flag === flag) { if (flag == flag) {
onLrcLoaded(lrcEntries) onLrcLoaded(lrcEntries)
this@CoverLrcView.flag = null this@CoverLrcView.flag = null
} }
@ -400,12 +400,7 @@ class CoverLrcView @JvmOverloads constructor(
}.execute(mainLrcText, secondLrcText) }.execute(mainLrcText, secondLrcText)
} }
} }
/**
* 加载在线歌词
*
* @param lrcUrl 歌词文件的网络地址
* @param charset 编码格式
*/
/** /**
* 加载在线歌词默认使用 utf-8 编码 * 加载在线歌词默认使用 utf-8 编码
* *
@ -421,7 +416,7 @@ class CoverLrcView @JvmOverloads constructor(
} }
override fun onPostExecute(lrcText: String) { override fun onPostExecute(lrcText: String) {
if (flag === flag) { if (flag == flag) {
loadLrc(lrcText) loadLrc(lrcText)
} }
} }

View file

@ -1,189 +0,0 @@
/*
* Copyright (c) 2019 Hemanth Savarala.
*
* Licensed under the GNU General Public License v3
*
* This is free software: you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by
* the Free Software Foundation either version 3 of the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*/
package code.name.monkey.retromusic.util;
import android.util.Base64;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import code.name.monkey.retromusic.model.Song;
/**
* Created by hefuyi on 2016/11/8.
*/
public class LyricUtil {
private static final String lrcRootPath =
android.os.Environment.getExternalStorageDirectory().toString() + "/RetroMusic/lyrics/";
private static final String TAG = "LyricUtil";
@Nullable
public static File writeLrcToLoc(
@NonNull String title, @NonNull String artist, @NonNull String lrcContext) {
FileWriter writer = null;
try {
File file = new File(getLrcPath(title, artist));
if (!file.getParentFile().exists()) {
file.getParentFile().mkdirs();
}
writer = new FileWriter(getLrcPath(title, artist));
writer.write(lrcContext);
return file;
} catch (IOException e) {
e.printStackTrace();
return null;
} finally {
try {
if (writer != null) writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
//So in Retro, Lrc file can be same folder as Music File or in RetroMusic Folder
// In this case we pass location of the file and Contents to write to file
public static void writeLrc(@NonNull Song song, @NonNull String lrcContext) {
FileWriter writer = null;
File location;
try {
if (isLrcOriginalFileExist(song.getData())) {
location = getLocalLyricOriginalFile(song.getData());
} else if (isLrcFileExist(song.getTitle(), song.getArtistName())) {
location = getLocalLyricFile(song.getTitle(), song.getArtistName());
} else {
location = new File(getLrcPath(song.getTitle(), song.getArtistName()));
if (!location.getParentFile().exists()) {
location.getParentFile().mkdirs();
}
}
writer = new FileWriter(location);
writer.write(lrcContext);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (writer != null) writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static boolean deleteLrcFile(@NonNull String title, @NonNull String artist) {
File file = new File(getLrcPath(title, artist));
return file.delete();
}
public static boolean isLrcFileExist(@NonNull String title, @NonNull String artist) {
File file = new File(getLrcPath(title, artist));
return file.exists();
}
public static boolean isLrcOriginalFileExist(@NonNull String path) {
File file = new File(getLrcOriginalPath(path));
return file.exists();
}
@Nullable
public static File getLocalLyricFile(@NonNull String title, @NonNull String artist) {
File file = new File(getLrcPath(title, artist));
if (file.exists()) {
return file;
} else {
return null;
}
}
@Nullable
public static File getLocalLyricOriginalFile(@NonNull String path) {
File file = new File(getLrcOriginalPath(path));
if (file.exists()) {
return file;
} else {
return null;
}
}
private static String getLrcPath(String title, String artist) {
return lrcRootPath + title + " - " + artist + ".lrc";
}
private static String getLrcOriginalPath(String filePath) {
return filePath.replace(filePath.substring(filePath.lastIndexOf(".") + 1), "lrc");
}
@NonNull
public static String decryptBASE64(@NonNull String str) {
if (str == null || str.length() == 0) {
return null;
}
byte[] encode = str.getBytes(StandardCharsets.UTF_8);
// base64 解密
return new String(
Base64.decode(encode, 0, encode.length, Base64.DEFAULT), StandardCharsets.UTF_8);
}
@NonNull
public static String getStringFromFile(@NonNull String title, @NonNull String artist)
throws Exception {
File file = new File(getLrcPath(title, artist));
FileInputStream fin = new FileInputStream(file);
String ret = convertStreamToString(fin);
fin.close();
return ret;
}
private static String convertStreamToString(InputStream is) throws Exception {
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
StringBuilder sb = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
sb.append(line).append("\n");
}
reader.close();
return sb.toString();
}
public static String getStringFromLrc(File file) {
try {
BufferedReader reader = new BufferedReader(new FileReader(file));
StringBuilder sb = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
sb.append(line).append("\n");
}
reader.close();
return sb.toString();
} catch (Exception e) {
Log.i("Error", "Error Occurred");
}
return "";
}
}

View file

@ -0,0 +1,188 @@
/*
* Copyright (c) 2019 Hemanth Savarala.
*
* Licensed under the GNU General Public License v3
*
* This is free software: you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by
* the Free Software Foundation either version 3 of the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*/
package code.name.monkey.retromusic.util
import android.os.Environment
import android.util.Log
import code.name.monkey.retromusic.model.Song
import code.name.monkey.retromusic.model.lyrics.AbsSynchronizedLyrics
import org.jaudiotagger.audio.AudioFileIO
import org.jaudiotagger.tag.FieldKey
import java.io.*
/**
* Created by hefuyi on 2016/11/8.
*/
object LyricUtil {
private val lrcRootPath =
Environment.getExternalStorageDirectory().toString() + "/RetroMusic/lyrics/"
private const val TAG = "LyricUtil"
fun writeLrcToLoc(
title: String, artist: String, lrcContext: String
): File? {
var writer: FileWriter? = null
return try {
val file = File(getLrcPath(title, artist))
if (file.parentFile?.exists() != true) {
file.parentFile?.mkdirs()
}
writer = FileWriter(getLrcPath(title, artist))
writer.write(lrcContext)
file
} catch (e: IOException) {
e.printStackTrace()
null
} finally {
try {
writer?.close()
} catch (e: IOException) {
e.printStackTrace()
}
}
}
//So in Retro, Lrc file can be same folder as Music File or in RetroMusic Folder
// In this case we pass location of the file and Contents to write to file
fun writeLrc(song: Song, lrcContext: String) {
var writer: FileWriter? = null
val location: File?
try {
if (isLrcOriginalFileExist(song.data)) {
location = getLocalLyricOriginalFile(song.data)
} else if (isLrcFileExist(song.title, song.artistName)) {
location = getLocalLyricFile(song.title, song.artistName)
} else {
location = File(getLrcPath(song.title, song.artistName))
if (location.parentFile?.exists() != true) {
location.parentFile?.mkdirs()
}
}
writer = FileWriter(location)
writer.write(lrcContext)
} catch (e: IOException) {
e.printStackTrace()
} finally {
try {
writer?.close()
} catch (e: IOException) {
e.printStackTrace()
}
}
}
fun deleteLrcFile(title: String, artist: String): Boolean {
val file = File(getLrcPath(title, artist))
return file.delete()
}
private fun isLrcFileExist(title: String, artist: String): Boolean {
val file = File(getLrcPath(title, artist))
return file.exists()
}
private fun isLrcOriginalFileExist(path: String): Boolean {
val file = File(getLrcOriginalPath(path))
return file.exists()
}
private fun getLocalLyricFile(title: String, artist: String): File? {
val file = File(getLrcPath(title, artist))
return if (file.exists()) {
file
} else {
null
}
}
private fun getLocalLyricOriginalFile(path: String): File? {
val file = File(getLrcOriginalPath(path))
return if (file.exists()) {
file
} else {
null
}
}
private fun getLrcPath(title: String, artist: String): String {
return "$lrcRootPath$title - $artist.lrc"
}
private fun getLrcOriginalPath(filePath: String): String {
return filePath.replace(filePath.substring(filePath.lastIndexOf(".") + 1), "lrc")
}
@Throws(Exception::class)
fun getStringFromFile(title: String, artist: String): String {
val file = File(getLrcPath(title, artist))
val fin = FileInputStream(file)
val ret = convertStreamToString(fin)
fin.close()
return ret
}
@Throws(Exception::class)
private fun convertStreamToString(`is`: InputStream): String {
val reader = BufferedReader(InputStreamReader(`is`))
val sb = StringBuilder()
var line: String?
while (reader.readLine().also { line = it } != null) {
sb.append(line).append("\n")
}
reader.close()
return sb.toString()
}
fun getStringFromLrc(file: File?): String {
try {
val reader = BufferedReader(FileReader(file))
val sb = StringBuilder()
var line: String?
while (reader.readLine().also { line = it } != null) {
sb.append(line).append("\n")
}
reader.close()
return sb.toString()
} catch (e: Exception) {
Log.i("Error", "Error Occurred")
}
return ""
}
fun getSyncedLyricsFile(song: Song): File? {
return when {
isLrcOriginalFileExist(song.data) -> {
getLocalLyricOriginalFile(song.data)
}
isLrcFileExist(song.title, song.artistName) -> {
getLocalLyricFile(song.title, song.artistName)
}
else -> {
null
}
}
}
fun getEmbeddedSyncedLyrics(data: String): String? {
val embeddedLyrics = try{
AudioFileIO.read(File(data)).tagOrCreateDefault.getFirst(FieldKey.LYRICS)
} catch(e: Exception){
return null
}
return if (AbsSynchronizedLyrics.isSynchronized(embeddedLyrics)) {
embeddedLyrics
} else {
null
}
}
}

View file

@ -66,17 +66,21 @@
android:orderInCategory="10" android:orderInCategory="10"
android:title="@string/action_details" /> android:title="@string/action_details" />
<item <item
android:id="@+id/action_sleep_timer" android:id="@+id/action_go_to_lyrics"
android:orderInCategory="11" android:orderInCategory="11"
android:title="@string/action_go_to_lyrics" />
<item
android:id="@+id/action_sleep_timer"
android:orderInCategory="12"
android:title="@string/action_sleep_timer" android:title="@string/action_sleep_timer"
app:showAsAction="never" /> app:showAsAction="never" />
<item <item
android:id="@+id/action_equalizer" android:id="@+id/action_equalizer"
android:orderInCategory="12" android:orderInCategory="13"
android:title="@string/equalizer" android:title="@string/equalizer"
app:showAsAction="never" /> app:showAsAction="never" />
<item <item
android:id="@+id/action_delete_from_device" android:id="@+id/action_delete_from_device"
android:orderInCategory="13" android:orderInCategory="14"
android:title="@string/action_delete_from_device" /> android:title="@string/action_delete_from_device" />
</menu> </menu>

View file

@ -19,6 +19,7 @@
<string name="action_go_to_album">Go to album</string> <string name="action_go_to_album">Go to album</string>
<string name="action_go_to_artist">Go to artist</string> <string name="action_go_to_artist">Go to artist</string>
<string name="action_go_to_genre">Go to genre</string> <string name="action_go_to_genre">Go to genre</string>
<string name="action_go_to_lyrics">Go to Lyrics</string>
<string name="action_go_to_start_directory">Go to start directory</string> <string name="action_go_to_start_directory">Go to start directory</string>
<string name="action_grant">Grant</string> <string name="action_grant">Grant</string>
<string name="action_grid_size">Grid size</string> <string name="action_grid_size">Grid size</string>