Plugin Help!

FromSport.com
Ok. Moving my questions to a dedicated topic.

I think I've got the basics figured out, except XPath and how to navigate my way through the objects that are created, etc.

Also, my site configuration. But one step at a time.


I am able to pull out rows of a table that hold the links/info I need. First: I haven't been able to figure out how to cycle through the columns of each row item. Next: It appears that the title of the video (in one of the columns) is generated through a script so I'm not sure how to turn that into a usable form.

Something like



<br />
foreach row in context.xpath('//table/tr'):<br />
    columns = row.xpath('./td')<br />
    title = columns[0].text<br />
    etc<br />




maybe?

Or (just looked at the site)



<br />
foreach row in content.xpath('//table/tr'):<br />
    title = row.xpath('./td[@class="list_champ"]')[0].text<br />
    thumb = row.xpath('./td[@class="list_flag"]/img')[0].get('src')<br />
<br />
   etc.<br />


As for the title, it’s in an escaped string. Try pasting an example http://www.linkedresources.com/tools/unescaper_v0.2b1.html and unescape.



In the plugin, extract out the escaped string using standard python string commands and then use String.Unquote from the PMS framework to get the actual string.



Jonny

I will have to look into the escaped string. The others are working fine except a few. When trying to do



<br />
row.xpath('./td[@class="list_ball"]/img')[0].get('src')<br />




I am getting 'list index out of range' - can you explain what having the [0] outside of the xpath call is doing (or should be doing)?





EDIT:
NM: was missing an 'a' tag - should be row.xpath('./td[@class="list_ball"]/a/img')[0].get('src')

I’m trying to use string.replace(‘replacethis’, ‘withthis’) to manipulate the escaped string but not having any success. I’m I headed in the best direction with that?

Wow… I figured it out… it’s getting late, need to call it a night.



Thanks for the help, all. Be back to finish tomorrow.



