Roku Developer Program

Join our online forum to talk to Roku developers and fellow channel creators. Ask questions, share tips with the community, and find helpful resources.
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
hugetv
Visitor

help this CustomPlaybackScreen

please help I have a problem with Custom Screen Playback works only with x channels to display and if you put more than 8 others not listed as I can make it show or change to continue showing the list

this code
Sub RunUserInterface()
o = Setup()
o.setup()
o.paint()
o.eventloop()
End Sub

Sub Setup() As Object
this = {
port: CreateObject("roMessagePort")
progress: 0 'buffering progress
position: 0 'playback position (in seconds)
paused: false 'is the video currently paused?
feedData: invalid
playing: 0
playingPrev: 0
playlistSize: 0
canvas: CreateObject("roImageCanvas") 'user interface
player: CreateObject("roVideoPlayer")
load: LoadFeed
setup: SetupFullscreenCanvas
paint: PaintFullscreenCanvas
create_playlist_text: CreatePlaylistText
drawtext: false
eventloop: EventLoop
}

this.targetRect = this.canvas.GetCanvasRect()
this.textRect = {x: 520, y: 480, w: 300, h:200}

this.load()
'Setup image canvas:
this.canvas.SetMessagePort(this.port)
this.canvas.SetLayer(0, { Color: "#000000" })
this.canvas.Show()

this.player.SetMessagePort(this.port)
this.player.SetLoop(true)
this.player.SetPositionNotificationPeriod(1)
this.player.SetDestinationRect(this.targetRect)

this.player.Play()
this.playingPrev = this.playing

return this
End Sub

Sub EventLoop()
while true
msg = wait(0, m.port)
if msg <> invalid
if msg.isStatusMessage() and msg.GetMessage() = "startup progress"
m.paused = false
print "Raw progress: " + stri(msg.GetIndex())
progress% = msg.GetIndex() / 10
if m.progress <> progress%
m.progress = progress%
m.paint()
end if

'Playback progress (in seconds):
else if msg.isPlaybackPosition()
m.position = msg.GetIndex()
print "Playback position: " + stri(m.position)

else if msg.isRemoteKeyPressed()
index = msg.GetIndex()
print "Remote button pressed: " + index.tostr()
if index = 4 '<LEFT>
m.playing = m.playing - 1
if (m.playing < 0)
m.playing = 2
endif
m.player.SetNext(m.playing)
m.player.Play()
m.playingPrev = m.playing
else if index = 8 '<REV>
m.position = m.position - 60
m.player.Seek(m.position * 1000)
else if index = 5 '<RIGHT>
m.playing = m.playing + 1
if (m.playing > 2)
m.playing = 0
endif
m.player.SetNext(m.playing)
m.player.Play()
m.playingPrev = m.playing
else if index = 9 '<REV>
m.position = m.position + 60
m.player.Seek(m.position * 1000)
else if index = 2 '<Up>
if m.drawtext
m.playing = m.playing - 1
if (m.playing < 0)
m.playing = m.playlistSize-1
endif
m.paint()
endif
else if index = 3 '<Down>
if m.drawtext
m.playing = m.playing + 1
if (m.playing > m.playlistSize-1)
m.playing = 0
endif
m.paint()
endif
else if index = 13 '<PAUSE/PLAY>
if m.paused m.player.Resume() else m.player.Pause()
else if index = 6 'OK
if m.drawtext
m.drawtext = false
if m.playing <> m.playingPrev
m.player.SetNext(m.playing)
m.player.Play()
m.playingPrev = m.playing
endif
else
m.drawtext = true
endif
m.paint()
end if

else if msg.isPaused()
m.paused = true
m.paint()

else if msg.isResumed()
m.paused = false
m.paint()

end if
endif
end while
End Sub

Sub SetupFullscreenCanvas()
m.canvas.AllowUpdates(false)
m.paint()
m.canvas.AllowUpdates(true)
End Sub

Sub PaintFullscreenCanvas()
splash = []
list = []

