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: 
belltown
Roku Guru

How to play audio content in SDK videoplayer

For those of you who have been asking about how to modify the videoplayer example SDK app to play audio, here's a solution:

1. In the XML file for your feed, set <streamFormat> to mp3 or wma, as appropriate. The <streamFormat> tag should be subordinate to the <item> tag for your content, the <item> tag being under the <feed> tag. You can mix audio and video content in the same feed as long as the <streamFormat> tags for each are set appropriately.

2. Replace appDetailScreen.brs with:


'*******************************************************************
'** Video Player Example Application - Detail Screen
'** November 2009
'** Copyright(c) 2009 Roku Inc. All Rights Reserved.
'*******************************************************************
'
' Modified by belltown to support mp3 and wma audio streams.
'
' All you need to do to handle an audio stream is to replace
' appDetailScreen.brs in the videoplayer SDK example with this file,
' then in the XML file set <StreamFormat> for your audio item
' to mp3 or wma.
'*******************************************************************

Function VIDEO_BUTTON_PLAY() As Integer : Return 1 : End Function
Function VIDEO_BUTTON_RESUME() As Integer : Return 2 : End Function
Function AUDIO_BUTTON_PLAY() As Integer : Return 3 : End Function
Function AUDIO_BUTTON_STOP() As Integer : Return 4 : End Function
Function AUDIO_BUTTON_PAUSE() As Integer : Return 5 : End Function
Function AUDIO_BUTTON_RESUME() As Integer : Return 6 : End Function

Function preShowDetailScreen(breadA=invalid, breadB=invalid) As Object
port=CreateObject("roMessagePort")
screen = CreateObject("roSpringboardScreen")
' The description style is now set in refreshShowDetail once it is known whether the content is audio or video
'screen.SetDescriptionStyle("video")
screen.SetMessagePort(port)
if breadA<>invalid and breadB<>invalid then
screen.SetBreadcrumbText(breadA, breadB)
end if

return screen
End Function

'***************************************************************
'** 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

' Set up the audio player
audio = CreateObject("roAudioPlayer")
audio.SetMessagePort(screen.GetMessagePort())
audio.SetLoop(0)
audio.SetNext(0)

' Display the Springboard screen
show = showList[showIndex]
refreshShowDetail(screen, audio, showList, showIndex)

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

isPlaying = false ' Set to true when the user presses the Play button on the audio Springboard screen
isPaused = false ' Set to true when the user presses the Pause button on the audio Springboard screen
isBuffering = true ' Set to true when audio is buffering or waiting for play to start

while true
' Use a timeout on the wait loop to allow for updating of the audio progress bar
' The smaller the timeout value, the smoother the updates to the progress bar
msg = wait(100, screen.GetMessagePort())

