Forum Discussion

marsradio's avatar
marsradio
Visitor
13 years ago

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.

9 Replies

  • 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
  • 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>

  • 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
  • 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
  • @ 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.
  • 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
  • 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!
  • 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
  • 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