if m.progress < 100
progress_bar = {TargetRect: {x: 350, y: 500, w: 598, h: 37}, url: "pkg:/images/progress_bar.png"}
color = "#00a0a0a0"
splash.Push({
url: "pkg:/images/splash.png"
TargetRect: m.targetRect
})
list.Push({
Text: "Loading..."
TextAttrs: { font: "large", color: "#707070" }
TargetRect: m.textRect
})
if m.progress >= 0 AND m.progress < 20
progress_bar.url = "pkg:/images/progress_bar_1.png"
print progress_bar.url
else if m.progress >= 20 AND m.progress < 40
progress_bar.url = "pkg:/images/progress_bar_2.png"
print progress_bar.url
else if m.progress >= 40 AND m.progress < 75
progress_bar.url = "pkg:/images/progress_bar_3.png"
print progress_bar.url
else
progress_bar.url = "pkg:/images/progress_bar_4.png"
print progress_bar.url
endif
list.Push(progress_bar)

end if

if m.drawtext
textArr = m.create_playlist_text()
yTxt = 100
color = "#00000000"
index = 0
for each str in textArr
if index = m.playing
textColor = "#00ff00"
else
textColor = "#dddddd"
endif
list.Push({
Text: str
TextAttrs: {color: textColor, font: "medium"}
TargetRect: {x:200, y:yTxt, w: 500, h: 100}
})
yTxt = yTxt + 100
index = index + 1
end for
else
color = "#00000000"
list.Push({
Text: ""
TextAttrs: {font: "medium"}
TargetRect: {x:100, y:600, w: 300, h: 100}
})
endif

'Clear previous contents
m.canvas.ClearLayer(0)
m.canvas.ClearLayer(1)
m.canvas.ClearLayer(2)
m.canvas.SetLayer(0, { Color: color, CompositionMode: "Source" })
if (splash.Count() > 0)
m.canvas.SetLayer(1, splash)
m.canvas.SetLayer(2, list)
else
m.canvas.SetLayer(1, list)
endif
list.Clear()
splash.Clear()
End Sub

Function LoadFeed() as void
jsonAsString = ReadAsciiFile("pkg:/json/feed.json")
m.feedData = ParseJSON(jsonAsString)
m.playlistSize = m.feedData.Videos.Count()
contentList = []
for each video in m.feedData.Videos
contentList.Push({
Stream: { url: video.url }
StreamFormat: "mp4"
})
end for
m.player.SetContentList(contentList)
End Function

Function CreatePlaylistText() as object
textArr = []
for each video in m.feedData.Videos
textArr.Push(video.title)
end for
return textArr
End Function
Our system http://www.rokumanager.com
0 Kudos
5 REPLIES 5
hugetv
Visitor

Re: help this CustomPlaybackScreen

help this code
Our system http://www.rokumanager.com
0 Kudos
hugetv
Visitor

Re: help this CustomPlaybackScreen

greetings to all is to see how to make this code can display 200 channels since the problem is that only shows 10 channels and then siges down the list but you can not see
Our system http://www.rokumanager.com
0 Kudos
NewManLiving
Visitor

Re: help this CustomPlaybackScreen

Not really sure what you are doing, but this is an example of an imagecanvas menu. I put it together quickly and had to leave before thoroughly testing it. So if there are any issues with it, I will correct them if needed. I'll test it further when I get back - one more thing, Only tested on ROKU 3 firmware 7


' Example of wrap-around menu. Since you really don't have exact metrics,
' unless you want to use the depreciated roFontMetrics or a work-around you have to experiment
' with the height of each row based upon the font size ( medium, small ) and the alignment meta-data properties
' the usual buttons operate up/dn fw/rw for paging, can also hold the buttons down for continuous movement
Sub Main()

' Constants for isRemoteKeyPressed
kp_BK = 0
kp_UP = 2
kp_DN = 3
kp_LT = 4
kp_RT = 5
kp_OK = 6
kp_RW = 8
kp_FW = 9

' The color of the imagecanvas - of course you just need to use your own canvas
backL = 0
back = { Color:"#262626", CompositionMode: "Source" }

' Create the canvas, port and set the color of the imagecanvas
canvas = CreateObject( "roImageCanvas" )
port = CreateObject( "roMessagePort" )
canvas.SetMessagePort(port)
canvas.SetLayer( backL, back )

