1st plugin - help required

I am trying to write a plugin to play some IPTV my ISP provides, via rtp streams.

In theory this sounds pretty straight forward, however I am having huge trouble getting this off the ground. If anyone could PLEASE offer some help, I’d really appreciate it!



An XML playlist is provided by my ISP, which is generated dynamically, as not everyone is entitled to the same channels - some locations (ie. Sydney) get 30 channels, where as in Adelaide, I get 5.

I gather all I need to do is to parse this playlist, find the IPTV streams, and add them as videoItems. However, as the error below shows, I am not having any luck!




I've used the basic kick start, and simply edited the __init__.py file to add some custom features, like attempting to parse a XML document, and append menu options based upon the results.
But whenever I enable my for loop as below, I'm met with all the errors show above.


VIDEO_PREFIX = "/video/tpgtv"<br />
<br />
NAME = L('Title')<br />
<br />
# make sure to replace artwork with what you want<br />
# these filenames reference the example files in<br />
# the Contents/Resources/ folder in the bundle<br />
ART  = 'art-default.jpg'<br />
ICON = 'icon-default.png'<br />
<br />
####################################################################################################<br />
<br />
def Start():<br />
<br />
    ## make this plugin show up in the 'Video' section<br />
    ## in Plex. The L() function pulls the string out of the strings<br />
    ## file in the Contents/Strings/ folder in the bundle<br />
    ## see also:<br />
    ##  http://dev.plexapp.com/docs/mod_Plugin.html<br />
    ##  http://dev.plexapp.com/docs/Bundle.html#the-strings-directory<br />
    Plugin.AddPrefixHandler(VIDEO_PREFIX, VideoMainMenu, NAME, ICON, ART)<br />
<br />
    Plugin.AddViewGroup("InfoList", viewMode="InfoList", mediaType="items")<br />
    Plugin.AddViewGroup("List", viewMode="List", mediaType="items")<br />
<br />
    ## set some defaults so that you don't have to<br />
    ## pass these parameters to these object types<br />
    ## every single time<br />
    ## see also:<br />
    ##  http://dev.plexapp.com/docs/Objects.html<br />
    MediaContainer.title1 = NAME<br />
    MediaContainer.viewGroup = "List"<br />
    MediaContainer.art = R(ART)<br />
    DirectoryItem.thumb = R(ICON)<br />
    VideoItem.thumb = R(ICON)<br />
<br />
    HTTP.CacheTime = CACHE_1HOUR<br />
<br />
<br />
<br />
<br />
#### the rest of these are user created functions and<br />
#### are not reserved by the plugin framework.<br />
#### see: http://dev.plexapp.com/docs/Functions.html for<br />
#### a list of reserved functions above<br />
<br />
<br />
<br />
#<br />
# Example main menu referenced in the Start() method<br />
# for the 'Video' prefix handler<br />
#<br />
<br />
def VideoMainMenu():<br />
<br />
<br />
    # Container acting sort of like a folder on<br />
    # a file system containing other things like<br />
    # "sub-folders", videos, music, etc<br />
    # see:<br />
    #  http://dev.plexapp.com/docs/Objects.html#MediaContainer<br />
    dir = MediaContainer(viewGroup="InfoList")<br />
<br />
<br />
    # see:<br />
    #  http://dev.plexapp.com/docs/Objects.html#DirectoryItem<br />
    #  http://dev.plexapp.com/docs/Objects.html#function-objects<br />
    dir.Append(<br />
        Function(<br />
            DirectoryItem(<br />
                CallbackExample,<br />
                "directory item title",<br />
                subtitle="subtitle",<br />
                summary="clicking on me will call CallbackExample",<br />
                thumb=R(ICON),<br />
                art=R(ART)<br />
            )<br />
        )<br />
    )<br />
<br />
    for iptvStream in XML.ElementFromURL('http://www.tpg.com.au/iptv/playlist.php',isHTML=true,errors='ignore').xpath('/a:playlist/a:trackList/a:track'):<br />
        dir.Append(<br />
            Function(<br />
                DirectoryItem(<br />
                    CallbackExample,<br />
                    "1234",<br />
                    subtitle="subtitle",<br />
                    summary="clicking on me will call CallbackExample",<br />
                    thumb=R(ICON),<br />
                    art=R(ART)<br />
                )<br />
            )<br />
        )<br />
