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: 
marsradio
Visitor

Need to Modify SDK Videoplayer to Allow Display of Image

I'm guessing that this is a unique need here, and I'm wondering if this is even possible. I'm building a video channel using "Videoplayer" from the SDK as my template guide. I've figured out how to set it up to play videos using my own custom XML files. That was the easy part. Here's what I'm stuck on: is it possible to modify the channel code, or the XML code or both to allow for ONE of my Categories to fetch and display a remote static .gif image instead of a remote mp4 video?
Here's a little more insight into what I'm trying to create here: the channel is weather-related. It will primarily host videos of weather events (again, this part is complete...XML files that point to the videos - no problem), but I want one Category to point to static .gif images which consist of forecast maps published by the National Weather Service. The URL for These .gifs never change. So a static link to these .gifs will always yield the latest forecast map. It's this last Category feature that I'm racking my brain on. How do I make this Category display these images when the code is looking for an mp4 video file to play? If it's any help: these .gifs display perfectly within the small sd and hd Poster frame, and they do show the latest .gif within that small frame. Now if only I could figure out how to expand it to full screen so the viewer can see it better.
Any help is greatly appreciated.
0 Kudos
9 REPLIES 9
RokuJoel
Binge Watcher

Re: Need to Modify SDK Videoplayer to Allow Display of Image

Take a look at the function showDetailScreen in the file appDetailScreen.brs

find this spot:



if msg.GetIndex() = 1
PlayStart = RegRead(showList[showIndex].ContentId)
if PlayStart <> invalid then
showList[showIndex].PlayStart = PlayStart.ToInt()
endif
showVideoScreen(showList[showIndex])
refreshShowDetail(screen,showList,showIndex)
endif
if msg.GetIndex() = 2
showList[showIndex].PlayStart = 0
showVideoScreen(showList[showIndex])
refreshShowDetail(screen,showList,showIndex)


what you would want to do is add some logic to check for an image and then write an image display function that would display the image, otherwise, play a video.

For example, in your xml, you could set <contentType>image</contentType> and or <streamFormat>.gif</streamformat>

Then in the above function you could have:
               if msg.GetIndex() = 2
showList[showIndex].PlayStart = 0

if Showlist[ShowIndex].streamformat=".gif" or Showlist[Showindex].StreamFormat="image" then
showImage(showlist[showindex])
else
showVideoScreen(showList[showIndex])
end if

refreshShowDetail(screen,showList,showIndex)


- Joel
0 Kudos
marsradio
Visitor

Re: Need to Modify SDK Videoplayer to Allow Display of Image

Joel:
As always, thank you for replying and for your help.

I believe I did what you recommended, but I'm still not able to open the image to full screen. When I press "Play," the screen goes black and the "retrieving" bar starts to load for about a half second. Then it quits and returns back to where I just was.

Here is the section of code from the apsDetailScreen.brs which I believe I modified exactly as you suggested. I'm pasting the entire section just for reference:

PORTION OF apsDetailScreen.brs CODE:


'***************************************************************
'** The show detail screen (springboard) is where the user sees
'** the details for a show and is allowed to select a show to
'** begin playback. This is the main event loop for that screen
'** and where we spend our time waiting until the user presses a
'** button and then we decide how best to handle the event.
'***************************************************************
Function showDetailScreen(screen As Object, showList As Object, showIndex as Integer) As Integer

if validateParam(screen, "roSpringboardScreen", "showDetailScreen") = false return -1
if validateParam(showList, "roArray", "showDetailScreen") = false return -1

refreshShowDetail(screen, showList, showIndex)

'remote key id's for left/right navigation
remoteKeyLeft = 4
remoteKeyRight = 5

while true
msg = wait(0, screen.GetMessagePort())