' Create the menu component. I strongly suggest you learn how to use AA to encapsulate a component or other
' data. Its not that hard, actually we use it all the time but don't realize it. I see that you are using
' it yourself so this should not be a problem
' Instantiate and create the menu passing a reference to your canvas, it will store it and use it
' You will need to go into the canvas.create and change the properties to place and size it according to your data
menu = NewMenu( canvas )
' Must call create before using any of its methods. Pass a reference to your data, if its more than an array of strings you will have to make the adjustments
menu.Create( GetData() )
' Show the canvas
canvas.Show()

' Unlike roScreen, when you hold down the buttons here, there is a continuous sending of the
' keydown ( at least there is with ROKU 3 firmware 7 ), you never know whats going to happen
' there are a few bugs across devices with the new update. You write it today, its broken tomorrow
' And you never know when your going to get those "sounds", up/down you dont but fw and rw you do
while( True )
msg = wait( 0, port )
if ( type( msg ) = "roImageCanvasEvent" )

if ( msg.isRemoteKeyPressed() )
i = msg.GetIndex()

' All you have to do is use the members of the menu component to scroll
' when the proper buttons are pressed. up/dn moves the selector first
' if the selector is up against the top or bottom rows, then the menu scrolls and
' the selector is updated
' For paging, an entire page is redrawn
if (i = kp_BK ) then
canvas.close()
else if ( i = kp_DN )
menu.ScrollDown()
else if ( i = kp_UP )
menu.ScrollUp()
else if ( i = kp_FW )
menu.PageDown()
else if ( i = kp_RW )
menu.PageUp()
else if( i = kp_OK )
print menu.GetText()
end if
else if (msg.isScreenClosed()) then
return
end if
end if
end while
End Sub

' The menu component is designed using an Associative Array
' To instantiate an instance var = NewManu() passing a reference to your canvas
Function NewMenu( a_canvas As Object ) As Object

return {
' Reference to the created image canvas
Canvas: a_canvas

' Reference to the Array of data, if you need to include description text or anything else
' then make this an array of AA { Text: text Description: desc } m.Data[ IndexTop ].Text
Data: Invalid
' The number of items in Data
DataCount: 0
' The row the the selector is on ( indexTop to IndexBot
RowIndex: 0
' The selectors text index within Data
FocusIndex: 0
' Top and bottom indexes of the menu ( what is displayed on the first line and last line
IndexTop: 0
IndexBot: 0

' Offset from the sides of the backgound of the menu
Margin: 0
' The height of each row, you have to set this according to how much space you want
' between rows, and the size of your text
RowHeight: 0'
' Number of visible rows in the menu
PageSize: 0
' RowHeight * PageSize = the menu height
PageHeight: 0

' Meta-data for the menu backgound and selector background
MenuBkg: Invalid
SelBkg: Invalid

' Meta-data for the text displayed in the menu,
' this is an array of PageSize. As the user scrolls it is updated
MenuText: Invalid
' The single line of text over the selector that changes as the user scrolls
SelText: Invalid
' Layer constants
menuL: 2
menuTL: 3
menuSL: 4
menuSTL: 5

' Functions that act upon the data above using the m pointer
' Creates the menu component
Create: menu_create
' Draws/redraws a page of data
DrawPage: menu_draw_page
' The scrolling and paging functions
ScrollUp: menu_scroll_up
ScrollDown: menu_scroll_down
PageDown: menu_page_down
PageUp: menu_page_up
GetText: menu_get_text
}


End Function

' The menu's create function MUST be called before calling any other functions - NO error checking is done
' Pass in the data - can be a complex data type (AA) but you would have to modify the code to assign
' the proper field
Function menu_create( a_data As Object ) As Void

' Store a reference to data
m.Data = a_data
' The total count of data and the page size is set to 12 rows, you can change this to what you want
m.DataCount = m.Data.count()
m.PageSize = 12
' Insure the pagesize is within range
if ( m.PageSize > m.DataCount ) then m.PageSize = m.DataCount

' The margin is the space that borders the menu so that the menu text is not flushed against the edges
m.Margin = 5
' This is the height that I use for the Medium font, you have to adjust to your own font size
' You will also have to adjust the text metadata alignment properties to get it to center properly
m.RowHeight = 45
' So then the pageHeight or menu Height would be te following:
m.PageHeight = m.RowHeight * m.PageSize + m.Margin * 2

