setResolvedUrl: what does it do ?

  Thread Rating:
  • 0 Votes - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Post Reply
realtebo Offline
Senior Member
Posts: 164
Joined: Apr 2013
Reputation: 0
Post: #1
What is the goal of the method "setResolvedUrl" ?

Wha'ts a way to utilize when developing audio or video plugin ?
find quote
sphere Offline
Team-Kodi Member
Posts: 1,205
Joined: Jul 2009
Reputation: 50
Location: Germany
Post: #2
setResolvedUrl is used to - like the name says - set the (playable) url for an listitem _after_ it got selected.

Main call flow for a plugin without setResolvedUrl is as following:
1. plugin adds a bunch of listitems which have URLs pointing back to the plugin and isFolder=True
(optional repeat step 1 multiple times)
2. plugin adds a bunch of listitems which have playable URLs pointing to a playable resource with isFolder=False (e.g. http://server.com/video.mp4 or rtmp://foo.bar/file)
3. user chose one of them and xbmc starts playing the already known playable url
Problem is, in some cases the plugin does not know the playable URL for all items which were populated in step 2 - the plugin would become slow because it needs to calculate or scrape the playable URLs for multiple ListItems - even if the user only wants to play one of them. This is (one of multiple) good usecases for the usage of setResolvedUrl.

Here the same flow but _with_ the usage of setResolvedUrl:
1. plugin adds a bunch of listitems which have URLs pointing back to the plugin and isFolder=True
(optional repeat step 1 multiple times)
2. plugin adds a bunch of listitems which have not playable URLs (pointing back the plugin) with isFolder=False - but these items represent playable files for which the plugin does not yet know the playable URL
3. user chose one of them and the plugin gets called to set the _resolved_ playable url for the chosen listitem and does so.
4. the player receives the playable url via setResolvedUrl and starts playing the now known playable url.

There are some other usecases in which the usage (or the extra level/round of plugin call) makes sense, e.g.:
- time critical URLs in general (if the user wants to add a listitem to its favourites, the url could be outdated on later call)
- dynamic URLs (the listitem is is meant for something like "play the newest video")
- preventing of XBMC's mime type retrieving HEAD-Request for all playable ListItems URLs
- (much more rare reasons)

My GitHub. My Add-ons:
[Image: IOoywq0.jpg]
find quote
realtebo Offline
Senior Member
Posts: 164
Joined: Apr 2013
Reputation: 0
Post: #3
A lot of thanks for the tutorial !

I plan to try this different approach in 2 weeks. My Plugin actually have a 'clean' list of url, every one is static, playable and fully resolved, so I'm thinking about the need to do the change, but I'd like to try, and, of course, if it's the 'official' way to play a video, I want to learn it
find quote
josetaza Offline
Junior Member
Posts: 45
Joined: Aug 2013
Reputation: 2
Location: The Netherlands, Eindhoven
Post: #4
I found out the setResolvedUrl() is useless without settings the item.setProperty("IsPlayable", "true"). so like:
Code:
liz=xbmcgui.ListItem(name, iconImage="DefaultVideo.png", thumbnailImage=iconimage)
liz.setInfo( type="Video", infoLabels={ "Title": name , "Plot" : detail } )
liz.setProperty('IsPlayable', 'true')
liz.addContextMenuItems([('Add to My Favorite','xbmc.RunPlugin(%s?mode=12&name=%s&url=%s&iconimage=%s)'%(sys.argv[0],name,url,iconimage))])
ok=xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]),url=u,listitem=liz)
Otherwise the plugin is called back with an invalid handle (sys.arg[1]). It took me a lot of time to figure this out...

But this only works for video and music items.
Is there also a special (hidden) property to set to make this work for picture items?
Thanks.
find quote
realtebo Offline
Senior Member
Posts: 164
Joined: Apr 2013
Reputation: 0
Post: #5
Do you have an example to a classic listitem and enddirectory ?
find quote
learningit Offline
Senior Member
Posts: 242
Joined: Aug 2012
Reputation: 8
Post: #6
(2013-10-04 11:14)realtebo Wrote:  Do you have an example to a classic listitem and enddirectory ?

Have a look at this really simple addon I wrote for RT News: https://github.com/learningit/plugin.vid...default.py

getSources has an example of how to setup a a directory with a playable link and links another level of directories

mode==18 scrapes a webpage and builds a directory of urls with enough data to pass to mode==19 which scrapes and plays the actual link, rather than reading dozens of pages to create static urls.

Remember that everything falls through to the xbmcplugin.endOfDirectory(int(sys.argv[1])) at the end of the module.

I use code similar to mode==19 all the time to allow the addon to be called from other addons to play urls which require tokens, cookies, whatever.
You can have a look at https://github.com/learningit/plugin.vid...nowtvguide at mode=='play' to see how I modified an existing USTVNOW addon which uses dynamic urls to allow it to be played from a static url in a .strm file from the tvguide addon.

