@@ -219,6 +219,7 @@ class GramophonePlaybackService : MediaLibraryService(), MediaSessionService.Lis
219219 private lateinit var lastPlayedManager: LastPlayedManager
220220 private lateinit var prefs: SharedPreferences
221221 private var lastSentHighlightedLyric: String? = null
222+ private var lastSentNotificationLyric: String? = null
222223 private lateinit var afFormatTracker: AfFormatTracker
223224 private lateinit var rgAp: ReplayGainAudioProcessor
224225 private var rgMode = 0 // 0 = disabled, 1 = track, 2 = album, 3 = smart
@@ -406,6 +407,7 @@ class GramophonePlaybackService : MediaLibraryService(), MediaSessionService.Lis
406407 onSharedPreferenceChanged(prefs, null ) // read initial values
407408 val player = EndedWorkaroundPlayer (
408409 this ,
410+ prefs,
409411 exoPlayer = ExoPlayer .Builder (
410412 this ,
411413 GramophoneRenderFactory (
@@ -453,6 +455,7 @@ class GramophonePlaybackService : MediaLibraryService(), MediaSessionService.Lis
453455 .build(),
454456 { lyrics },
455457 queueBoard = qb,
458+ getNotificationLyric = { lastSentNotificationLyric }
456459 )
457460 player.exoPlayer.addAnalyticsListener(EventLogger ())
458461 player.exoPlayer.addAnalyticsListener(afFormatTracker)
@@ -818,6 +821,7 @@ class GramophonePlaybackService : MediaLibraryService(), MediaSessionService.Lis
818821 scope.cancel()
819822 endedWorkaroundPlayer!! .stop()
820823 handler.removeCallbacks(timer)
824+ handler.removeCallbacks(sendLyrics)
821825 mediaSession!! .setOptOutOfMediaButtonPlaybackResumption(controller!! .currentTimeline.isEmpty)
822826 proxy?.let {
823827 it.adapter.closeProfileProxy(BluetoothProfile .A2DP , it.a2dp)
@@ -903,6 +907,10 @@ class GramophonePlaybackService : MediaLibraryService(), MediaSessionService.Lis
903907
904908 override fun onSharedPreferenceChanged (sharedPreferences : SharedPreferences , key : String? ) {
905909 var restart = false
910+ if (key == null || key == " notification_lyrics" || key == " status_bar_lyrics" ) {
911+ scheduleSendingLyrics(false )
912+ endedWorkaroundPlayer?.updateLyricNow()
913+ }
906914 if (key == null || key == " rg_mode" ) {
907915 rgMode = prefs.getStringStrict(" rg_mode" , " 0" )!! .toInt()
908916 restart = ! computeRgMode(true )
@@ -1572,6 +1580,8 @@ class GramophonePlaybackService : MediaLibraryService(), MediaSessionService.Lis
15721580 // lyrics = null
15731581 // scheduleSendingLyrics(true)
15741582 }
1583+ lastSentNotificationLyric = null
1584+ lastSentHighlightedLyric = null
15751585
15761586 // reshuffle queue when shuffle AND repeat all are enabled
15771587 val player = endedWorkaroundPlayer
@@ -1768,6 +1778,20 @@ class GramophonePlaybackService : MediaLibraryService(), MediaSessionService.Lis
17681778 scheduleSendingLyrics(false )
17691779 }
17701780
1781+ private fun getActiveNotificationLyric (): String? {
1782+ val isNotificationLyricsEnabled = prefs.getBooleanStrict(" notification_lyrics" , false )
1783+ if (! isNotificationLyricsEnabled) return null
1784+ if (controller?.playbackState == Player .STATE_ENDED || controller?.playbackState == Player .STATE_IDLE ) return null
1785+
1786+ val cPos = (controller?.contentPosition ? : 0 ).toULong()
1787+ val lines = syncedLyrics?.text?.filter {
1788+ it.start <= cPos && ! it.isTranslated
1789+ }
1790+ val currentLine = lines?.maxByOrNull { it.start } ? : return null
1791+ if (currentLine.text.isBlank()) return null
1792+ return currentLine.text
1793+ }
1794+
17711795 private fun scheduleSendingLyrics (new : Boolean ) {
17721796 handler.removeCallbacks(sendLyrics)
17731797 sendLyricNow(new || ! updatedLyricAtLeastOnce)
@@ -1776,8 +1800,9 @@ class GramophonePlaybackService : MediaLibraryService(), MediaSessionService.Lis
17761800 endedWorkaroundPlayer?.updateLyricNow()
17771801 }
17781802 val isStatusBarLyricsEnabled = prefs.getBooleanStrict(" status_bar_lyrics" , false )
1803+ val isNotificationLyricsEnabled = prefs.getBooleanStrict(" notification_lyrics" , false )
17791804 val hnw = ! LyricWidgetProvider .hasWidget(this )
1780- if (controller?.isPlaying != true || (! isStatusBarLyricsEnabled && hnw)) return
1805+ if (controller?.isPlaying != true || (! isStatusBarLyricsEnabled && ! isNotificationLyricsEnabled && hnw)) return
17811806 val cPos = (controller?.contentPosition ? : 0 ).toULong()
17821807 val nextUpdate = syncedLyrics?.text?.flatMap { line ->
17831808 if (hnw && line.start <= cPos) listOf () else if (hnw) listOf (line.start) else
@@ -1803,10 +1828,16 @@ class GramophonePlaybackService : MediaLibraryService(), MediaSessionService.Lis
18031828 syncedLyrics?.text?.get(it)?.text
18041829 }
18051830 else null
1806- if (lastSentHighlightedLyric != highlightedLyric) {
1831+ val notificationLyric = getActiveNotificationLyric()
1832+ if (lastSentHighlightedLyric != highlightedLyric || lastSentNotificationLyric != notificationLyric) {
1833+ val notifLyricChanged = lastSentNotificationLyric != notificationLyric
18071834 lastSentHighlightedLyric = highlightedLyric
1835+ lastSentNotificationLyric = notificationLyric
18081836 handler.post {
18091837 endedWorkaroundPlayer?.let {
1838+ if (notifLyricChanged) {
1839+ it.updateLyricNow()
1840+ }
18101841 // This will access the media notification controller's getters. But because
18111842 // controller callback ordering is undefined and in practice our service
18121843 // controller sometimes gets called first, this would cause us to access a stale
0 commit comments