' This is the menu rectangle you adjust this according to your own needs
' its width would have to accomodate your largest text width and the height is
' determined by how many rows you are going to display. the x, y is where you want it in your canvas
mr = { x: 100, y: 90, w: 295, h: m.PageHeight }
' The selector rectangle ( blue ) rides above each row so it is the same except for the height
' which is only one row
sr = { x: mr.x, y: mr.y + m.Margin, w: mr.w, h: m.RowHeight }

' Set your meta-data for the layers
' Menu menu background
m.menuBkg = {
Color: "#353535"
TargetRect: mr
CompositionMode: "Source" }

' Selector background
m.SelBkg = {
Color: "#436372"
TargetRect: sr
CompositionMode:"Source" }

' The menu text is an array of meta data just for the text that sits
' on top of the menu backgound. So it will be the pagesize of the menu
m.menuText = CreateObject( "roArray", m.PageSize, False )

' Since The menu backgound is a different color from the canvas background
' I don't want the text to start at the edges so I'm going to offset the text
x = mr.x + m.Margin * 3
y = mr.y + m.Margin * 2
' The width is the menu width
w = mr.w
' And the text height is the row height. For h and ta you have to experiment with the size and alignment
' if you change the font size. with the medium font, 45 height and VAlign it is centered properly
h = m.RowHeight
' This is static so just create a variable for it.
ta = { Color: "#707070", Font: "Medium", HAlign:"Left",
VAlign: "Top", Direction: "LeftToRight" }

' Now create a text meta-data for each row in the page and store it into the menuText array
for i = 1 to m.PageSize
mt = {
Text: ""
TargetRect: { x: x , y: y , w: w, h: h }
TextAttrs: ta
CompositionMode: "Source"
}

m.menuText.Push( mt )
' Increment y by the row height
y = y + h
end for

' The selection text is only one row
m.SelText = {
Text: ""
TargetRect: { x: x , y: mr.y + m.Margin * 2, w: w, h: h }
TextAttrs: { Color: "#FFFFFF", Font: "Medium", HAlign:"Left",
VAlign: "Top", Direction: "LeftToRight"}
CompositionMode: "Source"
}

' These are the controlling indexes for the scrolling and
' paging functions
m.IndexTop = 0
m.IndexBot = 0
' This index keeps tract of the row in the menu that the selector is on
m.RowIndex = 0
' This index keeps tract of the text that is in the selector
m.FocusIndex = 0

' Call DrawPage to setup the first page, with false ( dont want it to redraw the canvas here )
' That will be done with the initial showing of the canvas
m.DrawPage( False )

' Then finally, set your layers
' Menu Background - If you do this some other way ( after showing the canvas ) you will have to
' turn off the AllowUpdates
m.canvas.SetLayer( m.menuL , m.menuBkg )
' The complete page of text over the background
m.canvas.SetLayer( m.menuTL, m.menuText )
' The selector background
m.canvas.SetLayer( m.menuSL, m.SelBkg )
' And finally the selectors text
m.canvas.SetLayer( m.menuSTL, m.SelText )

End Function

' Returns the selected text
Function menu_get_text() As String
return m.SelText.Text
End Function

' refresh menu meta data to index of user input
Function menu_draw_page( a_update = True As Boolean ) As Void

' I generally simplify references as I really do not know
' if it provides any optimization, but being a geriatric-programmer 🙂
' I come from environments where it did, especially in loops
menuText = m.MenuText
data = m.Data
index = m.IndexTop
count = m.DataCount

' So based upon where the indextop is
' you begin to draw from the top down, starting at
' indexTop ( index = m.IndexTop ), which is calculated in the
' scrolling functions below. Just wrap around if it reaches the bottom
for i = 0 to m.PageSize - 1
menuText[i].Text = data[ index ]
index = index + 1
if ( index >= count ) then index = 0
end for

' Then recalc the bottom index , or the row at the bottom of the menu
index = index - 1
if ( index < 0 ) then index = count - 1
m.IndexBot = index

' Adjust the focus index allowing for wrap-around
' and set the new selected text
index = m.RowIndex + m.IndexTop
if ( index >= count ) then index = index - count
m.FocusIndex = index
m.SelText.Text = data[ index ]

' if a_update is True (default) then update the canvas
if ( a_update )
iCanvas = m.Canvas
iCanvas.AllowUpdates( False )
iCanvas.SetLayer( m.menuTL, menuText )
iCanvas.SetLayer( m.menuSTL, m.SelText )
iCanvas.AllowUpdates( True )
end if