Link to my t1m/learningit XBMC Addons: [Image: HLVT8d8.png]
(This post was last modified: 2013-10-04 20:28 by learningit.)
find quote
realtebo Offline
Senior Member
Posts: 164
Joined: Apr 2013
Reputation: 0
Post: #7
So, in this piece of coce : https://github.com/realtebo/plugin.video...y#L115-137
Code:
    for mp4 in json["files"][language_code]["MP4"]:

        url                 = mp4["file"]["url"]
        res                 = mp4["label"]
        mp4_title_cleaned     = jw_common.cleanUpText (mp4["title"])
        title                 = "[" + res + "] - " + mp4_title_cleaned

        listItem = xbmcgui.ListItem(
            label             = title,
            thumbnailImage    = thumb
        )
        listItem.setInfo(
            type         = 'Video',
            infoLabels     = {'Title': mp4_title_cleaned}
        )
        xbmcplugin.addDirectoryItem(
            handle        = jw_config.pluginPid,
            url            = url,
            listitem    = listItem,
            isFolder    = False
        )  

    xbmcplugin.endOfDirectory(handle=jw_config.pluginPid)

i tried to do the following mod

Code:
    for mp4 in json["files"][language_code]["MP4"]:

        url                 = mp4["file"]["url"]
        res                 = mp4["label"]
        mp4_title_cleaned     = jw_common.cleanUpText (mp4["title"])
        title                 = "[" + res + "] - " + mp4_title_cleaned

        listItem = xbmcgui.ListItem(
            label             = title,
            thumbnailImage    = thumb
        )
        listItem.setInfo(
            type         = 'Video',
            infoLabels     = {'Title': mp4_title_cleaned}
        )
        listItem.setProperty("IsPlayable","true")

        """
        xbmcplugin.addDirectoryItem(
            handle        = jw_config.pluginPid,
            url            = url,
            listitem    = listItem,
            isFolder    = False
        )  
        """
        
        xbmcplugin.setResolvedUrl( handle=jw_config.pluginPid, succeeded=True, listitem=listItem)

    xbmcplugin.endOfDirectory(handle=jw_config.pluginPid)

but I simply got an empty list ... What I'm missing ?

from log
Quote:NOTICE: ['plugin://plugin.video.jworg/', '29', '?content_type=video&json_url=%2fapps%2fTRGCHlZRQVNYVrXF%3fdocid%3d502013390%26output%3djson%26fi​leformat%3dmp4%26alllangs%3d1%26track%3d1%26langwritten%3dI%26txtCMSLang%3dI&mode=open_json_video&thumb=http%3a%2f%2fassets.jw.org%2fassets%2fm%2fijw14nw%2f502013390%2fijw14n​w_id-502013390.art%2f502013390_univ_sqr_md.jpg']
WARNING: Attempt to use invalid handle 29
WARNING: Previous line repeats 3 times.
NOTICE: Thread Background Loader start, auto delete: false
(This post was last modified: 2013-10-07 16:09 by realtebo.)
find quote
learningit Offline
Senior Member
Posts: 242
Joined: Aug 2012
Reputation: 8
Post: #8
Try casting the jw_config.pluginPid to int, ie int(jw_config.pluginPid) wherever you're using it. It looks like a str to me. I'm assuming that jw_config.pluginPid is a global storing sys.argv[1] from the initial addon call.

Link to my t1m/learningit XBMC Addons: [Image: HLVT8d8.png]
find quote
divingmule Offline
Skilled Python Coder
Posts: 1,297
Joined: Oct 2008
Reputation: 61
Post: #9
As sphere explained, setResolvedUrl is called after the user selects the list item.

So your list item URL should be a 'plugin://plugin.video.jworg' url that calls back to your script with a 'mode' that calls setResolvedUrl with the actual media URL, then the player starts.
find quote
realtebo Offline
Senior Member
Posts: 164
Joined: Apr 2013
Reputation: 0
Post: #10
I'm simply don't undertstanding why to add more code and more work to something it's already working....

If the goal is 'only' to allow my plugin to be callable from external, I'll don't change my code
I know it's very important for some plugin, but not for mine.

(2013-10-07 16:41)learningit Wrote:  Try casting the jw_config.pluginPid to int, ie int(jw_config.pluginPid) wherever you're using it. It looks like a str to me. I'm assuming that jw_config.pluginPid is a global storing sys.argv[1] from the initial addon call.

No, jw_config.pluginPid is already been casted to integer.
(This post was last modified: 2013-10-07 16:50 by realtebo.)
find quote
learningit Offline
Senior Member
Posts: 242
Joined: Aug 2012
Reputation: 8
Post: #11
Sorry, i only glanced at the error msg, divingmule is absolutely right. setResolvedUrl is not just for allowing a plugin to be externally callable. It can also be used to defer choices and config parms. For example with the website you're trying to scrape, there are many language choices and video resolution choices. If you defer the building of the playable url based upon language selection, people will be able to add videos to favorites and playlists and be able to globally switch languages being played based upon an addon config parameter because it's not a static url. Likewise for a global addon setting for the video resolution to play. Using your static method, they would have to change all playlists and favorites.