if msg = invalid ' Wait Timeout - update the audio progress bar
if isAudioStream(show) and isPlaying and not isBuffering
runtimeElapsed = setProgressBar(screen, show)
' roAudioPlayer has a bug where if the audio player is paused immediately before the content finishes playing
' (within half a second or so), then the events that signify the end of the content do not fire.
' The 'if' statement below is a workaround for that bug. Assuming the runtime has been set correctly for
' the audio content item, if the audio content has reached its runtime then the audio player is stopped.
' Uncomment the 'if' statement below if you care enough to implement this workaround ...
REM if runtimeElapsed
REM print "Terminating play after runtime has elapsed"
REM isPlaying = false
REM isPaused = false
REM isBuffering = true
REM audio.Stop()
REM zeroProgressBar(screen, show)
REM screen.ClearButtons()
REM screen.AddButton(AUDIO_BUTTON_PLAY(), "Play")
REM endif
endif
else if type(msg) = "roSpringboardScreenEvent"
if msg.isScreenClosed()
print "Screen closed"
exit while
else if msg.isRemoteKeyPressed()
key = msg.GetIndex()
print "Remote key pressed: "; key
if key = remoteKeyLeft ' Play the previous content item
isPlaying = false
isPaused = false
audio.Stop()
audio.ClearContent()
showIndex = getPrevShow(showList, showIndex)
if showIndex <> -1
refreshShowDetail(screen, audio, showList, showIndex)
show = showList[showIndex]
endif
else if key = remoteKeyRight ' Play the next content item
isPlaying = false
isPaused = false
audio.Stop()
audio.ClearContent()
showIndex = getNextShow(showList, showIndex)
if showIndex <> -1
refreshShowDetail(screen, audio, showList, showIndex)
show = showList[showIndex]
endif
endif
else if msg.isButtonPressed()
button = msg.GetIndex()
if button = VIDEO_BUTTON_RESUME()
PlayStart = RegRead(showList[showIndex].ContentId)
if PlayStart <> invalid
showList[showIndex].PlayStart = PlayStart.ToInt()
endif
showVideoScreen(showList[showIndex])
refreshShowDetail(screen, audio, showList, showIndex)
else if button = VIDEO_BUTTON_PLAY()
showList[showIndex].PlayStart = 0
showVideoScreen(showList[showIndex])
refreshShowDetail(screen, audio, showList, showIndex)
else if button = AUDIO_BUTTON_PLAY()
isPlaying = true
isPaused = false
audio.Play()
show.CurrentPosition = 0
zeroProgressBar(screen, show)
screen.ClearButtons()
screen.AddButton(AUDIO_BUTTON_PAUSE(), "Pause")
screen.AddButton(AUDIO_BUTTON_STOP(), "Stop")
else if button = AUDIO_BUTTON_STOP()
isPlaying = false
isPaused = false
isBuffering = true
audio.Stop()
show.CurrentPosition = 0
zeroProgressBar(screen, show)
screen.ClearButtons()
screen.AddButton(AUDIO_BUTTON_PLAY(), "Play")
else if button = AUDIO_BUTTON_PAUSE()
isPlaying = false
isPaused = true
audio.Pause()
screen.ClearButtons()
screen.AddButton(AUDIO_BUTTON_RESUME(), "Resume")
screen.AddButton(AUDIO_BUTTON_STOP(), "Stop")
else if button = AUDIO_BUTTON_RESUME()
isPlaying = true
isPaused = false
audio.Resume()
screen.ClearButtons()
screen.AddButton(AUDIO_BUTTON_PAUSE(), "Pause")
screen.AddButton(AUDIO_BUTTON_STOP(), "Stop")
else
print "Invalid button pressed"
endif
print "Button pressed:"; button " " msg.GetData()
endif
else if type(msg) = "roAudioPlayerEvent"
if msg.IsRequestSucceeded() or msg.IsRequestFailed() or msg.IsPartialResult() or msg.IsFullResult()
if msg.IsRequestSucceeded() then print "roAudioPlayerEvent: IsRequestSucceeded"
if msg.IsRequestFailed() then print "roAudioPlayerEvent: IsRequestFailed: "; msg.GetMessage ()
if msg.IsPartialResult() then print "roAudioPlayerEvent: IsPartialResult"
if msg.IsFullResult() then print "roAudioPlayerEvent: IsFullResult"
isPlaying = false
isPaused = false
isBuffering = true
audio.Stop()
zeroProgressBar(screen, show)
screen.ClearButtons()
screen.AddButton(AUDIO_BUTTON_PLAY(), "Play")
else if msg.IsPaused()
print "roAudioPlayerEvent: IsPaused"
if not isBuffering ' If we're buffering, the current position has already been stored
show.CurrentPosition = show.CurrentPosition + show.PlaybackTimer.TotalMilliseconds()
endif
else if msg.IsResumed()
print "roAudioPlayerEvent: IsResumed"
show.PlaybackTimer.Mark()
else if msg.IsStatusMessage()
message = msg.GetMessage()
print "roAudioPlayerEvent: IsStatusMessage: "; message
if message = "startup progress"
if not isBuffering ' Audio player has started buffering - reset playback timer
show.CurrentPosition = show.CurrentPosition + show.PlaybackTimer.TotalMilliseconds()
isBuffering = true
endif
else if message = "start of play"
show.PlaybackTimer.Mark()
isBuffering = false
endif
else if msg.IsListItemSelected()
print "roAudioPlayerEvent: IsListItemSelected"
else if msg.IsStreamStarted()
print "roAudioPlayerEvent: IsStreamStarted"
else
print "roAudioPlayerEvent: Unknown Event:"; msg.GetType()
endif
else
print "Unexpected message class: "; type(msg)
endif
end while