End Function

' Scrolls down one row
Function menu_scroll_down() As Void

' If the selector is not at the bottom
if ( m.RowIndex < m.PageSize - 1 )
' Increment its row
m.RowIndex = m.RowIndex + 1
' Increment the selector's text focusindex, wrap-around if needed
index = m.FocusIndex + 1
if ( index >= m.DataCount ) then index = 0
m.FocusIndex = index

' Change the meta-data
m.SelText.Text = m.Data[ index ]
tRect = m.SelBkg.TargetRect
tRect.y = tRect.y + m.RowHeight
tRect = m.SelText.TargetRect
tRect.y = tRect.y + m.RowHeight
' Redraw the layers and return
iCanvas = m.Canvas
iCanvas.AllowUpdates( False )
iCanvas.SetLayer( m.menuSL, m.SelBkg )
iCanvas.SetLayer( m.menuSTL, m.SelText )
iCanvas.AllowUpdates( True )
return
end if
' Otherwise the selector is at the bottom
' so increase the top index by one and redraw the page
' the Focusindex will be handled in DrawPage. It does not move just
' changes its text
m.IndexTop = m.IndexTop + 1
if ( m.IndexTop >= m.DataCount ) then m.IndexTop = 0
m.DrawPage()
End Function

' Same as above only going in the opposite direction
Function menu_scroll_up() As Void

if ( m.RowIndex > 0 )
m.RowIndex = m.RowIndex - 1

index = m.FocusIndex - 1
if ( index < 0 ) then index = m.DataCount - 1
m.FocusIndex = index

m.SelText.Text = m.Data[ index ]
tRect = m.SelBkg.TargetRect
tRect.y = tRect.y - m.RowHeight
tRect = m.SelText.TargetRect
tRect.y = tRect.y - m.RowHeight
iCanvas = m.Canvas
iCanvas.AllowUpdates( False )
iCanvas.SetLayer( m.menuSL, m.SelBkg )
iCanvas.SetLayer( m.menuSTL, m.SelText )
iCanvas.AllowUpdates( True )
return
end if

' Selector is at the top so scroll up
m.IndexTop = m.IndexTop - 1
if ( m.IndexTop < 0 ) then m.IndexTop = m.DataCount - 1
m.DrawPage()
End Function

' Paging down - use the bottom index as the reference point
' to change the top index, wrap around if needed and redraw the page
' the focusindex will be updated in drawpage
Function menu_page_down() As Void
index = m.IndexBot + 1
if ( index >= m.DataCount ) then index = 0
m.IndexTop = index
m.DrawPage()
End Function

' When moving back a page you decrement the top index by the page size
' Wrap around correctly if needed, set the new TopIndex and redraw the page
Function menu_page_up() As Void
index = m.IndexTop - m.PageSize
if ( index < 0 ) then index = m.DataCount + index
m.IndexTop = index
m.DrawPage()
End Function

' Get sample data - just returns strings here but you can return
' anything just make sure you make the changes when assigning the Text to the correct field
Function GetData() As Object
l_data = []
for l_i = 1 to 200
l_text = l_i.ToStr()

if ( l_i < 100 )
if ( l_i < 10 )
l_text = "00" + l_text
else
l_text = "0" + l_text
end if
end if
l_text = "Menu Item Number " + l_text
l_data.Push( l_text )
end for
return l_data
End Function

My Channels: 2D API Framework Presentation: https://owner.roku.com/add/2M9LCVC
Updated: 11-11-2015 - Completed Keyboard interface
The Joel Channel ( Final Beta )
0 Kudos
NewManLiving
Visitor

Re: help this CustomPlaybackScreen

Optimized - removed focusindex, indexbot calculations, changed for loop in drawpage to for_each

' Example of wrap-around menu.  Since you really don't have exact metrics, 
' unless you want to use the depreciated roFontMetrics or a work-around you have to experiment
' with the height of each row based upon the font size ( medium, small ) and the alignment meta-data properties
' the usual buttons operate up/dn fw/rw for paging, can also hold the buttons down for continuous movement
Sub Main()

