Channel __init__.py questions

Now you are talking about the fact that you can modify the Dict to use while the channel is open, right? No modifications that you make to that Dict are permanent and sent back to the JSON data file. Correct?

I was pretty much asking because I created a channel that can pull RSS feeds, YouTube Playlist and YouTube user uploads, as well as original shows from Yahoo and Hulu (though webkit doesn't work for me so Hulu has not been completely tested).  All you need is the URL. You add an entry in the JSON data file with the url and type. (Right now it also has an image field, mainly so I can manually enter them for those shows that do not produce icons, so they look nicer)

I just thought down the line, it would be really cool if it could be set up to let the user enter a url, and then use that url to create a new permanent entry in the JSON data file, allowing the user to add their own shows. Which would also mean it would need the option of editing and deleting entries in the JSON data file.

As I said I am getting way beyond my abilities. I was curious if it was an option.

What I described was a way to store data in the Dict file that survives across reboots. It does not require modifying the stored JSON file. There are a couple reasons I would be hesitant to modify the stored resource file. First, it needlessly complicates things since channels aren’t really intended to write/modify local files. Second, if at some point your plugin is added to the channel directory, changing any file in the plugin bundle (including the stored JSON) will trigger the Appstore’s auto-update to replace the bundle.


Realistically, it would be fairly simple to include a check to see if any “new” feed data has been added to the JSON resource file AND still make use of the channel Dict to store user modifications. Actually, this is all pretty similar in concept to how the U-Appstore functions (as we discussed a little previously).

I see what you are saying with the changing the JSON causing problems with the show once it is added to the channel directory.

It is good to know that this can be accomplished with the Dict[] file.  OK, I looked back at the UnSupportedAppstore.bundle and I see how he adds entries to the Dict and how he uses an uninstall button to delete entries from data. Right now I understand it in theory. it will take me some time and experimenting to completely understand it and be able to actually use it in my channel.

If nothing else, this current channel project has been very helpful to me in learning different processes and methods for writing channels.  It uses a lot of different websites and services, each having different methods for pulls and different challenges and exceptions. So it keeps bringing up new questions and areas of channel design I have to research and learn.

Here is a question.

In looking at some different channels design, I see two different ways to create directories. I have tried to give basic examples of the two methods below. One uses MediaContainers and DirectoryItems and the other uses ObjectContainers and DirectoryObjects. I am just curious why that is, especially considering I do not see any reference to the first example in the Framework Documentation, except the use of MediaContainers in Services. Is the first method still acceptable, are there differences in the two methods, are there situations where you should choose one method over the other, etc.?

Example One:

def DirectoryMenu():
dir = MediaContainer(viewGroup="List", noCache=True)
dir.Append(Function(DirectoryItem(FunctionName1, 'MenuTitle1', 'This is the description for the first menu', thumb = R(ICON))))
dir.Append(Function(DirectoryItem(FunctionName2, 'MenuTitle2', 'This is the description for the second menu', thumb = R(ICON)), var=variable))
return dir

def FunctionName1(sender):

and then here you would add the code for this function

def FunctionName2(sender, var):

and then here you would add the code for this function

Example Two:

def DirectoryMenu():

oc = ObjectContainer()

oc.add(DirectoryObject(key=Callback(FunctionName1, title=“Title1”), title=“Title1”, summary=“This is the description for Title1”, thumb=R(RSS_ICON)))

oc.add(DirectoryObject(key=Callback(FunctionName2, title=“Title2”, var=variable), title=“Title2”, summary=“This is the description for Title2”, thumb=R(RSS_ICON)))

return oc

def FunctionName1(title):

and then here you would add the code for this function

def FunctionName2(title, var):

and then here you would add the code for this function

The first method (using MediaContainers and DirectoryItems) is the old method (framework v2.0). Whereas, the method with the Objects is the new method (framework v2.1-2.3(?)). The old method is (currently) still supported but not capable of some of the extra goodies that become available to channels using the new method and URL Services. I believe the intention is to phase out support for the old (v.20 and previous) method but, I don't know what (if any) timeline has been set for that.

Thanks for the clarification.

OK, I am having trouble with the dict stuff.  First, I cannot figure out how to access a data entry screen in Roku. I tried InputDirectoryObject, but that just takes me to a search screen. It seems to pull up the right screen in PMC but not in Roku. Why is that?

Second, I cannot figure out how to delete an entry.  Which should be the easy part. Every example out on the web is so simple and basic, I cannot figure out how it would translate to a dictionary with multiple lists.

I have a dict called Dict['MyShows'] that has pulled the following data from a JSON. 

[
{type: "rss",url: "http://www.lstudio.com/rss/lstudiorss-web-therapy.xml",thumb: "http://www.lstudio.com/img/WebTherapy_Series_197x111.jpg"},
{type: "rss",url: "http://vimeo.com/channels/highmaintenance/videos/rss",thumb: ""},
{type: "rss",url: "http://www.cwtv.com/feed/video/xml",thumb: ""}
]

How would I delete the whole entry with the url of http://www.cwtv.com/feed/video/xml? {type: "rss",url: "http://www.cwtv.com/feed/video/xml",thumb: ""}

I tried setting up a for loop to find the entry and assign it to a variable. Which is probably making it harder than it should be. I then had a log message to show me the value of the variable which showed:

{u'url': u'http://www.cwtv.com/feed/video/xml' u'type': u'rss', u'thumb': ''}

But I tried several commands to delete it and none worked and all gave me errors. Without the quotes around the variable, it told me I couldn't use a string. With quotes around the variable, it tells me 'NoneType' object does not support item deletion.

I have been searching the Internet and trying different combinations all day and cannot figure out one that works.

Below is the last one I tried:

def DeleteShow(url, show_type):
  Log('The value of url is %s' %url)
  shows = Dict["MyShows"]
  show_del = ''
  for show in shows:
    if show['url'] == url:
      Log('show is %s' %show)
      show_del = show

  del Dict['MyShow']['show_del']
  Log(Dict['MyShows'])
  # Then send a message
  return MessageContainer(NAME, 'The show has been deleted from the channel.')

I think the issue that you are running in to is that you are trying to delete an entry from the Dict that doesn't have a direct reference key.  I can think of two ways around this.

One would be two assign a key to each "show" listed in "MyShows". For Example:

{
"web-therapy":{type: "rss",url: "http://www.lstudio.com/rss/lstudiorss-web-therapy.xml",thumb: "http://www.lstudio.com/img/WebTherapy_Series_197x111.jpg"},
"highmaintenance":{type: "rss",url: "http://vimeo.com/channels/highmaintenance/videos/rss",thumb: ""},
"cwtv":{type: "rss",url: "http://www.cwtv.com/feed/video/xml",thumb: ""}
}

Then you should be able to use the del command with the appropriate key. Like so,

del Dict['MyShows']['cwtv']

The other option would be to use the numerical index of the show as the key and delete it that way. Something like this:


i = 0
for show in Dict['MyShows']:
  if show['url'] == url_of_show_to_delete:
    del Dict['MyShows']*
  else:
    i += 1

In regards to the Roku data entry, it is my understanding that the "Search" screen is the only data entry option available to channels on the Roku client. If you know of any other Roku apps that offer a different data entry option, we may be able to pester the Plex-dev in charge of the Roku client to add another Data entry option. Otherwise, we kind of have to make do with what we have.

Thanks.  I had seen that the appstore had a name for each entry. But since user entry is so basic and I was trying to keep it simple and only have the user enter a url and then pull the title or name for the show from that url, I wasn't sure how I would add a name to each entry.  So, it will probably work best with the numeric reference key for each entry.

Here is the thing about Roku user entry.  There is the option of user entry in Roku already and it works with Plex. The user entry screen works on Roku with channels for the PrefsObject. (I know in the past you had to have PMC just to enter preferences like username and passwork in Roku because those screens brought up the search page instead. But now they work properly.) So if they have already figured out how to get the Roku to bring up the user entry screen in Plex for PrefsObject, which can have a variety of options for input, it would seem they have already figured out the biggest glitch for user entry in the Roku.  So in theory, they should be able to use whatever method they used to alter the PrefsObject and make it work as user entry to make the UserInputObject work for user entry.

I know I am talking in theory, but the Roku Search screen option doesn't fully work in Plex anyway. It only allows you to enter keywords anyway which is pretty much user entry.  The Search suggestions option of the Roku search screen does not work in Plex, so why not change the UserInputObject to straight user entry so it can handle entry and keywords?

As for user entry in channels, I know there was at least one other channel that tried to allow user entry cause I tried to use it when I first started and had to install PMC just for entry. It was that RSS feed channel Feed Me, though it seemed to bring up a search in Roku and PMC. Of course there aren't any channels using user entry right now. Why would anyone want to add user entry to their channel, if it doesn't work on half of the clients? There are probably at least a few that would like to have user entry if they knew it would work with PMC and Roku.

Am I making a good case? :D

I will start a thread and see if we can get anyone else interested in pestering the Plex-Dev Roku guys.

Here is a question for you guys. How do you keep Roku from sending a query to your channel for every letter entered in the search user input screen? I have a InputDirectoryObject that send the results of the query to an add function in my code, but If I enter three letters into the the search screen produced by the InputDirectoryObject in Roku, it send three request back to my function.  One with the first letter, one with the first and second letter, and one with the all three letters.

I think I found a way around the Roku search box vs user input issue, but not as long as it creates a new item in my directory for every letter entered in to the search screen. It is filling my dictionary with alot of junk.

I remember Mikwhy saying something about having to turn off the autocomplete. Could that be the issue?

I am taking that since noone has responded that there is no solution to the Roku search query sending every keystroke to your function.  I looked around and tried to see if others addressed this. I figured YouTube had a search that works well with Roku, so if any channel stopped this, it would be that channel, but instead even YouTube's channel sends a request to the search for every entry. And there was nothing in the documentation that would allow some type of argument to prevent this, but could not find anything.I even considered trying to add in a function to put all the entries in a list and tell it just use the last entry, but I am not sure if there is any real way to determine when the last keystroke is entered. I do not see any added value returned in the query variable after the search button is clicked.

So my next question is MessageContainer, is it still used or is that outdated?

Also, is there a way to return a message to the screen and then direct back to a function.  For example, once a show is added or deleted, I would like to be able to pop a message up that says the show was added or deleted and then return to the function that lists the updated shows. I can seem to do one or the other but not both. I can either return it to the function or return an object container message. And if I do use an object container to pop up a message to the screen it is then immediately followed by an empty directory message.
 

So my next question is MessageContainer, is it still used or is that outdated?

MessageContainer is old. If you want to display a message to the user, you can set the header and message attribute on an ObjectContainer.

http://dev.plexapp.com/docs/api/objectkit.html#ObjectContainer.header

I am adding some final tweaks to the __init__.py template I created and had a question.

@route(PREFIX + '/functionnickname')

Why exactly do you add the route above  to each function? I know there is a warning in your channel code if you do not include it and the Framework documentation says it helps the designer create a "rest-like API." What exactly does that mean? I am thinking it somehow would allow you access to this particular function from outside of the __init__.py file. Is that correct?

I also have an objects question. 

I have a video source/website that provides the season and episode info in a json data file, so I figured it was best to use the EpisodeObject to take advantage of all the info provided. What is returned to the screen by the EpisodeObject for each episode is the thumb with the title underneath and a third line that gives the season, episode, and date (originally_available_at).

But the EpisodeObject does not have an episode attribute, so that third line that is produces by my channel for every entry shows the word Episode followed by double question marks. For example:

Season 1 - Episode ?? - 2013-05-31

And I cannot figure out how to populate that episode double question mark field.  I tried using the absolute_index, but that didn't work. Why does that third line come up as Episode - ?? and is there a way to change the double question mark to a episode value?

“index” is the attribute to use for setting the EpisodeNumber of a video within a Season. “absolute_index” is for shows that do not use season numbering so, I presume that if you set the value for “season” and “absolute_index” there may be some confusion (in the framework or client, not sure which) as to what should be displayed.

Thanks Mike, index (with an integer value) worked. And, BTW, when I tried absolute index, it didn't change anything. At least in the Roku client. It defaulted to the season attribute (season was listed in the returned attributes for the objects before the absolute index, though I could not say if that influenced the way the Roku used the data).

But why is index not listed as an attribute of the EpisodeObject in the Framework Documentation? Is index, just a default attribute that is available for all Metadata Objects whether it is listed or not? Are there any other attributes that are default for all objects?

Or is this just an oversight in the Framework Documentation or a change that has been made since the Framework Documentation was last updated? Which leads me to my next question, since with each version of Plex, they may add little tweaks that may improve the programming that may not be updated in the Framework Documentation, is there a forum post that lets you know updates to Plex that specifically affect, change, or improve channel development?

It would be nice to have a pinned list of API changes or additions that may not be included in the existing Framework Documentation.

It’s definitely an oversight that “index” is not listed in the framework docs for EpisodeObject. Updating the docs always seems to lag. There is some effort being madeto update them but that tends to fall to volunteers, just like the channel development, since the main Plex developer in charge of the channel framework (Jam) has a lot of other stuff on his plate too.

I agree, a pinned forum post with notes about updates that are not (yet) included in the docs is a good idea. Hopefully, we can get a few of the notable omissions publicized for more general use.

Here a question for you guys.

In looking at a site, I noticed in the network activity that some pages used a stripped down ajax URL to populate a list of episodes and video clips for shows. I would think in theory, it would always be better to use that ajax URL. It had very little code in it to be changed or tweaked and would be less likely to be changed by the site than the regular show pages, so your code will last longer. But that ajax URL only provided the most basic info (url, thumb and title), while the regular show page also offered description and date. And more importantly, the ajax URL was very slow. It about took twice as long to produce results as the pull from the regular show page.

So the question is:

Is it better to make your code less resistant to change or make it as fast as possible?

And another question, are default image settings in variables, Startup defaults for objects and handler no longer necessary?

Here a question for you guys.

In looking at a site, I noticed in the network activity that some pages used a stripped down ajax URL to populate a list of episodes and video clips for shows. I would think in theory, it would always be better to use that ajax URL. It had very little code in it to be changed or tweaked and would be less likely to be changed by the site than the regular show pages, so your code will last longer. But that ajax URL only provided the most basic info (url, thumb and title), while the regular show page also offered description and date. And more importantly, the ajax URL was very slow. It about took twice as long to produce results as the pull from the regular show page.

So the question is:

Is it better to make your code less resistant to change or make it as fast as possible?

This is a tough one! Even if loading the 'Ajax' URLs (is it JSON formatted?) is slow, with some smart caching this doesn't have to be that big of a problem. But since the metadata in the HTML pages is richer, I would prefer that. Website markup and Ajax URL parameters or JSON content will change all the time (breaking the channel), but with some smart xpath queries you can usually survive small changes.

And another question, are default image settings in variables, Startup defaults for objects and handler no longer necessary?

You still need them, just like before, but there's a new option that allows us to use icons and background art that's hosted on a CDN.