Channel "Loading" screen - as seen in PodTV and KoldcastTV

I just tried both PodTV and KoldcastTV for the first time, and they both shared something that I haven’t seen in other channels.

When you first launch the channel, you are greeted with a minimalistic loading screen. It has a solid-black background, and prominently displays the channel logo with the “loading…” written underneath it.

Is this a new feature in the 2.8 SDK? If not, are there best-practices that Roku wants to encourage when implementing something like this?

Not a new feature.. just an roImageCanvas, if I’m not mistaken. My MainSqueeze channel implemented something similar back in 2.6.

I’m not sure how RokuChris does it (I believe he’s the developer of both of the channels that you mentioned), but if you’re interested, here’s a simplified version of my implementation that uses the HD channel icon… I put this in my RunUserInterface() method instead of the facade screen…

deviceInfo = CreateObject( "roDeviceInfo" )
displaySize = deviceInfo.GetDisplaySize()
background = {
    Color: "#000000"
}
loadingImage = {
    Url: "pkg:/images/mm_icon_focus_hd.png"
    TargetRect: {
        x: Int( displaySize.w / 2 ) - Int( 336 / 2 ),
        y: Int( displaySize.h / 2 ) - Int( 209 / 2 ),
        w: 336,
        h: 209
    }
}
loadingText = {
    Text: "Loading...",
    TextAttrs: {
        Font: "Large",
        VAlign: "Top"
    },
    TargetRect: {
        x: loadingImage.TargetRect.x,
        y: loadingImage.TargetRect.y + 25,
        w: loadingImage.TargetRect.w,
        h: 30
    }
}
canvas = CreateObject( "roImageCanvas" )
canvas.SetLayer( 0, [ background, loadingImage, loadingText ] )
canvas.Show()

i thought i would give this a try and im getting the following error

006: Sub RunUserInterface()
007:
008: deviceInfo = CreateObject( "roDeviceInfo" )
009: displaySize = deviceInfo.GetDisplaySize()
010: background = {
011:     Color: "#000000"
012: }
013: loadingImage = {
014:     Url: "pkg:/images/MainMenu_Icon_CenterFocus_HD.png"
015:     TargetRect: {
016:         x: Int( displaySize.w / 2 ) - Int( 336 / 2 ),
017:         y: Int( displaySize.h / 2 ) - Int( 209 / 2 ),
018:         w: 336,
019:         h: 209
020:     }
021: }
022: loadingText = {
023:     Text: "Loading...",
024:     TextAttrs: {
025:         Font: "Large",
026:         VAlign: "Top"
027:     },
028:     TargetRect: {
029:         x: loading.TargetRect.x,
030:         y: loading.TargetRect.y + 25,
031:         w: loading.TargetRect.w,
032:         h: 30
033:     }
034: }
035: canvas = CreateObject( "roImageCanvas" )
036: canvas.SetLayer( 0, [ background, loadingImage, loadingText ] )
037: canvas.Show()
038:
039: showWelcomeScreen()
040: homeMain()
041:
042:
043: End Sub
/tmp/plugin/NEAAAAa9pBYR/pkg:/source/appMain.brs(29): runtime error ec: 'Dot' Op
erator attempted with invalid BrightScript Component or interface reference.

029:         x: loading.TargetRect.x,

Backtrace:
Function runuserinterface() As Void

i added these cause i wasnt sure if i need them as they are in my sub main()

039: showWelcomeScreen()
040: homeMain()

I also took out the sub main(), do i need to?

Sorry, “loading” on lines 29-31 should be “loadingImage”. That’s what I get for making a last minute change to the code without testing. I’ve updated my original code snippet.

thanks endless now i have two questions about this screen.

1.) is there a way to set a time on it?

2.) I do not want it showing twice, its also showing after i click the start button on the welcome screen. i tried doing a canvas.close but it didnt like that. it just exited the channel

the way i have it now is

Sub RunUserInterface()
 deviceInfo = CreateObject( "roDeviceInfo" )
 displaySize = deviceInfo.GetDisplaySize()
background = {
    Color: "#000000"
 }
loadingImage = {
    Url: "pkg:/images/MainMenu_Icon_CenterFocus_HD.png"
     TargetRect: {
        x: Int( displaySize.w / 2 ) - Int( 336 / 2 ),
         y: Int( displaySize.h / 2 ) - Int( 209 / 2 ),
         w: 336,
         h: 209
     }
 }
 loadingText = {
     Text: "Loading...",
     TextAttrs: {
         Font: "Large",
         VAlign: "Top"
     },
     TargetRect: {
         x: loading.TargetRect.x,
         y: loading.TargetRect.y + 25,
         w: loading.TargetRect.w,
         h: 30
     }
 }
canvas = CreateObject( "roImageCanvas" )
canvas.SetLayer( 0, [ background, loadingImage, loadingText ] )
canvas.Show()

initTheme()
showWelcomeScreen()
homeMain()
End Sub

but its going in this order
1.) RunUserInterface()
2.) showWelcomeScreen()
3.) RunUserInterface()
4.) homeMain()

i dont want that i just want it going like this
1.) RunUserInterface()
2.) showWelcomeScreen()
3.) homeMain()

No idea why RunUserInterface would be getting called twice, unless you’re explicitly calling it in your code somewhere… ?

i had to take it out for now… however i did like it…

i must have it called somewhere or maybe its cause its not closing out the screen or something…

Is it possible to set a timer on hit however?

