Skip to content

Commit a578dda

Browse files
committed
Update code docs
1 parent e2a7196 commit a578dda

10 files changed

Lines changed: 209 additions & 138 deletions

docs/components_music_AudioPlayerView.bs.html

Lines changed: 134 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@
2424
setupInfoNodes()
2525
setupDataTasks()
2626
setupScreenSaver()
27+
applyTheme()
2728

28-
m.buttonCount = m.buttons.getChildCount()
2929
m.seekPosition.translation = [720 - (m.seekPosition.width / 2), m.seekPosition.translation[1]]
3030

3131
m.screenSaverTimeout = 300
@@ -43,8 +43,24 @@
4343
pageContentChanged()
4444
setShuffleIconState()
4545
setLoopButtonImage()
46+
' Set lastFocus for JRScreen lifecycle management
47+
m.top.lastFocus = m.buttons
48+
end sub
49+
50+
sub applyTheme()
51+
constants = m.global.constants
52+
53+
m.backDropMask.color = constants.colorBlack + constants.alpha40
4654

47-
m.buttons.setFocus(true)
55+
for each button in m.buttons.getChildren(-1, 0)
56+
button.iconBackground = constants.colorTextSecondary
57+
button.iconFocusBackground = constants.colorTextSecondary
58+
end for
59+
60+
m.seekBar.color = constants.colorBlack + constants.alpha60
61+
m.bufferPosition.color = constants.colorBackgroundSecondary
62+
m.playPosition.color = constants.colorSecondary
63+
m.thumb.blendColor = constants.colorPrimary
4864
end sub
4965

5066
sub onScreensaverTimeoutLoaded()
@@ -71,14 +87,11 @@
7187
end sub
7288

7389
sub setupAnimationTasks()
74-
m.displayButtonsAnimation = m.top.FindNode("displayButtonsAnimation")
7590
m.playPositionAnimation = m.top.FindNode("playPositionAnimation")
7691
m.playPositionAnimationWidth = m.top.FindNode("playPositionAnimationWidth")
7792

7893
m.bufferPositionAnimation = m.top.FindNode("bufferPositionAnimation")
7994
m.bufferPositionAnimationWidth = m.top.FindNode("bufferPositionAnimationWidth")
80-
81-
m.screenSaverStartAnimation = m.top.FindNode("screenSaverStartAnimation")
8295
end sub
8396

8497
' Creates tasks to gather data needed to render Scene and play song
@@ -101,45 +114,63 @@
101114
' Setup playback buttons, default to Play button selected
102115
sub setupButtons()
103116
m.buttons = m.top.findNode("buttons")
104-
m.top.observeField("selectedButtonIndex", "onButtonSelectedChange")
105117

106-
' If we're playing a mixed playlist, remove the shuffle and loop buttons
107-
if m.playlistTypeCount > 1
108-
shuffleButton = m.top.findNode("shuffle")
109-
m.buttons.removeChild(shuffleButton)
118+
' Get button references for later use
119+
m.playButton = m.buttons.findNode("play")
120+
m.shuffleButton = m.buttons.findNode("shuffle")
121+
m.repeatButton = m.buttons.findNode("repeat")
110122

111-
loopButton = m.top.findNode("loop")
112-
m.buttons.removeChild(loopButton)
123+
' If we're playing a mixed playlist, remove the shuffle and repeat buttons
124+
if m.playlistTypeCount > 1
125+
if isValid(m.shuffleButton)
126+
m.buttons.removeChild(m.shuffleButton)
127+
m.shuffleButton = invalid
128+
end if
113129

114-
m.previouslySelectedButtonIndex = 0
115-
m.top.selectedButtonIndex = 1
116-
return
130+
if isValid(m.repeatButton)
131+
m.buttons.removeChild(m.repeatButton)
132+
m.repeatButton = invalid
133+
end if
117134
end if
118135

119-
m.previouslySelectedButtonIndex = 1
120-
m.top.selectedButtonIndex = 2
136+
' Set default focus to play button (index 1)
137+
m.buttons.buttonFocused = 1
138+
139+
' Center button group horizontally
140+
m.buttons.callFunc("center")
141+
142+
' Observe button selection
143+
m.buttons.observeField("buttonSelected", "onButtonSelected")
121144
end sub
122145

123-
' Event handler when user selected a different playback button
124-
sub onButtonSelectedChange()
125-
' Change previously selected button back to default image
126-
selectedButton = m.buttons.getChild(m.previouslySelectedButtonIndex)
127-
selectedButton.uri = selectedButton.uri.Replace("-selected", "-default")
146+
' Event handler when user selects a button via OK key
147+
sub onButtonSelected()
148+
buttonIndex = m.buttons.buttonSelected
149+
button = m.buttons.getChild(buttonIndex)
150+
151+
if not isValid(button) then return
128152