<br />
<br />
<br />
<br />
    # ... and then return the container<br />
    return dir<br />
<br />
def CallbackExample(sender):<br />
<br />
    ## you might want to try making me return a MediaContainer<br />
    ## containing a list of DirectoryItems to see what happens =)<br />
<br />
    return MessageContainer(<br />
        "Not implemented",<br />
        "In real life, you'll make more than one callback,
and you'll do something useful.
sender.itemTitle=%s" % sender.itemTitle<br />
    )



An example of the XML document is:

<?xml version="1.0" encoding="UTF-8"?><br />
<playlist version="1" xmlns="http://xspf.org/ns/0/"><br />
<trackList><br />
	<track><br />
		<location>rtp://@al-jazeera.iptv.tpg.com.au:1234</location><br />
		<title>Al Jazeera</title><br />
	</track><br />
	<track><br />
		<location>rtp://@bloomberg.iptv.tpg.com.au:1234</location><br />
		<title>Bloomberg</title><br />
	</track><br />
	<track><br />
		<location>rtp://@cnai.iptv.tpg.com.au:1234</location><br />
		<title>Channel News Asia</title><br />
	</track><br />
	<track><br />
		<location>rtp://@phoenix-info-news.iptv.tpg.com.au:1234</location><br />
		<title>Phoenix InfoNews</title><br />
	</track><br />
	<track><br />
		<location>rtp://@tv5-monde.iptv.tpg.com.au:1234</location><br />
		<title>TV5 Monde</title><br />
	</track><br />
	<track><br />
		<location>rtp://@playboy.iptv.tpg.com.au:1234</location><br />
		<title>Playboy TV</title><br />
	</track><br />
</trackList><br />
</playlist><br />
 <br />


Hey Mike!



A plug-in failing to start like that indicates a syntax error in the code. If you check the individual plug-in log file in the “~/Library/Logs/PMS Plugin Logs” folder, this should provide more information.



Hey Jam, thanks for pointing me to the plugin log - I had looked for that but couldnt find it anywhere!
Unfortunately the output doesnt appear to be very helpful

I just want to clarify, does the plugin show up in the client? Are you able to open it?



Also, I would change this line


for iptvStream in XML.ElementFromURL('http://www.tpg.com.au/iptv/playlist.php',isHTML=true,errors='ignore').xpath('/a:playlist/a:trackList/a:track'):


to

for iptvStream in XML.ElementFromURL('http://www.tpg.com.au/iptv/playlist.php',errors='ignore').xpath('//track'):


The "isHTML" flag indicates that you're trying to parse HTML using the XML parser instead of the HTML parser, which you're not since you have nice clean XML. The change to the xpath just cleans it up and I don't think the "a:" tags are necessary.



Hey Mikedm139, the plugin shows correctly, but would not launch.
I've made the changes as you suggested and its now launching! Thankyou!

I need to revise my XPATH iteration as it is not picking up any tracks, with //track or with /playlist/trackList/track. I think this may have something to do with the xmlns="http://xspf.org/ns/0/" name space - I'm not sure how to parse the XML correctly.



2012-01-15 09:24:01,772 (-4fa6b000) :  DEBUG (prefskit:218) - Loaded preferences from DefaultPrefs.json<br />
2012-01-15 09:24:01,774 (-4faed000) :  DEBUG (runtime:528) - Handling request GET /video/tpgtv<br />
2012-01-15 09:24:01,776 (-4faed000) :  DEBUG (runtime:575) - Found prefix handler matching /video/tpgtv<br />
2012-01-15 09:24:01,776 (-4faed000) :  INFO (__init__:50) - VideoMainMenu initiated<br />
2012-01-15 09:24:01,777 (-4fa6b000) :  DEBUG (prefskit:320) - Loaded the user preferences for com.plexapp.plugins.tpgtv<br />
2012-01-15 09:24:01,779 (-4fa6b000) :  DEBUG (prefskit:353) - Saved the user preferences<br />
2012-01-15 09:24:01,780 (-4faed000) :  DEBUG (networking:111) - Fetching 'http://www.tpg.com.au/iptv/playlist.php' from the HTTP cache<br />
2012-01-15 09:24:01,786 (-4faed000) :  DEBUG (runtime:678) - Response: 200

