Skip to content

Commit

Permalink
poke MyPlex PMS before registering. add 'scheme' to PlexAPI. use 'bas…
Browse files Browse the repository at this point in the history
…eURL' instead of 'PMSaddress' (PlexAPI, PlayVideo - todo: XMLConverter cleanup)
  • Loading branch information
iBaa committed Nov 6, 2013
1 parent a2f87db commit 7bd7b27
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 35 deletions.
46 changes: 30 additions & 16 deletions PlexAPI.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,18 +59,22 @@
parameters:
ATV_udid
uuid - PMS ID
name, ip, port, type, token
name, scheme, ip, port, type, owned, token
"""
def declarePMS(ATV_udid, uuid, name, ip, port, type, token):
def declarePMS(ATV_udid, uuid, name, scheme, ip, port, type, owned, token):
# store PMS information in g_PMS database
global g_PMS
if not ATV_udid in g_PMS:
g_PMS[ATV_udid] = {}

address = ip + ':' + port
baseURL = scheme+'://'+ip+':'+port
g_PMS[ATV_udid][uuid] = { 'name': name,
'ip': ip , 'port': port, 'address': address,
'scheme':scheme, 'ip': ip , 'port': port,
'address': address,
'baseURL': baseURL,
'type': type,
'owned': owned,
'accesstoken': token
}

Expand Down Expand Up @@ -98,7 +102,7 @@ def getPMSFromAddress(ATV_udid, address):
return '' # no server known for this aTV

for uuid in g_PMS[ATV_udid]:
if address==g_PMS[ATV_udid][uuid].get('address', None):
if address in g_PMS[ATV_udid][uuid].get('baseURL', None):
return uuid
return '' # IP not found

Expand Down Expand Up @@ -220,8 +224,8 @@ def discoverPMS(ATV_udid, CSettings, MyPlexToken=''):
g_PMS[ATV_udid] = {}

#debug
#declarePMS(ATV_udid, '2ndServer', '2ndServer', '192.168.178.22', '32400', 'local', 'token')
#declarePMS(ATV_udid, 'remoteServer', 'remoteServer', '127.0.0.1', '1234', 'remote', 'token')
#declarePMS(ATV_udid, '2ndServer', '2ndServer', 'http', '192.168.178.22', '32400', 'local', '1', 'token')
#declarePMS(ATV_udid, 'remoteServer', 'remoteServer', 'http', '127.0.0.1', '1234', 'myplex', '1', 'token')
#debug

# local PMS
Expand All @@ -238,14 +242,14 @@ def discoverPMS(ATV_udid, CSettings, MyPlexToken=''):
uuid = Server.get('machineIdentifier')
name = Server.get('name')

declarePMS(ATV_udid, uuid, name, ip, port, 'local', '')
declarePMS(ATV_udid, uuid, name, 'http', ip, port, 'local', '', '')

else:
# PlexGDM
PMS_list = PlexGDM()
for uuid in PMS_list:
PMS = PMS_list[uuid]
declarePMS(ATV_udid, PMS['uuid'], PMS['serverName'], PMS['ip'], PMS['port'], 'local', '')
declarePMS(ATV_udid, PMS['uuid'], PMS['serverName'], 'http', PMS['ip'], PMS['port'], 'local', '', '')

# MyPlex servers
if not MyPlexToken=='':
Expand All @@ -257,20 +261,29 @@ def discoverPMS(ATV_udid, CSettings, MyPlexToken=''):
for Dir in XML.getiterator('Server'):
uuid = Dir.get('machineIdentifier')
name = Dir.get('name')
scheme = Dir.get('scheme')
ip = Dir.get('address')
port = Dir.get('port')
token = Dir.get('accessToken', '')
owned = Dir.get('owned', '0')

# check MyPlex data age - skip if >2 days
infoAge = time.time() - int(Dir.get('updatedAt'))
oneDayInSec = 60*60*24
if infoAge > 2*oneDayInSec: # two days in seconds -> expiration in setting?
dprint(__name__, 1, "Server {0} not updated for {1} days - skipping.", name, infoAge/oneDayInSec)
continue

# poke PMS - skip if not accessible
PMS = getXMLFromPMS(scheme+'://'+ip+':'+port, '/', None, token)
if PMS==False:
continue

if not uuid in g_PMS.get(ATV_udid, {}):
declarePMS(ATV_udid, uuid, name, ip, port, 'myplex', token)
declarePMS(ATV_udid, uuid, name, scheme, ip, port, 'myplex', owned, token)
else:
updatePMSProperty(ATV_udid, uuid, 'accesstoken', token)
updatePMSProperty(ATV_udid, uuid, 'owned', owned)

# debug print all servers
dprint(__name__, 0, "Servers (local+MyPlex): {0}", len(g_PMS[ATV_udid]))
Expand Down Expand Up @@ -302,7 +315,7 @@ def getXMLFromPMS(baseURL, path, options={}, authtoken=''):

request = urllib2.Request(baseURL+path , None, xargs)
try:
response = urllib2.urlopen(request)
response = urllib2.urlopen(request, timeout=10)
except urllib2.URLError as e:
dprint(__name__, 0, 'No Response from Plex Media Server')
if hasattr(e, 'reason'):
Expand Down Expand Up @@ -364,7 +377,8 @@ def getXMLFromMultiplePMS(ATV_udid, path, type, options={}):
Server.set('name', getPMSProperty(ATV_udid, uuid, 'name'))
Server.set('address', getPMSProperty(ATV_udid, uuid, 'ip'))
Server.set('port', getPMSProperty(ATV_udid, uuid, 'port'))
baseURL = 'http://' + getPMSAddress(ATV_udid, uuid)

baseURL = getPMSProperty(ATV_udid, uuid, 'baseURL')
token = getPMSProperty(ATV_udid, uuid, 'accesstoken')

PMSaddr = 'PMS(' + getPMSAddress(ATV_udid, uuid) + ')'
Expand Down Expand Up @@ -397,7 +411,7 @@ def getXMLFromMultiplePMS(ATV_udid, path, type, options={}):


def getURL(PMSaddress, path, key):
if key.startswith('http://'): # external server
if key.startswith('http://') or key.startswith('https://'): # external server
URL = key
elif key.startswith('/'): # internal full path.
URL = PMSaddress + key
Expand Down Expand Up @@ -565,7 +579,7 @@ def getTranscodeVideoPath(path, AuthToken, options, action, quality, settings):
final path to media file
"""
def getDirectVideoPath(key, AuthToken):
if key.startswith('http://'): # external address - keep
if key.startswith('http://') or key.startswith('https://'): # external address - keep
path = key
else:
if AuthToken=='':
Expand Down Expand Up @@ -595,10 +609,10 @@ def getDirectVideoPath(key, AuthToken):
final path to image file
"""
def getTranscodeImagePath(key, AuthToken, path, width, height):
if key.startswith('/'): # internal full path.
path = 'http://127.0.0.1:32400' + key
elif key.startswith('http://'): # external address - can we get a transcoding request for external images?
if key.startswith('http://') or key.startswith('https://'): # external address - can we get a transcoding request for external images?
path = key
elif key.startswith('/'): # internal full path.
path = 'http://127.0.0.1:32400' + key
else: # internal path, add-on
path = 'http://127.0.0.1:32400' + path + '/' + key

Expand Down
13 changes: 6 additions & 7 deletions XMLConverter.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,18 +75,19 @@ def XML_Error(title, desc):



def XML_PlayVideo_ChannelsV1(PMSaddress, path):
def XML_PlayVideo_ChannelsV1(baseURL, path):
XML = '\
<atv>\n\
<body>\n\
<videoPlayer id="com.sample.video-player">\n\
<httpFileVideoAsset id="' + path + '">\n\
<mediaURL>http://' + PMSaddress + path + '</mediaURL>\n\
<mediaURL>' + baseURL + path + '</mediaURL>\n\
<title>*title*</title>\n\
<!--bookmarkTime>{{EVAL(Video/viewOffset:0:int(x/1000))}}</bookmarkTime-->\n\
<myMetadata>\n\
<!-- PMS, OSD settings, ... -->\n\
<addrPMS>http://' + PMSaddress + '</addrPMS>\n\
<baseURL>' + baseURL + '</baseURL>\n\
<accessToken></accessToken>\n\
<key></key>\n\
<ratingKey></ratingKey>\n\
<duration></duration>\n\
Expand All @@ -95,7 +96,6 @@ def XML_PlayVideo_ChannelsV1(PMSaddress, path):
<clockPosition></clockPosition>\n\
<overscanAdjust></overscanAdjust>\n\
<showEndtime>False</showEndtime>\n\
<accessToken></accessToken>\n\
</myMetadata>\n\
</httpFileVideoAsset>\n\
</videoPlayer>\n\
Expand Down Expand Up @@ -189,9 +189,10 @@ def XML_PMS2aTV(PMSaddress, path, options):
dprint(__name__, 1, "playing Channels XML Version 1: {0}".format(path))
UDID = options['PlexConnectUDID']
PMS_uuid = PlexAPI.getPMSFromAddress(UDID, PMSaddress)
baseURL = PlexAPI.getPMSProperty(UDID, PMS_uuid, 'baseURL')
auth_token = PlexAPI.getPMSProperty(UDID, PMS_uuid, 'accesstoken')
path = PlexAPI.getDirectVideoPath(path, auth_token)
return XML_PlayVideo_ChannelsV1(PMSaddress, path) # direct link, no PMS XML available
return XML_PlayVideo_ChannelsV1(baseURL, path) # direct link, no PMS XML available

elif cmd=='PhotoBrowser':
XMLtemplate = 'Photo_Browser.xml'
Expand Down Expand Up @@ -1021,15 +1022,13 @@ def ATTRIB_MEDIAURL(self, src, srcXML, param):
res, leftover, dfltd = self.getKey(PMS.getroot(), srcXML, 'Video/Media/Part/key')

res = PlexAPI.getDirectVideoPath(res, AuthToken)
print "directplay"
else:
# request transcoding
res = Video.get('key','')

# misc settings: subtitlesize, audioboost
settings = ( g_ATVSettings.getSetting(UDID, 'subtitlesize'), \
g_ATVSettings.getSetting(UDID, 'audioboost') )
print "transcode"
res = PlexAPI.getTranscodeVideoPath(res, AuthToken, self.options, transcoderAction, qLimits, settings)

else:
Expand Down
23 changes: 13 additions & 10 deletions assets/js/application.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
// settings for atv.player - communicated in PlayVideo/myMetadata
var addrPMS;
var baseURL;
var accessToken;
var key;
var ratingKey;
var duration;
var showClock, timeFormat, clockPosition, overscanAdjust;
var showEndtime;
var accessToken;


// information for atv.player - computed internally to application.js
var lastReportedTime = -1;
Expand Down Expand Up @@ -47,7 +48,7 @@ atv.player.playerTimeDidChange = function(time)
var token = '';
if (accessToken!='')
token = '&X-Plex-Token=' + accessToken;
loadPage( addrPMS + '/:/timeline?ratingKey=' + ratingKey +
loadPage( baseURL + '/:/timeline?ratingKey=' + ratingKey +
'&key=' + key +
'&duration=' + duration +
'&state=playing' +
Expand All @@ -72,7 +73,7 @@ atv.player.didStopPlaying = function()
var token = '';
if (accessToken!='')
token = '&X-Plex-Token=' + accessToken;
loadPage( addrPMS + '/:/timeline?ratingKey=' + ratingKey +
loadPage( baseURL + '/:/timeline?ratingKey=' + ratingKey +
'&key=' + key +
'&duration=' + duration +
'&state=stopped' +
Expand All @@ -82,7 +83,7 @@ atv.player.didStopPlaying = function()
token );

// Kill the session.
loadPage(addrPMS + '/video/:/transcode/universal/stop?session=' + atv.device.udid);
loadPage(baseURL + '/video/:/transcode/universal/stop?session=' + atv.device.udid);
};

/*
Expand All @@ -96,19 +97,21 @@ atv.player.willStartPlaying = function()
var url = atv.player.asset.getElementByTagName('mediaURL').textContent;
var metadata = atv.player.asset.getElementByTagName('myMetadata');

// get addrPMS, OSD settings, ...
// get baseURL, OSD settings, ...
if (metadata != null)
{
addrPMS = metadata.getElementByTagName('addrPMS').textContent;
baseURL = metadata.getElementByTagName('baseURL').textContent;
accessToken = metadata.getElementByTagName('accessToken').textContent;

key = metadata.getElementByTagName('key').textContent;
ratingKey = metadata.getElementByTagName('ratingKey').textContent;
duration = metadata.getElementByTagName('duration').textContent;

showClock = metadata.getElementByTagName('showClock').textContent;
timeFormat = metadata.getElementByTagName('timeFormat').textContent;
clockPosition = metadata.getElementByTagName('clockPosition').textContent;
overscanAdjust = metadata.getElementByTagName('overscanAdjust').textContent;
showEndtime = metadata.getElementByTagName('showEndtime').textContent;
accessToken = metadata.getElementByTagName('accessToken').textContent;
}

// Use loadMoreAssets callback for playlists - if not transcoding!
Expand Down Expand Up @@ -204,7 +207,7 @@ atv.player.playerStateChanged = function(newState, timeIntervalSec) {
if (newState == 'Paused')
{
state = 'paused';
pingTimer = atv.setInterval(function() {loadPage( addrPMS + '/video/:/transcode/universal/ping?session=' +
pingTimer = atv.setInterval(function() {loadPage( baseURL + '/video/:/transcode/universal/ping?session=' +
atv.device.udid); }, 60000);
}

Expand All @@ -227,7 +230,7 @@ atv.player.playerStateChanged = function(newState, timeIntervalSec) {
var token = '';
if (accessToken!='')
token = '&X-Plex-Token=' + accessToken;
loadPage( addrPMS + '/:/timeline?ratingKey=' + ratingKey +
loadPage( baseURL + '/:/timeline?ratingKey=' + ratingKey +
'&key=' + key +
'&duration=' + duration +
'&state=' + state +
Expand Down
6 changes: 4 additions & 2 deletions assets/templates/PlayVideo.xml
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,18 @@

<myMetadata>
<!-- PMS, OSD settings, ... -->
<addrPMS>http://{{ADDR_PMS()}}</addrPMS>
<baseURL>{{VAL(%baseURL)}}</baseURL>
<accessToken>{{VAL(%accesstoken)}}</accessToken>

<key>{{VAL(Video/key)}}</key>
<ratingKey>{{VAL(Video/ratingKey)}}</ratingKey>
<duration>{{VAL(Video/duration)}}</duration>

<showClock>{{VAL($showplayerclock)}}</showClock>
<timeFormat>{{VAL($timeformat)}}</timeFormat>
<clockPosition>{{VAL($clockposition)}}</clockPosition>
<overscanAdjust>{{VAL($overscanadjust)}}</overscanAdjust>
<showEndtime>{{VAL($showendtime)}}</showEndtime>
<accessToken>{{VAL(%accesstoken)}}</accessToken>

<!-- stacked media -->
<httpFileVideoAsset id="{{VAL(key)}}">
Expand Down

0 comments on commit 7bd7b27

Please sign in to comment.