129-
' Change selected button image to selected image
130-
selectedButton = m.buttons.getChild(m.top.selectedButtonIndex)
131-
selectedButton.uri = selectedButton.uri.Replace("-default", "-selected")
153+
if button.id = "play"
154+
playAction()
155+
else if button.id = "previous"
156+
previousClicked()
157+
else if button.id = "next"
158+
nextClicked()
159+
else if button.id = "shuffle"
160+
shuffleClicked()
161+
else if button.id = "repeat"
162+
loopClicked()
163+
end if
132164
end sub
133165

134166
sub setupInfoNodes()
135167
m.albumCover = m.top.findNode("albumCover")
136168
m.backDrop = m.top.findNode("backdrop")
169+
m.backDropMask = m.top.findNode("backDropMask")
137170
m.playPosition = m.top.findNode("playPosition")
138171
m.bufferPosition = m.top.findNode("bufferPosition")
139172
m.seekBar = m.top.findNode("seekBar")
140173
m.thumb = m.top.findNode("thumb")
141-
m.shuffleIndicator = m.top.findNode("shuffleIndicator")
142-
m.loopIndicator = m.top.findNode("loopIndicator")
143174
m.positionTimestamp = m.top.findNode("positionTimestamp")
144175
m.seekPosition = m.top.findNode("seekPosition")
145176
m.seekTimestamp = m.top.findNode("seekTimestamp")
@@ -247,6 +278,15 @@
247278
end sub
248279

249280
sub audioStateChanged()
281+
' Update play/pause button icon based on audio state
282+
if isValid(m.playButton)
283+
if m.audioPlayer.state = "playing"
284+
m.playButton.icon = "pkg:/images/icons/pause.png"
285+
else
286+
m.playButton.icon = "pkg:/images/icons/play.png"
287+
end if
288+
end if
289+
250290
' Song Finished, attempt to move to next song
251291
if m.audioPlayer.state = "finished"
252292
' User has enabled single song loop, play current song again
@@ -279,16 +319,25 @@
279319

280320
if m.audioPlayer.state = "playing"
281321
m.audioPlayer.control = "pause"
322+
if isValid(m.playButton)
323+
m.playButton.icon = "pkg:/images/icons/play.png"
324+
end if
282325
' Allow screen to go to real screensaver
283326
WriteAsciiFile("tmp:/scene.temp", "nowplaying-paused")
284327
MoveFile("tmp:/scene.temp", "tmp:/scene")
285328
else if m.audioPlayer.state = "paused"
286329
m.audioPlayer.control = "resume"
330+
if isValid(m.playButton)
331+
m.playButton.icon = "pkg:/images/icons/pause.png"
332+
end if
287333
' Write screen tracker for screensaver
288334
WriteAsciiFile("tmp:/scene.temp", "nowplaying")
289335
MoveFile("tmp:/scene.temp", "tmp:/scene")
290336
else if m.audioPlayer.state = "finished"
291337
m.audioPlayer.control = "play"
338+
if isValid(m.playButton)
339+
m.playButton.icon = "pkg:/images/icons/pause.png"
340+
end if
292341
' Write screen tracker for screensaver
293342
WriteAsciiFile("tmp:/scene.temp", "nowplaying")
294343
MoveFile("tmp:/scene.temp", "tmp:/scene")
@@ -355,13 +404,20 @@
355404
end function
356405

357406
sub setLoopButtonImage()
407+
if not isValid(m.repeatButton) then return
408+
358409
if m.audioPlayer.loopMode = "all"
359-
m.loopIndicator.opacity = "1"
360-
m.loopIndicator.uri = m.loopIndicator.uri.Replace("-off", "-on")
410+
' Repeat all - use repeat.png with active state
411+
m.repeatButton.icon = "pkg:/images/icons/repeat.png"
412+
m.repeatButton.selected = true
361413
else if m.audioPlayer.loopMode = "one"
362-
m.loopIndicator.uri = m.loopIndicator.uri.Replace("-on", "1-on")
414+
' Repeat one - use repeat-1.png with active state
415+
m.repeatButton.icon = "pkg:/images/icons/repeat-1.png"
416+
m.repeatButton.selected = true
363417
else
364-
m.loopIndicator.uri = m.loopIndicator.uri.Replace("1-on", "-off")
418+
' Repeat off - use repeat.png without active state
419+
m.repeatButton.icon = "pkg:/images/icons/repeat.png"
420+
m.repeatButton.selected = false
365421
end if
366422
end sub
367423