' Constants for isRemoteKeyPressed
kp_BK = 0
kp_UP = 2
kp_DN = 3
kp_LT = 4
kp_RT = 5
kp_OK = 6
kp_RW = 8
kp_FW = 9

' The color of the imagecanvas - of course you just need to use your own canvas
backL = 0
back = { Color:"#262626", CompositionMode: "Source" }

' Create the canvas, port and set the color of the imagecanvas
canvas = CreateObject( "roImageCanvas" )
port = CreateObject( "roMessagePort" )
canvas.SetMessagePort(port)
canvas.SetLayer( backL, back )

' Create the menu component. I strongly suggest you learn how to use AA to encapsulate a component or other
' data. Its not that hard, actually we use it all the time but don't realize it. I see that you are using
' it yourself so this should not be a problem
' Instantiate and create the menu passing a reference to your canvas, it will store it and use it
' You will need to go into the canvas.create and change the properties to place and size it according to your data
menu = NewMenu( canvas )
' Must call create before using any of its methods. Pass a reference to your data, if its more than an array of strings you will have to make the adjustments
menu.Create( GetData() )
' Show the canvas
canvas.Show()

' Unlike roScreen, when you hold down the buttons here, there is a continuous sending of the
' keydown ( at least there is with ROKU 3 firmware 7 ), you never know whats going to happen
' there are a few bugs across devices with the new update. You write it today, its broken tomorrow
' And you never know when your going to get those "sounds", up/down you dont but fw and rw you do
while( True )
msg = wait( 0, port )
if ( type( msg ) = "roImageCanvasEvent" )

if ( msg.isRemoteKeyPressed() )
i = msg.GetIndex()

' All you have to do is use the members of the menu component to scroll
' when the proper buttons are pressed. up/dn moves the selector first
' if the selector is up against the top or bottom rows, then the menu scrolls and
' the selector is updated
' For paging, an entire page is redrawn
if (i = kp_BK ) then
canvas.close()
else if ( i = kp_DN )
menu.ScrollDown()
else if ( i = kp_UP )
menu.ScrollUp()
else if ( i = kp_FW )
menu.PageDown()
else if ( i = kp_RW )
menu.PageUp()
else if( i = kp_OK )
print menu.GetText()
end if
else if (msg.isScreenClosed()) then
return
end if
end if
end while
End Sub

' The menu component is designed using an Associative Array
' To instantiate an instance var = NewManu() passing a reference to your canvas
Function NewMenu( a_canvas As Object ) As Object

return {
' Reference to the created image canvas
Canvas: a_canvas

' Reference to the Array of data, if you need to include description text or anything else
' then make this an array of AA { Text: text Description: desc } m.Data[ IndexTop ].Text
Data: Invalid
' The number of items in Data
DataCount: 0
' The row the the selector is on
RowIndex: 0

' Data index of first line in menu
IndexTop: 0

' Offset from the sides of the backgound of the menu
Margin: 0
' The height of each row, you have to set this according to how much space you want
' between rows, and the size of your text
RowHeight: 0'
' Number of visible rows in the menu
PageSize: 0
' RowHeight * PageSize = the menu height
PageHeight: 0

' Meta-data for the menu backgound and selector background
MenuBkg: Invalid
SelBkg: Invalid

' Meta-data for the text displayed in the menu,
' this is an array of PageSize. As the user scrolls it is updated
MenuText: Invalid
' The single line of text over the selector that changes as the user scrolls
SelText: Invalid
' Layer constants
menuL: 2
menuTL: 3
menuSL: 4
menuSTL: 5

' Functions that act upon the data above using the m pointer
' Creates the menu component
Create: menu_create
' Draws/redraws a page of data
DrawPage: menu_draw_page
' The scrolling and paging functions
ScrollUp: menu_scroll_up
ScrollDown: menu_scroll_down
PageDown: menu_page_down
PageUp: menu_page_up
GetText: menu_get_text
}


End Function

' The menu's create function MUST be called before calling any other functions - NO error checking is done
' Pass in the data - can be a complex data type (AA) but you would have to modify the code to assign
' the proper field
Function menu_create( a_data As Object ) As Void

' Store a reference to data
m.Data = a_data
' The total count of data and the page size is set to 12 rows, you can change this to what you want
m.DataCount = m.Data.count()
m.PageSize = 12
' Insure the pagesize is within range
if ( m.PageSize > m.DataCount ) then m.PageSize = m.DataCount