if type(msg) = "roSpringboardScreenEvent" then
if msg.isScreenClosed()
print "Screen closed"
exit while
else if msg.isRemoteKeyPressed()
print "Remote key pressed"
if msg.GetIndex() = remoteKeyLeft then
showIndex = getPrevShow(showList, showIndex)
if showIndex <> -1
refreshShowDetail(screen, showList, showIndex)
end if
else if msg.GetIndex() = remoteKeyRight
showIndex = getNextShow(showList, showIndex)
if showIndex <> -1
refreshShowDetail(screen, showList, showIndex)
end if
endif
else if msg.isButtonPressed()
print "ButtonPressed"
print "ButtonPressed"
if msg.GetIndex() = 1
PlayStart = RegRead(showList[showIndex].ContentId)
if PlayStart <> invalid then
showList[showIndex].PlayStart = PlayStart.ToInt()
endif
showVideoScreen(showList[showIndex])
refreshShowDetail(screen,showList,showIndex)
endif
if msg.GetIndex() = 2
showList[showIndex].PlayStart = 0
if Showlist[ShowIndex].streamformat=".gif" or Showlist[Showindex].StreamFormat="image" then
showImage(showlist[showindex])
else
showVideoScreen(showList[showIndex])
end if
refreshShowDetail(screen,showList,showIndex)
endif
if msg.GetIndex() = 3
endif
print "Button pressed: "; msg.GetIndex(); " " msg.GetData()
end if
else
print "Unexpected message class: "; type(msg)
end if
end while

return showIndex

End Function



Now, here is the entire xml file through which I'm trying to display this remote gif. It is formatted the exact way all of the others which link to mp4 video feeds are formatted. Per your instructions, I changed the <contentType> tag to image and the <streamFormat> tag to .gif

If you can see what I'm doing wrong from what I've provided here, please let me know.

Many thanks, Joel!

XML CODE:


<feed>

<!-- resultLength indicates the total number of results for this feed --><resultLength>1</resultLength><!-- endIndix indicates the number of results for this *paged* section of the feed --><endIndex>1</endIndex>

<item sdImg="http://www.spc.noaa.gov/products/outlook/day1probotlk_1200_torn.gif" hdImg="http://www.spc.noaa.gov/products/outlook/day1probotlk_1200_torn.gif">
<title>24 Hour Tornado Outlook</title>

<contentType>image</contentType>
<contentQuality>SD</contentQuality>

<media>
<streamFormat>.gif</streamFormat>
<streamQuality>SD</streamQuality>
<streamBitrate>1500</streamBitrate>
<streamUrl>http://www.spc.noaa.gov/products/outlook/day1probotlk_1200_torn.gif</streamUrl>
</media>

<synopsis>The 24 Hour Tornado Outlook from the National Weather Service.</synopsis>

<genres>Weather</genres><runtime>100</runtime></item>

</feed>

0 Kudos
RokuMarkn
Visitor

Re: Need to Modify SDK Videoplayer to Allow Display of Image

If you're seeing the "retrieving" screen, then you must be calling showVideoScreen rather than showImage. The image display functions don't display a retrieving message. Either that, or your showImage function is invoking the video screen. I would add some print statements to trace the flow of execution and the variables of interest.

--Mark
0 Kudos
RokuJoel
Binge Watcher

Re: Need to Modify SDK Videoplayer to Allow Display of Image

Two things:

if Showlist[ShowIndex].streamformat=".gif" or Showlist[Showindex].StreamFormat="image" then


should be

if Showlist[ShowIndex].streamformat=".gif" or Showlist[Showindex].contentType="image" then


My bad.

Second, the <streamformat> tag in your xml is inside the media tag, for the syntax above to work, you would need to have a streamformat tag and some code to parse it outside the media tag. I suggest you just use the ContentType tag

if Showlist[Showindex].contentType="image" then


You will also need to handle the same in the case where button 1 is pressed

- Joel
0 Kudos
marsradio
Visitor

Re: Need to Modify SDK Videoplayer to Allow Display of Image

@ Mark:

Thank you for your input. However, I wish I was able to figure out how to implement your suggestion. Sadly, my experience with this type of code is very limited so far, but I'm happy that I am learning a lot as I push through these challenges.

@ Joel:

I thought I tried to implement the few changes you suggested. Unfortunately, I'm still getting the same results I reported last night.

Here's the section of code as it stands now:




'***************************************************************
'** The show detail screen (springboard) is where the user sees
'** the details for a show and is allowed to select a show to
'** begin playback. This is the main event loop for that screen
'** and where we spend our time waiting until the user presses a
'** button and then we decide how best to handle the event.
'***************************************************************
Function showDetailScreen(screen As Object, showList As Object, showIndex as Integer) As Integer

if validateParam(screen, "roSpringboardScreen", "showDetailScreen") = false return -1
if validateParam(showList, "roArray", "showDetailScreen") = false return -1

refreshShowDetail(screen, showList, showIndex)

'remote key id's for left/right navigation
remoteKeyLeft = 4
remoteKeyRight = 5