The playlist.php file shows up empty for me … :huh:

Anyway, you can declare the namespace(s) as a dict and then prefix the elements in your xpath that need it with the right key:



NAMESPACES = {'a':'http://xspf.org/ns/0/'}<br />
<br />
# ...<br />
<br />
for iptvStream in XML.ElementFromURL('http://www.tpg.com.au/iptv/playlist.php', errors='ignore').xpath('//a:track', namespaces=NAMESPACES):<br />
  # ...<br />




I assume that's because it's a dynamically generated file, and the contents vary on the IPTV content available to you - and given TPG IPTV is for tpg.com.au customers only, the file may not generate content if your not on a TPG internet connection.




HOTDAMN! IT WORKED! I now see 6 new menu items labelled "1234".

Now I just need to get the actual URL and provide the RTP stream, and I should be laughing!

Thanks for the ongoing help everyone!

hey i’m going to bump this as I’m stuck further. Basically - I cannot open a web stream of the rtp content!

I just get a “Error while opening file” error!

I’m so close i can taste victory! Please Help!



My Code:


<br />
VIDEO_PREFIX = "/video/tpgtv"<br />
NAME = L('Title')<br />
ART  = 'art-default.jpg'<br />
ICON = 'icon-default.png'<br />
NAMESPACES = {'a':'http://xspf.org/ns/0/'}<br />
<br />
####################################################################################################<br />
def Start():<br />
<br />
    Plugin.AddPrefixHandler(VIDEO_PREFIX, VideoMainMenu, NAME, ICON, ART)<br />
<br />
    Plugin.AddViewGroup("InfoList", viewMode="InfoList", mediaType="items")<br />
    Plugin.AddViewGroup("List", viewMode="List", mediaType="items")<br />
<br />
    MediaContainer.title1 = NAME<br />
    MediaContainer.viewGroup = "List"<br />
    MediaContainer.art = R(ART)<br />
    DirectoryItem.thumb = R(ICON)<br />
    VideoItem.thumb = R(ICON)<br />
    <br />
    HTTP.CacheTime = CACHE_1HOUR<br />
<br />
<br />
<br />
<br />
<br />
<br />
####################################################################################################<br />
def VideoMainMenu():<br />
<br />
<br />
    dir = MediaContainer(viewGroup="InfoList")<br />
<br />
<br />
    i=0<br />
    xmlData = XML.ElementFromURL('http://www.tpg.com.au/iptv/playlist.php',errors='ignore')<br />
    for iptvStream in xmlData.xpath('//a:track', namespaces=NAMESPACES):<br />
        url = iptvStream.xpath('//a:location', namespaces=NAMESPACES)*.text<br />
        title = iptvStream.xpath('//a:title', namespaces=NAMESPACES)*.text<br />
        Log("Found stream " + title + " (" + url + ")")<br />
<br />
        thumbTitle = title.lower().replace(" ","")<br />
        thumbTitle = thumbTitle.replace("channelnewsasia", "newsasia")<br />
        thumb = 'http://www.tpg.com.au/iptv/img/logo_' + thumbTitle + '_s.gif'<br />
        Log("Thumb: " + thumb)<br />
<br />
<br />
        dir.Append(<br />
            WebVideoItem(<br />
                url,<br />
                title=title,<br />
                subtitle="Click to open this stream!",<br />
                summary="Uh..",<br />
                thumb=thumb<br />
            )<br />
        )        i = i + 1<br />
<br />
 <br />
<br />
<br />
<br />
<br />
    return dir



My Log:

2012-01-17 07:20:00,935 (-4faed000) :  DEBUG (networking:111) - Fetching 'http://www.tpg.com.au/iptv/playlist.php' from the HTTP cache<br />
2012-01-17 07:20:00,937 (-4faed000) :  INFO (__init__:42) - Found stream Al Jazeera (rtp://@al-jazeera.iptv.tpg.com.au:1234)<br />
2012-01-17 07:20:00,938 (-4faed000) :  INFO (__init__:48) - Thumb: http://www.tpg.com.au/iptv/img/logo_aljazeera_s.gif<br />
2012-01-17 07:20:00,939 (-4faed000) :  INFO (__init__:42) - Found stream Bloomberg (rtp://@bloomberg.iptv.tpg.com.au:1234)<br />
2012-01-17 07:20:00,939 (-4faed000) :  INFO (__init__:48) - Thumb: http://www.tpg.com.au/iptv/img/logo_bloomberg_s.gif<br />
2012-01-17 07:20:00,940 (-4faed000) :  INFO (__init__:42) - Found stream Channel News Asia (rtp://@cnai.iptv.tpg.com.au:1234)<br />
2012-01-17 07:20:00,941 (-4faed000) :  INFO (__init__:48) - Thumb: http://www.tpg.com.au/iptv/img/logo_newsasia_s.gif4<br />
2012-01-17 07:20:00,941 (-4faed000) :  INFO (__init__:42) - Found stream Phoenix InfoNews (rtp://@phoenix-info-news.iptv.tpg.com.au:1234)<br />
2012-01-17 07:20:00,942 (-4faed000) :  INFO (__init__:48) - Thumb: http://www.tpg.com.au/iptv/img/logo_phoenixinfonews_s.gif<br />
2012-01-17 07:20:00,943 (-4faed000) :  INFO (__init__:42) - Found stream TV5 Monde (rtp://@tv5-monde.iptv.tpg.com.au:1234)<br />
2012-01-17 07:20:00,943 (-4faed000) :  INFO (__init__:48) - Thumb: http://www.tpg.com.au/iptv/img/logo_tv5monde_s.gif<br />
2012-01-17 07:20:00,944 (-4faed000) :  INFO (__init__:42) - Found stream Playboy TV (rtp://@playboy.iptv.tpg.com.au:1234)<br />
2012-01-17 07:20:00,945 (-4faed000) :  INFO (__init__:48) - Thumb: http://www.tpg.com.au/iptv/img/logo_playboytv_s.gif<br />
2012-01-17 07:20:00,948 (-4faed000) :  DEBUG (runtime:678) - Response: 200




PMSLog

Jan 17, 2012 07:31:29 [0xb0b2b000] DEBUG - [com.plexapp.plugins.tpgtv] Plug-in running on port 64532.<br />
Jan 17, 2012 07:31:29 [0xb0b2b000] DEBUG -  * Plug-in handles prefix: /video/tpgtv<br />
Jan 17, 2012 07:31:29 [0xb0b2b000] DEBUG - Read configuration for [com.plexapp.plugins.tpgtv], had 1 prefixes<br />
Jan 17, 2012 07:31:29 [0xb0b2b000] DEBUG - [com.plexapp.plugins.tpgtv] Sending command over HTTP (GET): /video/tpgtv<br />
Jan 17, 2012 07:31:30 [0xb0b2b000] DEBUG - HTTP request to: http://127.0.0.1:64532/video/tpgtv<br />
Jan 17, 2012 07:31:30 [0xb0b2b000] DEBUG - [com.plexapp.plugins.tpgtv] HTTP reply status 200, with 1846 bytes of content.<br />
Jan 17, 2012 07:31:32 [0xb0c2f000] DEBUG - Request: GET /video/:/webkit?url=rtp%3A%2F%2F%40al-jazeera.iptv.tpg.com.au%3A1234&prefix=/video/tpgtv [127.0.0.1] (1 live)<br />
Jan 17, 2012 07:31:32 [0xb0c2f000] DEBUG -  * prefix => /video/tpgtv<br />
Jan 17, 2012 07:31:32 [0xb0c2f000] DEBUG - Found corresponding plug-in: /Users/mike/Library/Application Support/Plex Media Server/Plug-in Support/Data/com.plexapp.plugins.tpgtv

Thanks for your help everyone. I’ve discovered if I use UDP:// rather than RTP:// the stream works. Its very choppy, but now I get audio & video.



Ultimately I’d like to see native RTP streams handled in Plex, but alas, I guess there’s not the demand for it, and Elan and the other gods are busy bringing us this awesome media center without looking at spending too much on small requests from the community.

It works. Im happy!

http://wiki.plexapp.com/index.php/TPGTV

Could someone explain me what this addon is supposed to do? It fetches channels  from TPG and shows them in Plex Media Server, so what next? How to view them on Plex Player?

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.