@@ -424,29 +480,36 @@
424480
toggleShuffleEnabled()
425481

426482
if not m.queueManager.callFunc("getIsShuffled")
427-
m.shuffleIndicator.opacity = ".4"
428-
m.shuffleIndicator.uri = m.shuffleIndicator.uri.Replace("-on", "-off")
483+
' Shuffle off
484+
if isValid(m.shuffleButton)
485+
m.shuffleButton.selected = false
486+
end if
429487
m.queueManager.callFunc("setPosition", currentSongIndex)
430488
setTrackNumberDisplay()
431489
return true
432490
end if
433491

434-
m.shuffleIndicator.opacity = "1"
435-
m.shuffleIndicator.uri = m.shuffleIndicator.uri.Replace("-off", "-on")
492+
' Shuffle on
493+
if isValid(m.shuffleButton)
494+
m.shuffleButton.selected = true
495+
end if
436496
setTrackNumberDisplay()
437497

438498
return true
439499
end function
440500

441501
sub setShuffleIconState()
502+
if not isValid(m.shuffleButton) then return
503+
442504
if m.queueManager.callFunc("getIsShuffled")
443-
m.shuffleIndicator.opacity = "1"
444-
m.shuffleIndicator.uri = m.shuffleIndicator.uri.Replace("-off", "-on")
505+
m.shuffleButton.selected = true
506+
else
507+
m.shuffleButton.selected = false
445508
end if
446509
end sub
447510

448511
sub setTrackNumberDisplay()
449-
setFieldTextValue("numberofsongs", "Track " + stri(m.queueManager.callFunc("getPosition") + 1) + "/" + stri(m.queueManager.callFunc("getCount")))
512+
setFieldTextValue("numberofsongs", tr("Track") + " " + tr("%1 of %2").Replace("%1", stri(m.queueManager.callFunc("getPosition") + 1).trim()).Replace("%2", stri(m.queueManager.callFunc("getCount")).trim()))
450513
end sub
451514

452515
sub LoadNextSong()
@@ -474,12 +537,10 @@
474537
m.LoadAudioStreamTask.control = "RUN"
475538
end sub
476539

477-
' If we have more and 1 song to play, fade in the next and previous controls
540+
' If we have more than 1 song to play, set initial button states
478541
sub loadButtons()
479542
if m.queueManager.callFunc("getCount") > 1
480-
m.shuffleIndicator.opacity = ".4"
481-
m.loopIndicator.opacity = ".4"
482-
m.displayButtonsAnimation.control = "start"
543+
' Set initial loop/repeat button state
483544
setLoopButtonImage()
484545
end if
485546
end sub
@@ -511,16 +572,32 @@
511572
useMetaTask = true
512573
end if
513574

575+
' If we don't have enough data to populate the screen, load metadata
514576
if useMetaTask
515577
m.LoadMetaDataTask.itemId = currentItem.id
516578
m.LoadMetaDataTask.observeField("content", "onMetaDataLoaded")
517579
m.LoadMetaDataTask.control = "RUN"
518580
else
519-
if isValid(currentItem.ParentBackdropItemId)
520-
setBackdropImage(ImageURL(currentItem.ParentBackdropItemId, "Backdrop", { "maxHeight": "720", "maxWidth": "1280" }))
581+
' backdrop image
582+
if isValid(currentItem.ParentBackdropItemId) and isValid(currentItem.ParentBackdropImageTags) and currentItem.ParentBackdropImageTags.count() > 0
583+
setBackdropImage(ImageURL(currentItem.ParentBackdropItemId, "Backdrop", { "maxHeight": "720", "maxWidth": "1280", "tag": currentItem.ParentBackdropImageTags[0] }))
584+
else
585+
' no backdrop available, clear existing backdrop
586+
setBackdropImage("pkg:/images/1px-transparent.png")
587+
end if
588+
589+
' poster image
590+
if isValid(currentItem.AlbumId) and isValid(currentItem.AlbumPrimaryImageTag) and currentItem.AlbumPrimaryImageTag <> ""
591+
' use primary album image
592+
setPosterImage(ImageURL(currentItem.AlbumId, "Primary", { "maxHeight": 500, "maxWidth": 500, "tag": currentItem.AlbumPrimaryImageTag }))
593+
else if isValid(currentItem.ImageTags) and currentItem.ImageTags["Primary"] <> invalid
594+
' use primary poster image
595+
setPosterImage(ImageURL(currentItem.id, "Primary", { "maxHeight": 500, "maxWidth": 500, "tag": currentItem.ImageTags["Primary"] }))
596+
else
597+
' no poster available, show placeholder image
598+
setPosterImage("pkg:/images/icons/album.png")
521599
end if
522600