return showIndex

End Function

'**************************************************************
'** Refresh the contents of the show detail screen. This may be
'** required on initial entry to the screen or as the user moves
'** left/right on the springboard. When the user is on the
'** springboard, we generally let them press left/right arrow keys
'** to navigate to the previous/next show in a circular manner.
'** When leaving the screen, the should be positioned on the
'** corresponding item in the poster screen matching the current show
'**************************************************************
Function refreshShowDetail(screen As Object, audio As Object, showList As Object, showIndex as Integer) As Integer

if validateParam(screen, "roSpringboardScreen", "refreshShowDetail") = false return -1
if validateParam(audio, "roAudioPlayer", "refreshShowDetail") = false return -1
if validateParam(showList, "roArray", "refreshShowDetail") = false return -1

show = showList[showIndex]
show.PlaybackTimer = CreateObject("roTimespan")

'Uncomment this statement to dump the details for each show
'PrintAA(show)

if isAudioStream(show)
if show.StreamUrls.Count() > 0
show.Url = show.StreamUrls[0]
else
print "No audio stream found"
endif
audio.AddContent(show)
show.CurrentPosition = 0
if show.Runtime <> "" and show.Runtime.ToInt() > 0
show.ContentType = "audio" ' ContentType controls the size of the artwork and whether a progress bar is allowed
screen.SetProgressIndicatorEnabled(true)
zeroProgressBar(screen, show)
else
screen.SetProgressIndicatorEnabled(false)
endif
'
' You can set the springboard screen's description style depending on which meta-data fields you want displayed.
'
' "audio": All tags on audio screen are substituted with Content Meta-Data (Album and Artist).
' "movie": All tags on the video screen are substituted with Content Meta-Data
' "video": All tags except <Directors> and <Ratings> on the video screen are replaced with Content Meta-Data.
' "generic": Only the <Title> and <Description> tags on the video screen are replaced with Content Meta-Data.
'
screen.SetDescriptionStyle("movie")
screen.ClearButtons()
screen.AddButton(AUDIO_BUTTON_PLAY(), "Play")
screen.SetContent(show)
screen.Show()
else
' Changed the description type from "video" in the original Roku SDK videoplayer example to "movie",
' so that more content Meta-Data items are displayed on the Springboard screen.
screen.SetDescriptionStyle("movie")
screen.ClearButtons()
if regRead(show.contentid) <> invalid and regRead(show.contentid).ToInt() >= 30
screen.AddButton(VIDEO_BUTTON_RESUME(), "Resume playing")
screen.AddButton(VIDEO_BUTTON_PLAY(), "Play from beginning")
else
screen.addbutton(VIDEO_BUTTON_PLAY(),"Play")
endif
screen.SetContent(show)
screen.Show()
endif

End Function

'********************************************************
'** Get the next item in the list and handle the wrap
'** around case to implement a circular list for left/right
'** navigation on the springboard screen
'********************************************************
Function getNextShow(showList As Object, showIndex As Integer) As Integer
if validateParam(showList, "roArray", "getNextShow") = false return -1

nextIndex = showIndex + 1
if nextIndex >= showList.Count() or nextIndex < 0
nextIndex = 0
endif

show = showList[nextIndex]
if validateParam(show, "roAssociativeArray", "getNextShow") = false return -1

return nextIndex
End Function

'********************************************************
'** Get the previous item in the list and handle the wrap
'** around case to implement a circular list for left/right
'** navigation on the springboard screen
'********************************************************
Function getPrevShow(showList As Object, showIndex As Integer) As Integer
if validateParam(showList, "roArray", "getPrevShow") = false return -1

prevIndex = showIndex - 1
if prevIndex < 0 or prevIndex >= showList.Count()
if showList.Count() > 0 then
prevIndex = showList.Count() - 1
else
return -1
endif
endif

show = showList[prevIndex]
if validateParam(show, "roAssociativeArray", "getPrevShow") = false return -1

return prevIndex
End Function

'********************************************************************
'** Return true if the content's StreamFormat denotes an audio stream
'********************************************************************
Function isAudioStream(show As Object) As Boolean
return LCase(show.StreamFormat) = "mp3" or LCase(show.StreamFormat) = "wma"
End Function

