Roku Developer Program

Developers and content creators—a complete solution for growing an audience directly.
cancel
Showing results for 
Search instead for 
Did you mean: 
sonnykr
Level 7

Infinite wait on roUrlTransfer object

Hi I am new to Roku development using brightscript. Please excuse me if im asking something stupid.

I am stuck in loading some images I got through roUrlTransfer object. This is what I am doing:

1. Create seperate roUrlTransfer objects for each images (since I need it async) - call it 'http'
2. Saving the resul to tmp using AsyncGetToFile(temp_path)
3. Pushing each http to imageTransfers array
4. Finally, take each item from imageTransfers array and drawing bitmap out of it

I have a grid control which has 4 rows and 2 col (so initially 8 images will load). After that on each button_down_pressed event, i'm loading next row (2 items). But when I do

for each http in m.imageTransfers
msg = wait(0, http.GetPort())
if (type(msg) = "roUrlEvent")
...........
...........
end if
end for

the code stops working at msg=wait(0, http.GetPort()). Its like an infinite wait. What am I doing wrong here? The initial 8 items in the grid is loading fine, and passing this code successfully. Please help :roll:
0 Kudos
24 Replies
sonnykr
Level 7

Re: Infinite wait on roUrlTransfer object

When I printed type of messages, most of them seems to be INVALID instead of roUrlEvent

But when i press down button again, im getting all 4 (2 from each row) roUrlEvent msgs.

Cant figure out why!
0 Kudos
NewManLiving
Level 7

Re: Infinite wait on roUrlTransfer object

For what you want to do you are probably better
Off using rotexturemanager And do not use wait
But create a separate port for just your textures
and use port.getmessage In any case your async
Objects must stay on scope until it completes
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
sonnykr
Level 7

Re: Infinite wait on roUrlTransfer object

Does texture manager supports legacy devices. I'm targeting roku2 as well. If it does, how will be the performance
0 Kudos
NewManLiving
Level 7

Re: Infinite wait on roUrlTransfer object

I use it with the 2xd. Essentially does the same thing
As urltransfer. But it also returns an in memory bitmap
Reference to you. The transfer object writes to disk so
You have to load your bitmap from tmp. If I preload something
For use later on I use the transfer object. For loading directly
Into a grid I prefer the texturemanager. Performance wise they area out the same
With retrieving. Did notice along with someone else recently that
The transfer object my give slightly better download times on a single larger
Bitmap than the texturemanager. But for more than one on a component
Such as a grid during realtime scrolling definitely the manager
With the 2xd box i have to balance size, and number with performance
The textures arrive quick enough. But are disk and processor
Intensive. To see what I mean just start scrolling your home screens
Ok the 2 boxes. You will notice resistance and uneven movement
As the textures arrive during scrolling. If you open up a telnet
You can see that the manager or some equivalent is being used.

In the 4200 boxes it just absolutely impressive. No studdering at all
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
sonnykr
Level 7

Re: Infinite wait on roUrlTransfer object

I tried roTextureManager. I have to load 20-25 or so images initially. It starts well, but after a while, most of the roTextureRequestEvent states are returining 4, which means Failed.

Is this a limitation of the texturemanager? Is there any work around?
0 Kudos
NewManLiving
Level 7

Re: Infinite wait on roUrlTransfer object

20 -25 is well within reason for standard
Grid size textures. A failure code can mean
That your roTextureRequest may have gone
Out of scope. If you are requesting textures
asynchronously and not polling for returns
Within the same function , you need to
Make sure your texture requests are global to
Either an object or your application
If they go out of scope such as when creating them
Locally In a function and then exiting the
Function to listen somewhere else, they
Are removed from the function stack that
Created them and
Destroyed. This would generate a return of
4. Without seeing your code it is difficult
To determine where your problem is
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
sonnykr
Level 7

Re: Infinite wait on roUrlTransfer object

This is what im doing with textureManager

in getBitmap function
1. I am calling a function called sendRequest, which creates a roTextureReques object with the passed in url and send a RequestTexture request. As return, I am passing request object
2. The request object is pushed to an imageTransfers array
3. So, now I have imageTransfers array with all the roTextureRequest objects.
4. then i loop through each items in the imagetransfers and calling a listening function. (here im using the same message port created at the time of request) and wait for the roTextureRequestEvent
5. for first 12 items state =3, after that state=4.