while true
msg = wait(0, screen.GetMessagePort())

if type(msg) = "roSpringboardScreenEvent" then
if msg.isScreenClosed()
print "Screen closed"
exit while
else if msg.isRemoteKeyPressed()
print "Remote key pressed"
if msg.GetIndex() = remoteKeyLeft then
showIndex = getPrevShow(showList, showIndex)
if showIndex <> -1
refreshShowDetail(screen, showList, showIndex)
end if
else if msg.GetIndex() = remoteKeyRight
showIndex = getNextShow(showList, showIndex)
if showIndex <> -1
refreshShowDetail(screen, showList, showIndex)
end if
endif
else if msg.isButtonPressed()
print "ButtonPressed"
print "ButtonPressed"
if msg.GetIndex() = 1
PlayStart = RegRead(showList[showIndex].ContentId)
if PlayStart <> invalid then
showList[showIndex].PlayStart = PlayStart.ToInt()
endif
if Showlist[showIndex].contentType="image" then
showImage(showList[showIndex])
else
showVideoScreen(showList[showIndex])
end if
refreshShowDetail(screen,showList,showIndex)
endif
if msg.GetIndex() = 2
showList[showIndex].PlayStart = 0
if showList[showIndex].contentType="image" then
showImage(showList[showIndex])
else
showVideoScreen(showList[showIndex])
end if
refreshShowDetail(screen,showList,showIndex)
endif
if msg.GetIndex() = 3
endif
print "Button pressed: "; msg.GetIndex(); " " msg.GetData()
end if
else
print "Unexpected message class: "; type(msg)
end if
end while

return showIndex

End Function



And here is the XML file:




<feed>




<!-- resultLength indicates the total number of results for this feed --><resultLength>1</resultLength><!-- endIndix indicates the number of results for this *paged* section of the feed --><endIndex>1</endIndex>



<item sdImg="http://www.spc.noaa.gov/products/outlook/day1probotlk_1200_torn.gif" hdImg="http://www.spc.noaa.gov/products/outlook/day1probotlk_1200_torn.gif">
<title>24 Hour Tornado Outlook</title>

<contentType>image</contentType>
<contentQuality>SD</contentQuality>

<media>

<streamQuality>SD</streamQuality>
<streamBitrate>1500</streamBitrate>
<streamUrl>http://www.spc.noaa.gov/products/outlook/day1probotlk_1200_torn.gif</streamUrl>
</media>

<synopsis>The 24 Hour Tornado Outlook from the National Weather Service.</synopsis>

<genres>Weather</genres><runtime>100</runtime></item>





</feed>





As you suggested, I took out <streamFormat> and just left <contentType>.

Then, I shortened:

if Showlist[ShowIndex].streamformat=".gif" or Showlist[Showindex].contentType="image" then


To this:

if Showlist[Showindex].contentType="image" then



But, still, it's just not opening the image. It still does the "retrieve" for a split second and then back.

Any help is greatly appreciated. And, if this type of function is just not meant to coexist within a video app, then that's fine too. This channel will be video driven. This is just an extra "perk" that I'd like to have in there.
Thanks again for any advice that could assist me in accomplishing this.
0 Kudos
belltown
Roku Guru

Re: Need to Modify SDK Videoplayer to Allow Display of Image

In appDetailScreen.brs, the line:

if Showlist[showIndex].contentType="image" then


will never evaluate to true (i.e. you will never see that contentType equals "image"), because of a bug in showFeed.brs. The problem is that the contentType is read from the xml file, then subsequently set to "episode", overwriting the value read from the xml file.

The solution is to move the following lines in showFeed.brs to immediately after the line that says: item = init_show_feed_item()


'Set Default screen values for items not in feed
item.HDBranded = false
item.IsHD = false
item.StarRating = "90"
item.ContentType = "episode"


And, if you haven't already done so, you'll have to write a 'showImage' function, e.g:


Function showImage (image As Object)
ss = CreateObject ("roSlideShow")
port = CreateObject ("roMessagePort")
ss.SetMessagePort (port)
ss.AddContent ({Url: image.SDPosterUrl})
ss.SetUnderscan (3)
ss.Show ()
While True
msg = Wait (0, port)
If Type (msg) = "roSlideShowEvent"
If msg.IsScreenClosed ()
ss.Close ()
Exit While
EndIf
EndIf
End While
End Function
0 Kudos
marsradio
Visitor

Re: Need to Modify SDK Videoplayer to Allow Display of Image