'*******************************
'** Reset the audio progress bar
'*******************************
Function zeroProgressBar(screen As Object, show As Object) As Void
if show.Runtime <> "" and show.Runtime.ToInt() > 0
screen.SetProgressIndicator(0, show.Runtime.ToInt())
endif
End Function

'*************************************************
'** Update the audio progress bar
'** If the show's runtime has elapsed, return true
'*************************************************
Function setProgressBar(screen As Object, show As Object) As Boolean
if show.Runtime <> "" and show.Runtime.ToInt() > 0
' Update the progress indicator
screen.SetProgressIndicator(show.CurrentPosition + show.PlaybackTimer.TotalMilliseconds(), show.Runtime.ToInt() * 1000)
' Workaround for roAudioplayer bug where no event is fired when the end of the content is reached if the player was paused immediately before the end
return (show.CurrentPosition + show.PlaybackTimer.TotalMilliseconds ()) > (show.Runtime.ToInt () * 1000)
endif
return false
End Function


This will display a springboard screen for the audio content containing Play/Pause/Resume/Stop buttons. If the <runtime> tag is present and set to a non-zero value, then an audio player progress bar will also be displayed along the bottom edge of the artwork.
0 Kudos
12 REPLIES 12
bandal
Visitor

Re: How to play audio content in SDK videoplayer

I found this out by accident about a week ago. At least the answer is simple.
DA
0 Kudos
Gary1980Arb
Channel Surfer

Re: How to play audio content in SDK videoplayer

Bandal, you are Heaven Sent !!!

This is exactly what I needed for my Channel as well!!

Bless you, Bless You !!!

I believe you are the most helpful person in this forum!!
0 Kudos
bandal
Visitor

Re: How to play audio content in SDK videoplayer

You can also play Live Internet Streams by placing in the streamurl the actual link and Port with the slash or / at the end. Here is one to try. Set StreamFormat to mp3.
<streamUrl>http://67.228.150.184:9015/</streamUrl>

I was able to get it with a pc program called UrlGetter and play a Shoutcast Stream in VLC while UrlGetter is running and you can find the address and port number.
Credit to belltown.

Thanks,

DA
0 Kudos
destruk
Binge Watcher

Re: How to play audio content in SDK videoplayer

See, I don't understand that - the need for a 'ripper' program for Shoutcast?
That makes about as much sense as someone paying for a screenshot program because they can't be troubled to use printscreen and paste, lol.

All the currently broadcasting shoutcast servers are listed here: http://www.shoutcast.com/radio/List
You can search for whatever you want to listen to - when it shows up in the list, right click the name and "save link as" which saves a .PLS file to your hard drive.
Open it in notepad and there is the URL you need in plain text right there.
0 Kudos
bandal
Visitor

Re: How to play audio content in SDK videoplayer

Thanks, I knew there must be an easier way. Just never took the time to get this far as I needed it only 2 times. Thanks for the info looks way easier now.
DA
0 Kudos
agmark
Visitor

Re: How to play audio content in SDK videoplayer

"Gary1980Arb" wrote:
Bandal, you are Heaven Sent !!!

This is exactly what I needed for my Channel as well!!

Bless you, Bless You !!!

I believe you are the most helpful person in this forum!!


I believe you meant to thank belltown and I couldn't agree more. Belltown continues to be a great asset to this forum. My thanks as well!
0 Kudos
bandal
Visitor

Re: How to play audio content in SDK videoplayer

I agree.
0 Kudos
Gary1980Arb
Channel Surfer

Re: How to play audio content in SDK videoplayer

Thank you belltown !!
0 Kudos
RobSMS
Visitor

Re: How to play audio content in SDK videoplayer

I implemented this code, but I have one bug I just can't figure out when playing a shoutcast/icecast stream.

On my Roku 2XD it sometimes buffers for up to 2 minutes, then starts playing fine. Occasionally it starts after 2 or 3 seconds.

I thought it was the shoutcast stream or my wireless connection, but then I tried it on my Roku 3 in a room that is farther away from my router and it worked fine every time.

Any ideas?
Need Apps Templates? Content Management for OTT/IPTV? Check me out @ http://rovidx.com
0 Kudos