' The margin is the space that borders the menu so that the menu text is not flushed against the edges
m.Margin = 5
' This is the height that I use for the Medium font, you have to adjust to your own font size
' You will also have to adjust the text metadata alignment properties to get it to center properly
m.RowHeight = 45
' So then the pageHeight or menu Height would be te following:
m.PageHeight = m.RowHeight * m.PageSize + m.Margin * 2

' This is the menu rectangle you adjust this according to your own needs
' its width would have to accomodate your largest text width and the height is
' determined by how many rows you are going to display. the x, y is where you want it in your canvas
mr = { x: 100, y: 90, w: 295, h: m.PageHeight }
' The selector rectangle ( blue ) rides above each row so it is the same except for the height
' which is only one row
sr = { x: mr.x, y: mr.y + m.Margin, w: mr.w, h: m.RowHeight }

' Set your meta-data for the layers
' Menu menu background
m.menuBkg = {
Color: "#353535"
TargetRect: mr
CompositionMode: "Source" }

' Selector background
m.SelBkg = {
Color: "#436372"
TargetRect: sr
CompositionMode:"Source" }

' The menu text is an array of meta data just for the text that sits
' on top of the menu backgound. So it will be the pagesize of the menu
m.menuText = CreateObject( "roArray", m.PageSize, False )

' Since The menu backgound is a different color from the canvas background
' I don't want the text to start at the edges so I'm going to offset the text
x = mr.x + m.Margin * 3
y = mr.y + m.Margin * 2
' The width is the menu width
w = mr.w
' And the text height is the row height. For h and ta you have to experiment with the size and alignment
' if you change the font size. with the medium font, 45 height and VAlign it is centered properly
h = m.RowHeight
' This is static so just create a variable for it.
ta = { Color: "#707070", Font: "Medium", HAlign:"Left",
VAlign: "Top", Direction: "LeftToRight" }

' Now create a text meta-data for each row in the page and store it into the menuText array
for i = 1 to m.PageSize
mt = {
Text: ""
TargetRect: { x: x , y: y , w: w, h: h }
TextAttrs: ta
CompositionMode: "Source"
}

m.menuText.Push( mt )
' Increment y by the row height
y = y + h
end for

' The selection text is only one row
m.SelText = {
Text: ""
TargetRect: { x: x , y: mr.y + m.Margin * 2, w: w, h: h }
TextAttrs: { Color: "#FFFFFF", Font: "Medium", HAlign:"Left",
VAlign: "Top", Direction: "LeftToRight"}
CompositionMode: "Source"
}

' These are the controlling indexes for the scrolling and
' paging functions
m.IndexTop = 0
' This index keeps tract of the row in the menu that the selector is on
m.RowIndex = 0

' Call DrawPage to setup the first page, with false ( dont want it to redraw the canvas here )
' That will be done with the initial showing of the canvas
m.DrawPage( False )

' Then finally, set your layers
' Menu Background - If you do this some other way ( after showing the canvas ) you will have to
' turn off the AllowUpdates
m.canvas.SetLayer( m.menuL , m.menuBkg )
' The complete page of text over the background
m.canvas.SetLayer( m.menuTL, m.menuText )
' The selector background
m.canvas.SetLayer( m.menuSL, m.SelBkg )
' And finally the selectors text
m.canvas.SetLayer( m.menuSTL, m.SelText )

End Function

' Returns the selected text
Function menu_get_text() As String
return m.SelText.Text
End Function

' refresh menu meta data to index of user input
Function menu_draw_page( a_update = True As Boolean ) As Void

' I generally simplify references as I really do not know
' if it provides any optimization, but being a geriatric-programmer 🙂
' I come from environments where it did, especially in loops
menuText = m.MenuText
data = m.Data
index = m.IndexTop
count = m.DataCount

' So based upon where the indextop is
' you begin to draw from the top down, starting at
' indexTop ( index = m.IndexTop ), which is calculated in the
' scrolling functions below. Just wrap around if it reaches the bottom
for each item in menuText
item.Text = data[ index ]
index = index + 1
if ( index >= count ) then index = 0
end for

' Adjust the focus index allowing for wrap-around
' and set the new selected text
index = m.RowIndex + m.IndexTop
if ( index >= count ) then index = index - count
m.SelText.Text = data[ index ]