523-
setPosterImage(ImageURL(currentItem.id, "Primary", { "maxHeight": 500, "maxWidth": 500 }))
524601
setScreenTitle(currentItem)
525602
setOnScreenTextValues(currentItem)
526603
m.songDuration = currentItem.RunTimeTicks / 10000000.0
@@ -571,6 +648,17 @@
571648
sub setPosterImage(posterURL)
572649
if isValid(posterURL)
573650
if m.albumCover.uri <> posterURL
651+
if posterURL = "pkg:/images/icons/album.png"
652+
constants = m.global.constants
653+
' color the white album placeholder to match theme
654+
m.albumCover.blendColor = constants.colorTextSecondary
655+
m.screenSaverAlbumCover.blendColor = constants.colorTextSecondary
656+
else
657+
' reset blend color to default white
658+
m.albumCover.blendColor = "0xFFFFFFFF"
659+
m.screenSaverAlbumCover.blendColor = "0xFFFFFFFF"
660+
end if
661+
574662
m.albumCover.uri = posterURL
575663
m.screenSaverAlbumCover.uri = posterURL
576664
end if
@@ -618,15 +706,6 @@
618706
end if
619707
end sub
620708

621-
' setSelectedButtonState: Changes the icon state url for the currently selected button
622-
'
623-
' @param {string} oldState - current state to replace in icon url
624-
' @param {string} newState - state to replace {oldState} with in icon url
625-
sub setSelectedButtonState(oldState as string, newState as string)
626-
selectedButton = m.buttons.getChild(m.top.selectedButtonIndex)
627-
selectedButton.uri = selectedButton.uri.Replace(oldState, newState)
628-
end sub
629-
630709
' processScrubAction: Handles +/- seeking for the audio trickplay bar
631710
'
632711
' @param {integer} seekStep - seconds to move the trickplay position (negative values allowed)
@@ -694,7 +773,7 @@
694773
' exitScrubMode: Moves player out of scrub mode state, resets back to standard play mode
695774
'
696775
sub exitScrubMode()
697-
m.buttons.setFocus(true)
776+
m.buttons.callFunc("focus")
698777
m.thumb.setFocus(false)
699778

700779
if m.seekPosition.visible
@@ -705,7 +784,6 @@
705784

706785
m.inScrubMode = false
707786
m.thumb.visible = false
708-
setSelectedButtonState("-default", "-selected")
709787
end sub
710788

711789
' Process key press events
@@ -752,7 +830,6 @@
752830
if key = "up"
753831
if not m.thumb.visible
754832
m.thumb.visible = true
755-
setSelectedButtonState("-selected", "-default")
756833
end if
757834
if not m.seekPosition.visible
758835
m.seekPosition.visible = true
@@ -777,38 +854,6 @@
777854
return previousClicked()
778855
else if key = "fastforward"
779856
return nextClicked()
780-
else if key = "left"
781-
if m.buttons.hasFocus()
782-
if m.queueManager.callFunc("getCount") = 1 then return false
783-
784-
if m.top.selectedButtonIndex > 0
785-
m.previouslySelectedButtonIndex = m.top.selectedButtonIndex
786-
m.top.selectedButtonIndex = m.top.selectedButtonIndex - 1
787-
end if
788-
return true
789-
end if
790-
else if key = "right"
791-
if m.buttons.hasFocus()
792-
if m.queueManager.callFunc("getCount") = 1 then return false
793-
794-
m.previouslySelectedButtonIndex = m.top.selectedButtonIndex
795-
if m.top.selectedButtonIndex < m.buttonCount - 1 then m.top.selectedButtonIndex = m.top.selectedButtonIndex + 1
796-
return true
797-
end if
798-
else if key = "OK"
799-
if m.buttons.hasFocus()
800-
if m.buttons.getChild(m.top.selectedButtonIndex).id = "play"
801-
return playAction()
802-
else if m.buttons.getChild(m.top.selectedButtonIndex).id = "previous"
803-
return previousClicked()
804-
else if m.buttons.getChild(m.top.selectedButtonIndex).id = "next"
805-
return nextClicked()
806-
else if m.buttons.getChild(m.top.selectedButtonIndex).id = "shuffle"
807-
return shuffleClicked()
808-
else if m.buttons.getChild(m.top.selectedButtonIndex).id = "loop"
809-
return loopClicked()
810-
end if
811-
end if
812857
end if
813858
end if
814859

0 commit comments

Comments
 (0)