Thank you very much, belltown!!!
I followed everything you said to do, and I am now able to press "Play" and it now does open the image!

Unfortunately, there is a bit of a "glitch" happening. The problem only happens when I try to open an image that is a .gif. What it does is it takes the upper left corner of the gif and places it at the center of the screen. The result is that image then extends down and to the right of this center spot and then a vast amount of the image ends up going off screen. After playing with ss.setunderscan and anything else I could think of in the code, I decided to try a different image at a different URL. As luck would have it, the first image I tried happened to be a jpeg, and it displayed perfectly on the screen. After a few trials, I was able to narrow this issue down to the image being a gif as being the cause.

I took a couple of photos of my TV just to illustrate this:

This is the photo of the TV screen with the channel under construction displaying an image as a jpeg
https://www.dropbox.com/s/3b3xspsldyxfcjs/jpeg.jpg

And this is what a gif does. (It's dark and hard to see the outline of the TV, but use the blue dot as a reference and note that both photos are from the same position and both images are the same size)
http://www.dropbox.com/s/gnq7u1lpnobl53s/gif.jpg

I've searched this forum and online for possible solutions, and I'm coming up blank.

Unfortunately, in this case, I'm at the mercy of the National Weather Service in that I can't just tell the channel to show an jpeg. Since the particular map I want to display is published by the NWS in gif format only, I need this to work with the gif format.

I'm not sure if I need to put something within the XML code to tell the gif to center.

belltown, Joel and Mark, I really appreciate all of your help on getting me this far. If there's a way I can fix this small issue, then I'll basically be ready to finish the coding portion of this channel and then focus on getting the video content ready.
Thank you all again!
0 Kudos
RokuJoel
Binge Watcher

Re: Need to Modify SDK Videoplayer to Allow Display of Image

can you dropbox me (via private message) a copy of the channel you are developing so we can investigate? Sounds to me like it could be a bug, and I would like to verify it.

Meanwhile, you should be able to tell the filetype using instr() and perhaps adjust the x/y coordinates to handle the odd display issue. If you are going to send us the project however, please send it before you try to fix the problem!

- Joel
0 Kudos
belltown
Roku Guru

Re: Need to Modify SDK Videoplayer to Allow Display of Image

It may be a bug in the way roSlideShow handles gif images, although on my Roku 2 (4.9/5060) it displays correctly.

You could try using an roImageCanvas instead of an roSlideShow. Try this showImage function instead:


Function showImage (image As Object)

' Get the TV's display size
di = CreateObject ("roDeviceInfo")
displaySize = di.GetDisplaySize ()
displayMode = di.GetDisplayMode ()

' Make use of the 'Action Safe Zone'
' HD->1150x646 starting at (64, 35)
' SD->648x432, starting at (36, 24)
If displayMode = "720p" ' 720p (HD)
displayH% = 646
displayW% = 1150
displayX% = 64
displayY% = 35
Else If displayMode = "480i" ' 480p (SD)
displayH% = 432
displayW% = 648
displayX% = 36
displayY% = 24
Else ' Unknown display type
displayH% = displaySize.H * 0.9
displayW% = displaySize.W * 0.9
displayX% = (displaySize.W - displayW%) / 2
displayY% = (displaySize.H - displayH%) / 2
EndIf

port = CreateObject ("roMessagePort")
ic = CreateObject ("roImageCanvas")
ic.SetMessagePort (port)

' Black opaque background
ic.SetLayer (0, {Color: "#FF000000", CompositionMode: "Source"})

' Fill the display area with the image
' Display the title just below the top center of the image
ic.SetLayer (1, [{url: image.SDPosterUrl,
TargetRect: {x: displayX%, y: displayY%, w: displayW%, h: displayH%}},
{Text: image.Title,
TextAttrs: {Color: "#AA777777", Font: "Medium", HAlign: "Center", VAlign: "Top"},
TargetRect: {x: displayX%, y: displayY% + 10, w: displayW%, h: displayH% - 10}
}])
ic.Show ()

While True
msg = Wait (0, port)
If Type (msg) = "roImageCanvasEvent"
If msg.IsScreenClosed ()
ic.Close ()
Exit While
Else If msg.IsRemoteKeyPressed ()
key = msg.GetIndex ()
' Exit regardless of which key is pressed
ic.Close ()
Exit While
EndIf
EndIf
End While
End Function
0 Kudos