Link to my t1m/learningit XBMC Addons: [Image: HLVT8d8.png]
(This post was last modified: 2013-10-07 19:41 by learningit.)
find quote
realtebo Offline
Senior Member
Posts: 164
Joined: Apr 2013
Reputation: 0
Post: #12
Uhm .. I'm really thankfull for your explanation. If I'd see a situation unable to solve, I'll retry to apply this method.
find quote
o2ri Offline
Junior Member
Posts: 16
Joined: Jun 2013
Reputation: 0
Post: #13
i have read all the posts in this thread few times
i think that i am missing something:

1- most of the popular addons i see dont use it
2- it seems like something very important , but i cant understand it yet !

right now i am using folder=false but the addon DONOT scrap each url , so what is the diference?

i really need a simple explanation.
find quote
learningit Offline
Senior Member
Posts: 242
Joined: Aug 2012
Reputation: 8
Post: #14
(2013-12-09 23:15)o2ri Wrote:  i have read all the posts in this thread few times
i think that i am missing something:

1- most of the popular addons i see dont use it
2- it seems like something very important , but i cant understand it yet !

right now i am using folder=false but the addon DONOT scrap each url , so what is the diference?

i really need a simple explanation.

I think what hasn't been specifically said in this thread is that there is a difference between an addon script and an addon plugin. I may get this wrong (and someone correct me if I am), but a plugin is really just an lightweight event processor that handles directory items and doesn't have to concern itself with window processing etc. It is called (loaded) each time a user-defined event occurs to handle reasonable high level activities. There is a single thread which represents the plugin. The final call to xbmcplugin.endOfDirectory is something akin to DefaultWinProc in that it handles all the nitty-gritty common processing details. setResolvedUrl simply sets up that processing for playing a directory item that isn't directly marked as playable when added to the directory.

There are a few reasons for doing it this way, but the most common I've seen is either when you have an index page that you've scrapped which contains urls or video ids to the pages which have the actual playable urls. Another reason is when a token has to be created to play the url. Rather than read each individual pointed to page to resolve the url as you build the index directory, you can put enough info from the index page into the url stored in the index directory item (as playable=false and folder=false) to allow a routine resolve the actual playable url and create a playable directory item for it. It allows you to postpone some the work until the user clicks on the link.

An addon script loads and remains resident, can manage multiple threads and a richer set of events such as input, timers, window components, etc. I think many of the addons that you see directly calling the player, rather than setresolvedUrl are addon scripts, not plugins.

Link to my t1m/learningit XBMC Addons: [Image: HLVT8d8.png]
(This post was last modified: 2013-12-10 00:35 by learningit.)
find quote
foomanshoe Offline
Junior Member
Posts: 13
Joined: Nov 2013
Reputation: 1
Post: #15
(2013-12-10 00:31)learningit Wrote:  
(2013-12-09 23:15)o2ri Wrote:  i have read all the posts in this thread few times
i think that i am missing something:

1- most of the popular addons i see dont use it
2- it seems like something very important , but i cant understand it yet !

right now i am using folder=false but the addon DONOT scrap each url , so what is the diference?

i really need a simple explanation.

I think what hasn't been specifically said in this thread is that there is a difference between an addon script and an addon plugin. I may get this wrong (and someone correct me if I am), but a plugin is really just an lightweight event processor that handles directory items and doesn't have to concern itself with window processing etc. It is called (loaded) each time a user-defined event occurs to handle reasonable high level activities. There is a single thread which represents the plugin. The final call to xbmcplugin.endOfDirectory is something akin to DefaultWinProc in that it handles all the nitty-gritty common processing details. setResolvedUrl simply sets up that processing for playing a directory item that isn't directly marked as playable when added to the directory.

There are a few reasons for doing it this way, but the most common I've seen is either when you have an index page that you've scrapped which contains urls or video ids to the pages which have the actual playable urls. Another reason is when a token has to be created to play the url. Rather than read each individual pointed to page to resolve the url as you build the index directory, you can put enough info from the index page into the url stored in the index directory item (as playable=false and folder=false) to allow a routine resolve the actual playable url and create a playable directory item for it. It allows you to postpone some the work until the user clicks on the link.

An addon script loads and remains resident, can manage multiple threads and a richer set of events such as input, timers, window components, etc. I think many of the addons that you see directly calling the player, rather than setresolvedUrl are addon scripts, not plugins.

This is exactly it. I have a video plugin that lists a bunch of categories. When you click on a category it scrapes a website and grabs all of the information for all the videos listed on the page. Some pages may have 50 videos. Unfortunately the acutal mp4 file for each video is not located on that page. You have to click on each indivudual thumbnail to be taken to the video. So, if I didn't use setResolvedUrl() I would have to load 50 pages and scrape them to find the mp4 file, which would take too long and the video plugin would sit there for minutes. Instead, I get the url that the video is on, then scrape it to find the mp4, then call setResolvedIUrl().

You can see that here: https://bitbucket.org/boralyl/plugin.vid...ster#cl-27
(This post was last modified: 2013-12-10 22:58 by foomanshoe.)
find quote
Post Reply