The first 12 items remains in the scope. and I cant find any reason for the remaining items go out of the scope.
0 Kudos
NewManLiving
Level 7

Re: Infinite wait on roUrlTransfer object

Something's to remember


Create,push, send, receive, pop, destroy
Totally Recreate again when needed
Do not reuse a completed object
To re-request if removed from the manager
As a matter of fact it is better to save the
Bitmap than to save the request
Push onto an associative array list
With the objects. Id so you can find it
And pop it off the queue when returned
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
Level 7

Re: Infinite wait on roUrlTransfer object

' This is an example of one way to manage a texture cache.  It is a very stripped down version
' of one that I use. This version does not include the realtime populating of my grids that I have
' put out here. I do have that if anyone is interested. This version just includes the polling function
' that is used primarily for pseudo-async preloading. But it demonstrates what is essentially needed to
' do this as well as an indicator of how fast the manager can be. I have set up a test directory on my
' own content site. The image files are small but I have acceptable results with images as large
' as 10 - 18 kb. So for standard grid-sized poster images this should be very reasonable

' This was extracted from my channel and put together very quickly, and most of the error checking was removed.
' But I believe I have included enough code to demonstrate a particular method that I use. However some anomalies
' may exist, which if discovered I will be happy to fix

' My own experience with the manager is only about 4 months but I have learned a lot and have come to really appreciate
' the texture manager. It works very well with my grids which I have redesigned to be fully integrated with
' my managers. If anyone can contribute and make it better we can all benefit

' Add this function to test the code
Function TextureTest() As Void

' This directory is temporary and will be available for testing
l_url = "http://s3.amazonaws.com/NMLiving/texture_test/"

' I have created 25 simple textures texture1.jpg to texture25.jpg
l_textureList = CreateObject( "roArray", 25, False )

' Create the url, the textureobject and push onto the texture list
for l_i = 1 to 25
l_turl = l_url + "texture" + l_i.ToStr() + ".jpg"
l_textureList.Push( NewTextureObject( l_turl ) )
end for

' Create an instance of the texturemanager and reset (optional)
' However you should know when to reset
l_textureManager = NewTextureManager()
l_textureManager.Reset()

print "REQUESTING"
print "============================================================="

' For each texture in the list request it from the manager
for each l_texture in l_textureList
l_textureManager.RequestTexture( l_texture )
end for

print ""
print "RECEIVING"
print "============================================================"

' Ask the manager to poll for the textures
l_textureManager.PollTextures()

' Verify that we have a valid bitmap for each texture
for each l_texture in l_textureList
print type( l_texture.Bitmap )
end for


End Function


' Creates a texture cache object which contains the returned bitmap, the textureRequest
' a Url and a resend count
Function NewTextureObject( a_url As String ) As Object
return { Bitmap: Invalid, TRequest: Invalid, TUrl: a_url, ResendCount: 0 }
End Function

' Very stripped down version of my own manager. This version offers only polling
' you would not use polling to populate a grid during realtime scrolling on for preloading
Function NewTextureManager() As Object

tl = CreateObject( "roAssociativeArray" )

tl.TManager = CreateObject( "roTextureManager" )
tl.TMPort = CreateObject( "roMessagePort" )
tl.TManager.SetMessagePort( tl.TMPort )

tl.RequestList = CreateObject( "roAssociativeArray" )

tl.SendCount = 0
tl.ReceiveCount = 0

tl.STATE_READY = 3
tl.STATE_FAILED = 4

tl.AddItem = tl_add_item
tl.RemoveItem = tl_remove_item
tl.Reset = tl_reset

tl.RequestTexture = tl_request_texture
tl.ReceiveTexture = tl_receive_texture
tl.PollTextures = tl_poll_textures

return tl

End Function

' Adds an item to the list and increments the list count. The key is the textures id
Function tl_add_item( a_ID As Integer, a_value As DYNAMIC ) As Void
m.RequestList.AddReplace( a_ID.ToStr(), a_value )
m.ListCount = m.ListCount + 1
End Function

' Removes an item from the list, decrements the count
Function tl_remove_item( a_ID As Integer ) As Object

l_key = a_ID.ToStr()
l_value = m.RequestList.LookUp( l_key )

if l_value = Invalid then return Invalid

m.RequestList.Delete( l_key )
m.ListCount = m.ListCount - 1

return l_value

End Function