' if a_update is True (default) then update the canvas
if ( a_update )
iCanvas = m.Canvas
iCanvas.AllowUpdates( False )
iCanvas.SetLayer( m.menuTL, menuText )
iCanvas.SetLayer( m.menuSTL, m.SelText )
iCanvas.AllowUpdates( True )
end if

End Function

' Scrolls down one row
Function menu_scroll_down() As Void

' If the selector is not at the bottom
if ( m.RowIndex < m.PageSize - 1 )
' Increment its row
m.RowIndex = m.RowIndex + 1

' Calculate the focus index
index = m.RowIndex + m.IndexTop
if ( index >= m.DataCount ) then index = index - m.DataCount
m.SelText.Text = m.Data[ index ]

' Change the meta-data
tRect = m.SelBkg.TargetRect
tRect.y = tRect.y + m.RowHeight
tRect = m.SelText.TargetRect
tRect.y = tRect.y + m.RowHeight
' Redraw the layers and return
iCanvas = m.Canvas
iCanvas.AllowUpdates( False )
iCanvas.SetLayer( m.menuSL, m.SelBkg )
iCanvas.SetLayer( m.menuSTL, m.SelText )
iCanvas.AllowUpdates( True )
return
end if
' Otherwise the selector is at the bottom
' so increase the top index by one and redraw the page
' the Focus index will be handled in DrawPage. It does not move just
' changes its text
m.IndexTop = m.IndexTop + 1
if ( m.IndexTop >= m.DataCount ) then m.IndexTop = 0
m.DrawPage()
End Function

' Same as above only going in the opposite direction
Function menu_scroll_up() As Void

if ( m.RowIndex > 0 )
m.RowIndex = m.RowIndex - 1

index = m.RowIndex + m.IndexTop
if ( index >= m.DataCount ) then index = index - m.DataCount
m.SelText.Text = m.Data[ index ]

tRect = m.SelBkg.TargetRect
tRect.y = tRect.y - m.RowHeight
tRect = m.SelText.TargetRect
tRect.y = tRect.y - m.RowHeight
iCanvas = m.Canvas
iCanvas.AllowUpdates( False )
iCanvas.SetLayer( m.menuSL, m.SelBkg )
iCanvas.SetLayer( m.menuSTL, m.SelText )
iCanvas.AllowUpdates( True )
return
end if

' Selector is at the top so scroll up
m.IndexTop = m.IndexTop - 1
if ( m.IndexTop < 0 ) then m.IndexTop = m.DataCount - 1
m.DrawPage()
End Function

'Paging down woulb be the top index + page size, corrected for wrap around
Function menu_page_down() As Void
index = m.IndexTop + m.PageSize
if ( index >= m.DataCount ) then index = index - m.DataCount
m.IndexTop = index
m.DrawPage()
End Function

' When moving back a page you decrement the top index by the page size
' Wrap around correctly if needed, set the new TopIndex and redraw the page
Function menu_page_up() As Void
index = m.IndexTop - m.PageSize
if ( index < 0 ) then index = m.DataCount + index
m.IndexTop = index
m.DrawPage()
End Function

' Get sample data - just returns strings here but you can return
' anything just make sure you make the changes when assigning the Text to the correct field
Function GetData() As Object
l_data = []
for l_i = 1 to 200
l_text = l_i.ToStr()

if ( l_i < 100 )
if ( l_i < 10 )
l_text = "00" + l_text
else
l_text = "0" + l_text
end if
end if
l_text = "Menu Item Number " + l_text
l_data.Push( l_text )
end for
return l_data
End Function

My Channels: 2D API Framework Presentation: https://owner.roku.com/add/2M9LCVC
Updated: 11-11-2015 - Completed Keyboard interface
The Joel Channel ( Final Beta )
0 Kudos
hugetv
Visitor

Re: help this CustomPlaybackScreen

perfect but I'm using the sample channel and the menu bar and open on the same therefore selected
Our system http://www.rokumanager.com
0 Kudos
Need Assistance?
Welcome to the Roku Community! Feel free to search our Community for answers or post your question to get help.

Become a Roku Streaming Expert!

Share your expertise, help fellow streamers, and unlock exclusive rewards as part of the Roku Community. Learn more.