You could use './td[@class="list_ball"]//img' (note the // ) that would cause xpath to skip all intermediate elements. xpath is always returning and array, even if there is only one element hence the need for the [0]

Awesome. figured out the escaped string and have all my menus populating.



For those interested, here is what I currently have:


<br />
# PMS plugin framework<br />
from PMS import *<br />
from PMS.Objects import *<br />
from PMS.Shortcuts import *<br />
import re, string, datetime<br />
######<br />
#TODO: <br />
	# 'Country' SubMenu<br />
	# 'League' SubMenu<br />
		# BOTH?<br />
	# Sort (view might need to change so this is intuitive)<br />
	# Adjust times to a time-zone preference<br />
######<br />
####################################################################################################<br />
VIDEO_PREFIX 	= "/video/fromsport"<br />
PAGE_ROOT 		= "http://www.fromsport.com/"<br />
<br />
FOOTBALL		= "http://www.fromsport.com/c-1.html"<br />
HOCKEY			= "http://www.fromsport.com/c-3.html"<br />
TENNIS			= "http://www.fromsport.com/c-4.html"<br />
BASKETBALL	= "http://www.fromsport.com/c-6.html"<br />
BASEBALL		= "http://www.fromsport.com/c-7.html"<br />
GOLF				= "http://www.fromsport.com/c-8.html"<br />
CYCLING			= "http://www.fromsport.com/c-9.html"<br />
MOTORSPORTS	= "http://www.fromsport.com/c-10.html"<br />
OTHER				= "http://www.fromsport.com/c-11.html"<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.png'<br />
ICON			= 'icon-default.png'<br />
<br />
####################################################################################################<br />
<br />
def Start():<br />
	Plugin.AddPrefixHandler(VIDEO_PREFIX, MainMenu, "FromSport", ICON, ART)<br />
<br />
	Plugin.AddViewGroup("InfoList", viewMode = "InfoList", mediaType = "items")<br />
	Plugin.AddViewGroup("List", viewMode = "List", mediaType = "items")<br />
<br />
	MediaContainer.art = R(ART)<br />
	MediaContainer.title1 = NAME<br />
	DirectoryItem.thumb = R(ICON)<br />
<br />
def MainMenu():<br />
	dir = MediaContainer(viewGroup = "InfoList")<br />
	dir.Append(Function(DirectoryItem(VideoPage,"HOME",subtitle = "",summary = "",thumb = R(ICON),art = R(ART)),pageUrl = PAGE_ROOT))<br />
	dir.Append(Function(DirectoryItem(VideoPage,"Football",subtitle = "GOOOOOAAAAAAAAAALLLLLLLLLL!!!!!!",summary = "",thumb = R(ICON),art = R(ART)),pageUrl = FOOTBALL))<br />
	dir.Append(Function(DirectoryItem(VideoPage,"Hockey",subtitle = "pucks n' stuff",summary = "",thumb = R(ICON),art = R(ART)),pageUrl = HOCKEY))<br />
	dir.Append(Function(DirectoryItem(VideoPage,"Tennis",subtitle = "Ace!",summary = "",thumb = R(ICON),art = R(ART)),pageUrl = TENNIS))<br />
	dir.Append(Function(DirectoryItem(VideoPage,"Basketball",subtitle = "at the buzzer....",summary = "",thumb = R(ICON),art = R(ART)),pageUrl = BASKETBALL))<br />
	dir.Append(Function(DirectoryItem(VideoPage,"Baseball",subtitle = "Strike 3!",summary = "",thumb = R(ICON),art = R(ART)),pageUrl = BASEBALL))<br />
	dir.Append(Function(DirectoryItem(VideoPage,"Golf",subtitle = "FORE!",summary = "",thumb = R(ICON),art = R(ART)),pageUrl = GOLF))<br />
	dir.Append(Function(DirectoryItem(VideoPage,"Cycling",subtitle = "Push it",summary = "",thumb = R(ICON),art = R(ART)),pageUrl = CYCLING))<br />
	dir.Append(Function(DirectoryItem(VideoPage,"Motorsports",subtitle = "Vroom",summary = "",thumb = R(ICON),art = R(ART)),pageUrl = MOTORSPORTS))<br />
	dir.Append(Function(DirectoryItem(VideoPage,"Other",subtitle = "Uhhh..",summary = "",thumb = R(ICON),art = R(ART)),pageUrl = OTHER))<br />
	return dir<br />
<br />
def VideoPage(sender, pageUrl):<br />
	dir = MediaContainer(title2 = sender.itemTitle)<br />
	Log("Scraping " + pageUrl)<br />
	content = XML.ElementFromURL(pageUrl, isHTML = True)<br />
<br />
	for row in content.xpath('//table//tr'):<br />
		#un-escape the team names<br />
		teams = row.xpath('./td[@class="list_team"]/a/script')[0].text<br />
		teams = teams.replace("document.write(unescape('", "")<br />
		teams = teams.replace("'))", "")<br />
		teams = String.Unquote(teams)<br />
		teams = teams.replace(";", "")<br />
		<br />
		dateTime = row.xpath('./td[@class="list_date"]')[0].text<br />
		sport = row.xpath('./td[@class="list_ball"]/a/img')[0].get('alt')<br />
		country = row.xpath('./td[@class="list_flag"]/img')[0].get('alt')<br />
		league = row.xpath('./td[@class="list_champ"]')[0].text<br />
		vidLink = row.xpath('./td[@class="list_team"]/a')[0].get('href')<br />
		sportPic = row.xpath('./td[@class="list_ball"]/a/img')[0].get('src')				#TODO - find better picture options<br />
		countryPic = row.xpath('./td[@class="list_flag"]/img')[0].get('src')<br />
		<br />
		title = teams + " (" + league + ")"<br />
		subtitle = country + " " + sport + " @ " + dateTime<br />
		link = vidLink<br />
		thumb = sportPic<br />
		<br />
		dir.Append(WebVideoItem(link, subtitle = subtitle, title = title, thumb = thumb))<br />
	return dir<br />
<br />
<br />









Now on to the site configuration so that they will play.

When I first looked at this site, the videos I looked at all used the same flash plugin. Today, with new videos I'm finding that they may actually be using more than one. Is it possible to set up the site configuration using multiple flash plugins?

Yep, just have multiple site config files, one for each player. The Daily Show does this for clips vs full episodes.




Okay, working on my first configuration for this video: http://www.fromsport.com/v-0/18/2/v-180373.html



I found that it’s a Justin.TV plugin so my site configuration looks like this (copied from MTV and modified):


<br />
<?xml version="1.0" encoding="UTF-8"?><br />
<site site="http:/www.fromsport.com"<br />
	    plugin="http://www.justin.tv/widgets/live_embed_player.swf"<br />
			initialState="playing"<br />
			version="1.0"><br />
	<br />
	<crop x="0" y="0" width="560" height="400" /><br />
	<seekbar type="simple"><br />
		<start x="69" y="402" /><br />
		<end   x="479" y="402" /><br />
		<played><br />
				<color rgb="666666" /><br />
		</played><br />
	</seekbar><br />
<br />
</site><br />




When trying to open the video in Plex I get 'Error while opening file'

Any plugin devs?

I’ve seen I happen for a number of reasons but usually a typo in the site address or the plugin is the culprit. Also try using wildcards to make it more robust to changes.

I checked the url you gave (http://www.fromsport.com/v-0/18/2/v-180373.html) but I do not see the Flashplayer from your site config (http:****//www.justin.tv/widgets/live_embed_player.swf) anywhere on that page… Also, you initialState is set to “playing”, but that state is missing from your site config.



The video was live, so it is over now. The flashplayer showed up when I 'inspect element' in Chrome or Firefox but not directly in the source (pulled from a script, I believe... does that still work?) While the others might not use the justin.tv player, you should be able to look at other videos to see how they work.




If the initial state is playing, what does the state need to do? Doesn't that just say that the video is playing when the page is opened?

You don’t have ANY Tags. I don’t think it’ll work at all unless you have at least one.



http://wiki.plexapp.com/index.php/Creating_Plugins_Site_Config#.3Cstate.3E_Tag


Yes, for site configs that's fine.


Even if there's nothing to do (because the site config is for live stream for example), there needs to be at least one state. It doesn't necessarily have to be named "playing", but the state machine needs to be in *a* state.

For a live stream you can have something live this:

<br />
	<state name="playing"><br />
		<event><br />
			<condition><br />
				<frameLoaded /><br />
			</condition><br />
			<action><br />
				<!-- nothing to do here --><br />
			</action><br />
		</event><br />
	</state><br />


The way I understand it is as a state machine; the player is in a certain state and events (both user generated and stream generated) are detected that transition the player to another state. The site config file configures all the states and transitions you need to control playback. The initialState parameter you mentioned specifies which state the state machine starts in. As such, that state needs to be defined in the configuration file.



Jonny


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