How to get instant updates to Roku?

I’m using the videoplayer example and I need Roku to update instantly when I change my xml files on the server. As it is now it takes hours for it to update or it updates sometimes when I repackage everything and send it to the channel as a new version.

Here is the code in categoryFeed.brs:

Function InitCategoryFeedConnection() As Object

    conn = CreateObject("roAssociativeArray")

    conn.UrlPrefix   = "http://scclib.com/demo/roku/xml"
    conn.UrlCategoryFeed = conn.UrlPrefix + "/categories.xml?ts=" + dt.AsSeconds().ToStr()

    conn.Timer = CreateObject("roTimespan")

    conn.LoadCategoryFeed    = load_category_feed
    conn.GetCategoryNames    = get_category_names

    print "created feed connection for " + conn.UrlCategoryFeed
    return conn

End Function

categories.xml

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
<categories>
	<category title="Awesomeness" description="Here it iskhj"
		sd_img="http://scclib.com/demo/roku/images/test_sd_poster.jpg"
		hd_img="http://scclib.com/demo/roku/images/test_hd_poster.jpg">
		<categoryLeaf title="Awesomeness" description="" feed="http://scclib.com/demo/roku/xml/xmlfeed.php"/>
	</category>
</categories>

xmlfeed.php

<?php
	echo file_get_contents('awesomeness.xml?ts=23423423');
?>

awesomeness.xml

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
<feed>
	<resultLength>2</resultLength>
	<endIndex>2</endIndex>
	<item sdImg="" hdImg="">
		<title>Awesomeness</title>
		<contentId>10001</contentId>
		<contentType>Talk</contentType>
		<contentQuality>SD</contentQuality>
		<media>
			<streamFormat>mp4</streamFormat>
			<streamQuality>SD</streamQuality>
			<streamBitrate>1500</streamBitrate>
			<streamUrl>http://vidego-http.multicastmedia.com/mm/flvmedia/2878/M/a/k/MakingTheMostofIt_wk1-865721.f4v?cid=2878&aid=865721&afid=1099746</streamUrl>
		</media>
		<synopsis>This is what's happening</synopsis>
		<genres>Crap</genres>
		<runtime>120</runtime>
	</item>
</feed>

Not sure why, but my xml feeds update immediately when I ftp the files to my servers. Even changing the categories.xml updates within seconds. No modifications to the .brs files in videoplayer. I update my feeds daily and see results now. I used to have a problem with images in the past, but do not see it now. I have the XS and micro memory card too. My feeds are MP4 and HLS and MP3 only. No .flv or .f4v is supported.

Did you add a cache buster parameter to your URL as was suggested in your other thread?

–Mark

I’d check the content caching and expiration settings on your web server, or try adding something like the following to your php:

<?php
header("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1
header("Expires: Sat, 26 Jul 1997 05:00:00 GMT"); // Date in the past
?>

I don’t quite know what a cachebuster url means, but I did add ?ts= with a timestamp. You can see it in the code I posted. Did I do it correctly?

The code in categoryFeed.brs looks mostly right. It should assure that each time the Roku goes to access categories.xml it requests a fresh copy from your server. But then in the categories.xml file, you point to a categoryLeaf feed:


 <categoryLeaf title="Awesomeness" description="" feed="http://scclib.com/demo/roku/xml/xmlfeed.php"/>

That feed should have a unique parameter (timestamp) appended to it, so that when the Roku looks for it, it doesn’t use cached data:


 <categoryLeaf title="Awesomeness" description="" feed="http://scclib.com/demo/roku/xml/xmlfeed.php?ts=20120223104501"/>

Your php script, xmlfeed.php, should only echo the file contents of awesomness.xml. Appending the timestamp in that function is unnecessary (and I’d be surprised if it worked at all):

<?php
   echo file_get_contents('awesomeness.xml');
?>

What I would do is dynamically generate the category.xml file so that it timestamps the feed links:
categories.php

<?php
// Send the headers
header('Content-type: text/xml');
header('Pragma: public');
header('Cache-control: private');
header('Expires: -1');

//Store the current time in seconds into variable $now:
$now = time();

echo '<?xml version="1.0" encoding="utf-8" standalone="yes"?>';
echo '<xml>';
echo ' <categories>';
echo '  <category title="Awesomeness" description="Here it iskhj"';
echo '      sd_img="http://scclib.com/demo/roku/images/test_sd_poster.jpg"';
echo '      hd_img="http://scclib.com/demo/roku/images/test_hd_poster.jpg">';

//Append a timestamp to the category feed:
echo '      <categoryLeaf title="Awesomeness" description="" feed="http://scclib.com/demo/roku/xml/xmlfeed.php?ts=' . $now . '"/>';

echo '   </category>';
echo ' </categories>';
echo '</xml>';
?>

So instead of pointing at category.xml in categoryFeed.brs, you point at categories.php (keeping the timestamp!! :disappointed_face:

conn.UrlCategoryFeed = conn.UrlPrefix + "/categories.php?ts=" + dt.AsSeconds().ToStr()

Awesomness.xml looks fine to me, but if the contents will change often, you’ll want to dynamically generate this too. I assume that’s why you have the xmlfeed.php script just echoing the file contents, as a placeholder until you are dynamically generating?

PHP has a lot of built-in xml functions, simply echoing everything is definitely not the way to go for production use (I used it only so it would be easier for you to see what’s going on). If you aren’t comfortable with xml yet, the language may initially be a little intimidating, but it’s really quite easy to work with. I recommend reading up on it and the php functions you can use to generate and manipulate it. XML in a Nutshell, or the XML Pocket reference, both published by O’Reilly might be good places to start with XML learning, and the php reference for SimpleXML might help for when you’re ready to generate it on the fly

I’m gonna mess around with what you gave me, so far it’s just giving me a black screen, but I probably missed something.

Also, yes, my goal is to use that as a placeholder. I’d all the xml to be dynamic, so it’s good that I’m doing that for categories. The goal I have now is just to get the page running where it updates instantly with my files so I don’t have to keep repackaging and uploading, instead I can just work with the xml feeds and stuff and see instant changes.

Here is what I have now:

categoryFeed.brs

Function InitCategoryFeedConnection() As Object
    conn = CreateObject("roAssociativeArray")

    conn.UrlPrefix   = "http://scclib.com/demo/roku"
    conn.UrlCategoryFeed = conn.UrlPrefix + "/categories.php?ts=" + dt.AsSeconds().ToStr()

    conn.Timer = CreateObject("roTimespan")

    conn.LoadCategoryFeed    = load_category_feed
    conn.GetCategoryNames    = get_category_names

    print "created feed connection for " + conn.UrlCategoryFeed
    return conn
End Function

categories.php

<?php
// Send the headers
header('Content-type: text/xml');
header('Pragma: public');
header('Cache-control: private');
header('Expires: -1');

//Store the current time in seconds into variable $now:
$now = time();

echo '<?xml version="1.0" encoding="utf-8" standalone="yes"?>';
echo '<xml>';
echo ' <categories>';
echo '  <category title="Awesomeness" description="Here it iskhj"';
echo '      sd_img="http://scclib.com/demo/roku/images/test_sd_poster.jpg"';
echo '      hd_img="http://scclib.com/demo/roku/images/test_hd_poster.jpg">';

//Append a timestamp to the category feed:
echo '      <categoryLeaf title="Awesomeness" description="" feed="http://scclib.com/demo/roku/xml/xmlfeed.php?ts=' . $now . '" />';

echo '   </category>';
echo ' </categories>';
echo '</xml>';
?>

xmlfeed.php

<?php
	echo file_get_contents('awesomeness.xml');
?>

The result is that when I try clicking the channel in my Home area, nothing happens. When I view channel by finding it in “My Channels” then it comes up with a blank black screen.

What do you see on the debug console?

–Mark

How do I get to a debug console?

Found it:

‘Dot’ Operator attempted with invalid BrightScript Component or interface reference. (runtime error &hec) in …/pkg:/source/categoryFeed.brs(16)

016: conn.UrlCategoryFeed = conn.UrlPrefix + “/categories.php?ts=” + dt.AsSeconds().ToStr()
Backtrace:

Dude! This Debugger is awesome!!! OMG, what a life saver, I can test things now so much easier. I didn’t know this was around. The problem was that I was using the dt.AsSeconds which I copied from dude’s code, but I didn’t add the part assigning it to the object, so dt wasn’t assigned.

“SoutheastTv” wrote:
Found it:

‘Dot’ Operator attempted with invalid BrightScript Component or interface reference. (runtime error &hec) in …/pkg:/source/categoryFeed.brs(16)

016: conn.UrlCategoryFeed = conn.UrlPrefix + “/categories.php?ts=” + dt.AsSeconds().ToStr()
Backtrace:

Dude! This Debugger is awesome!!! OMG, what a life saver, I can test things now so much easier. I didn’t know this was around. The problem was that I was using the dt.AsSeconds which I copied from dude’s code, but I didn’t add the part assigning it to the object, so dt wasn’t assigned.Glad you found it(the error)! The debugger’s a BIG help.

Here is the problem I’m at now:

Escape character is '^]'.
ategory" then
Backtrace:
Function load_category_feed(conn As <uninitialized>) As 
   file/line: /tmp/plugin/DEAAAAKv3.../pkg:/source/categoryFeed.brs(86)
Function initcategorylist() As 
   file/line: /tmp/plugin/DEAAAAKv309F/pkg:/source/appHomeScreen.brs(111)
Function showhomescreen(screen As ) As Integer
   file/line: /tmp/plugin/DEAAAAKv309F/pkg:/source/appHomeScreen.brs(39)
Function main() As 
   file/line: /tmp/plugin/DEAAAAKv309F/pkg:/source/appMain.brs(20)

Local Variables:
conn     &h0010 bsc:roAssociativeArray, refcnt=4
global   &h0020 rotINTERFACE:ifGlobal
m        &h0010 bsc:roAssociativeArray, refcnt=4
http     &h0010 bsc:roAssociativeArray, refcnt=1
rsp      &h8010 bsc:roString (2.1 was String), refcnt=1
xml      &h0010 bsc:roXMLElement, refcnt=1
topnode  &h0000 <uninitialized> val:Uninitialized
categories &h0000 <uninitialized> val:Uninitialized
e        &h0000 <uninitialized> val:Uninitialized
o        &h0000 <uninitialized> val:Uninitialized
BrightScript Debugger> ------ Running ------
created feed connection for http://scclib.com/demo/roku/categories.php?ts=1330111172
url: http://scclib.com/demo/roku/categories.php?ts=1330111172
Took: 92ms
Parse Took: 1ms
Current Function:
057: Function load_category_feed(conn As Object) As Dynamic
058: 
059:     http = NewHttp(conn.UrlCategoryFeed)
060: 
061:     Dbg("url: ", http.Http.GetUrl())
062: 
063:     m.Timer.Mark()
064:     rsp = http.GetToStringWithRetry()
065:     Dbg("Took: ", m.Timer)
066: 
067:     m.Timer.Mark()
068:     xml=CreateObject("roXMLElement")
069:     if not xml.Parse(rsp) then
070:          print "Can't parse feed"
071:         return invalid
072:     endif
073:     Dbg("Parse Took: ", m.Timer)
074: 
075:     m.Timer.Mark()
076:     if xml.category = invalid then
077:         print "no categories tag"
078:         return invalid
079:     endif
080: 
081:     if islist(xml.category) = false then
082:         print "invalid feed body"
083:         return invalid
084:     endif
085: 
086:     if xml.category[0].GetName() <> "category" then
087:         print "no initial category tag"
088:         return invalid
089:     endif
090: 
091:     topNode = MakeEmptyCatNode()
092:     topNode.Title = "root"
093:     topNode.isapphome = true
094: 
095:     print "begin category node parsing"
096: 
097:     categories = xml.GetChildElements()
098:     print "number of categories: " + itostr(categories.Count())
099:     for each e in categories 
100:         o = ParseCategoryNode(e)
101:         if o <> invalid then
102:             topNode.AddKid(o)
103:             print "added new child node"
104:         else
105:             print "parse returned no child node"
106:         endif
107:     next
108:     Dbg("Traversing: ", m.Timer)
109: 
110:     return topNode
111: 
112: End Function
'Dot' Operator attempted with invalid BrightScript Component or interface reference. (runtime error &hec) in .../pkg:/source/categoryFeed.brs(86)

086:     if xml.category[0].GetName() <> "category" then
Backtrace:
Function load_category_feed(conn As <uninitialized>) As 
   file/line: /tmp/plugin/DEAAAAKv3.../pkg:/source/categoryFeed.brs(86)
Function initcategorylist() As 
   file/line: /tmp/plugin/DEAAAAKv309F/pkg:/source/appHomeScreen.brs(111)
Function showhomescreen(screen As ) As Integer
   file/line: /tmp/plugin/DEAAAAKv309F/pkg:/source/appHomeScreen.brs(39)
Function main() As 
   file/line: /tmp/plugin/DEAAAAKv309F/pkg:/source/appMain.brs(20)

Local Variables:
conn     &h0010 bsc:roAssociativeArray, refcnt=4
global   &h0020 rotINTERFACE:ifGlobal
m        &h0010 bsc:roAssociativeArray, refcnt=4
http     &h0010 bsc:roAssociativeArray, refcnt=1
rsp      &h8010 bsc:roString (2.1 was String), refcnt=1
xml      &h0010 bsc:roXMLElement, refcnt=1
topnode  &h0000 <uninitialized> val:Uninitialized
categories &h0000 <uninitialized> val:Uninitialized
e        &h0000 <uninitialized> val:Uninitialized
o        &h0000 <uninitialized> val:Uninitialized

I’ve connected it directly to the categories.xml and it appears to be working fine and updating. Thanks guys. I’ll be good from here on out I think, I’ve got more of a handle on it and connection to the debug program really helped.