' Resets the list by emptying the manager and clearing
' out any items remaing, resets all values
Function tl_reset() As Void

m.TManager.CleanUp()
m.RequestList.Clear()

m.ListCount = 0
m.SendCount = 0
m.ReceiveCount = 0

End Function

' Each texture object is sent to this function, which creates the texturerequest and sends it
' It also increments the sendcount
Function tl_request_texture( a_texture As Object ) As Integer

' Create the texture request and assign to the items TRequest member
a_texture.TRequest = CreateObject( "roTextureRequest", a_texture.TUrl )
' Add the item into the async list
m.AddItem( a_texture.TRequest.GetID(), a_texture )
' Asynchronously request the texture
m.TManager.RequestTexture( a_texture.TRequest )
' Increment the send count
m.SendCount = m.SendCount + 1
' Return the current total sent

print m.SendCount" "; a_texture.TUrl

return m.SendCount

End Function

' This function receives the texture and processes it, if successful it increments the receive count
Function tl_receive_texture( a_tmsg as DYNAMIC ) As Boolean

' Get the returned state
l_state = a_tmsg.GetState()

' If return state is Ready, Failed, or Cancelled - either case, remove it from the list
if l_state = m.STATE_READY or l_state >= m.STATE_FAILED

' Removed the received texture from the asynclist. But do not increment the received count
l_texture = m.RemoveItem( a_tmsg.GetID() )
' There SHOULD ALWAYS be one in there if used properly
if l_texture = Invalid then return False

' Assign the bitmap to the texture object
l_texture.Bitmap = a_tmsg.GetBitmap()
' A state of 3 with a valid bitmap is complete
if l_state = m.STATE_READY and l_texture.Bitmap <> Invalid

' Increment the receive count and get rid of the texture request
m.ReceiveCount = m.ReceiveCount + 1
l_texture.TRequest = Invalid

print m.ReceiveCount;" "; l_texture.TUrl

return True

' If a failure occurs you can try to resend it, but usually it is a more serious problem which
' can put you in an endless loop if you dont put a limit on it. I handle it differently but for this
' example it is resent a limited number of times
else if l_state = m.STATE_FAILED and l_texture.ResendCount <= 5

' Optional
l_texture.TRequest = Invalid

' Rebuild and resend
l_texture.ResendCount = l_texture.ResendCount + 1
l_texture.TRequest = CreateObject( "roTextureRequest", l_texture.TUrl )
m.AddItem( l_texture.TRequest.GetID(), l_texture )
m.TManager.RequestTexture( l_texture.TRequest )

' Set the global error
l_str = "Resend Texture Request. State : " + l_state.ToStr()
l_str = l_str + " Bitmap: " + type( a_tmsg.GetBitmap() ) + " ResendCount: " + l_texture.ResendCount.ToStr()
l_str = l_str + " URI: " + l_texture.TUrl

print l_str

return False

' This can occur with the dylnamic allocation when the textures are not removed from the queue fast enough
' or the resend count has expired, cancelled etc...
else

l_str = "Unhandled Message. State: " + l_state.ToStr() + " Bitmap: " + type( a_tmsg.GetBitmap() )
l_str = l_str + " URI: " + l_texture.TUrl

print l_str

return False

end if

end if

' Otherwise it is some other code such as downloading if it even exists. Never seen it
return True

End Function

' This function simply polls for all the textures to return. To populate a grid during realtime scrolling
' a little modification is needed to the grids I have put out here and this manager I have this available
' in my own library
Function tl_poll_textures() As Boolean

' Just a timeout here you may want to add something like I do to allow the user to abort under
' certain conditions. That was removed for simplicity
l_timer = CreateObject( "roTimeSpan" )
l_timeOut = 45
l_kp_BK = 0

l_success = False

while( True )

' Monitor the managers port
l_TMsg = m.TMPort.GetMessage()

if l_TMsg <> Invalid

' Process the received texture
m.ReceiveTexture( l_TMsg )

' When receivecount is = to send count then we have them all
' you have to be careful here any abnormality or failure in the chain can effect this
' I do it differently with more error checking but this is only a demonstration
l_success = ( m.ReceiveCount = m.SendCount )
if l_success then exit while

' Reset the timer
l_timer.Mark()

end if

' Should always have a timeout as anything can occur
if ( l_timer.TotalSeconds() >= l_timeout )

print "TextureRequest Timed Out"
exit while

end if

end while

return l_success


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