You should add a screen facade to assure there’s always a screen in the display stack whenever your channel is executing.

Add it to your RunUserInterface() method like so:


    'display a fake screen while the real one initializes. this screen
    'has to live for the duration of the whole app to prevent flashing
    'back to the roku home screen.
    screenFacade = CreateObject("roPosterScreen")
    screenFacade.show()

    showWelcomeScreen()
    homeMain()

    'exit the app gently so that the screen doesn't flash to black
    screenFacade.showMessage("")
    sleep(25)

–Kevin

unless i am missing something or did something wrong here. this code below skips past everything and goes straight to the welcome screen

Sub RunUserInterface()
deviceInfo = CreateObject( "roDeviceInfo" )
displaySize = deviceInfo.GetDisplaySize()
background = {
    Color: "#000000"
}
loadingImage = {
    Url: "pkg:/images/Logo.png"
     TargetRect: {
        x: Int( displaySize.w / 2 ) - Int( 336 / 2 ),
         y: Int( displaySize.h / 2 ) - Int( 209 / 2 ),
         w: 365,
         h: 110
     }
}
loadingText = {
     Text: "Loading...",
     TextAttrs: {
         Font: "Large",
         VAlign: "Bottom"
     },
     TargetRect: {
        x: loadingImage.TargetRect.x,
        y: loadingImage.TargetRect.y + 225,
        w: loadingImage.TargetRect.w,
        h: 30
     }
}
canvas = CreateObject( "roImageCanvas" )
canvas.SetLayer( 0, [ background, loadingImage, loadingText ] )
canvas.Show()

initTheme()
    screenFacade = CreateObject("roPosterScreen")
    screenFacade.show()

    showWelcomeScreen()
    homeMain()

    screenFacade.showMessage("")
    sleep(25)

End Sub

hello. i am trying to use this code in my app main file using the video player example.

i modified it to match the functions i am using and get this error. the screen loads the image and immediately goes to the home screen. it doesnt have the 3-5 sec pause. thanks.

Sub RunUserInterface()
    deviceInfo = CreateObject( "roDeviceInfo" )
    displaySize = deviceInfo.GetDisplaySize()
    background = {
        Color: "#FFFFFF"
    }
    loadingImage = {
        Url: "pkg:/images/MainMenu_Icon_CenterFocus_HD.png"
         TargetRect: {
            x: Int( displaySize.w / 2 ) - Int( 336 / 2 ),
             y: Int( displaySize.h / 2 ) - Int( 209 / 2 ),
             w: 365,
             h: 110
         }
    }
    loadingText = {
         Text: "Loading...",
         TextAttrs: {
             Font: "Large",
             VAlign: "Bottom"
             Color: "#000000"
         },
         TargetRect: {
            x: loadingImage.TargetRect.x,
            y: loadingImage.TargetRect.y + 225,
            w: loadingImage.TargetRect.w,
            h: 30
         }
    }
    canvas = CreateObject( "roImageCanvas" )
    canvas.SetLayer( 0, [ background, loadingImage, loadingText ] )
    canvas.Show()
 
    
    
    Main()

    End Sub

“uarlive” wrote:
the screen loads the image and immediately goes to the home screen. it doesnt have the 3-5 sec pause.
If you want it to display for a few seconds, then you’ll need to add a sleep. In my channel, there is background processing going on, but if you don’t have that, then you’ll need an artificial pause.

try something like this:

opening_timer.Mark()
     While true
           msg = Wait( 1000, msgPort )
              print "the seconds are: "; opening_timer.TotalSeconds()
              timer = opening_timer.TotalSeconds()
		      if timer = 2 then
                      Main() 
       exit while
		      end if
       end while
End sub

Its more of a timer but works if you got anything going in the background. I am sure it can be even written different i didn’t test it, not in front of my work PC to see what we use exactly… test it out and let us know

“dynamitemedia” wrote:
try something like this:

opening_timer.Mark()
     While true
           msg = Wait( 1000, msgPort )
              print "the seconds are: "; opening_timer.TotalSeconds()
              timer = opening_timer.TotalSeconds()
		      if timer = 2 then
                      Main() 
       exit while
		      end if
       end while
End sub

Its more of a timer but works if you got anything going in the background. I am sure it can be even written different i didn’t test it, not in front of my work PC to see what we use exactly… test it out and let us know
Unless you have some asynchronous processing going on, the same can be accomplished with a Sleep(2000)… That code will also lock up indefinitely if anything causes it to wait longer than a second (should be >= 2).

I mentioned i was not in front of a PC to test, didn’t say it was 100% correct and to try it.

I also said i am doing something in the background thus i do not do use a sleep, and was giving him a way to do a artificial sleep.

I would also like to know how this could lock something up at a opening of a channel? is it something we need to change? cause it has never gave me a bit of problems.

“dynamitemedia” wrote:
I would also like to know how this could lock something up at a opening of a channel? is it something we need to change? cause it has never gave me a bit of problems.
Assuming you’re actually listening for something in that loop (or even if there’s something to cause a hiccup in the wait), it could cause enough of a delay that TotalSeconds skips to 3. Checking for “= 2” would cause it to hang forever if that condition is missed, so you should use “>= 2”. Even then, though, if you are actually listening for something, bailing after 2 seconds seems like it would likely cause problems if what you’re listening for takes longer than that to complete.

thanks. i wound up using the sleep(3500).

Can someone get this up on github please?