def XML_PMS2aTV(PMSaddress, path, options): # double check aTV UDID, redo from client IP if needed/possible if not 'PlexConnectUDID' in options: UDID = getATVFromIP(options['aTVAddress']) if UDID: options['PlexConnectUDID'] = UDID else: declareATV(options['PlexConnectUDID'], options['aTVAddress']) # update with latest info # double check PMS IP address # the hope is: aTV sends either PMS address coded into URL or UDID in options if PMSaddress == '': if 'PlexConnectUDID' in options: UDID = options['PlexConnectUDID'] PMS_uuid = g_ATVSettings.getSetting(options['PlexConnectUDID'], 'pms_uuid') PMSaddress = PlexAPI.getPMSAddress(UDID, PMS_uuid) # this doesn't work any more, does it? is it really still used/needed? # check cmd to work on cmd = '' if 'PlexConnect' in options: cmd = options['PlexConnect'] dprint(__name__, 1, "PlexConnect Cmd: " + cmd) # check aTV language setting if not 'aTVLanguage' in options: dprint(__name__, 1, "no aTVLanguage - pick en") options['aTVLanguage'] = 'en' # discover! PlexGDM and MyPlex lookup - application just started on aTV UDID if path == '/PlexConnect.xml': UDID = options['PlexConnectUDID'] auth_token = g_ATVSettings.getSetting(UDID, 'myplex_auth') PlexAPI.discoverPMS(UDID, g_param['CSettings'], auth_token) # XML Template selector # - PlexConnect command # - path # - PMS ViewGroup XMLtemplate = '' PMS = None PMSroot = None # XML direct request or # XMLtemplate defined by solely PlexConnect Cmd if path.endswith(".xml"): XMLtemplate = path.lstrip('/') path = '' # clear path - we don't need PMS-XML elif cmd == 'Play': XMLtemplate = 'PlayVideo.xml' elif cmd == 'PlayVideo_ChannelsV1': dprint(__name__, 1, "playing Channels XML Version 1: {0}".format(path)) UDID = options['PlexConnectUDID'] PMS_uuid = PlexAPI.getPMSFromAddress(UDID, PMSaddress) 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 elif cmd == 'PhotoBrowser': XMLtemplate = 'Photo_Browser.xml' elif cmd == 'MoviePreview': XMLtemplate = 'MoviePreview.xml' elif cmd == 'MoviePrePlay': XMLtemplate = 'MoviePrePlay.xml' elif cmd == 'EpisodePrePlay': XMLtemplate = 'EpisodePrePlay.xml' elif cmd == 'ChannelPrePlay': XMLtemplate = 'ChannelPrePlay.xml' elif cmd == 'ChannelsVideo': XMLtemplate = 'ChannelsVideo.xml' elif cmd == 'ByFolder': XMLtemplate = 'ByFolder.xml' elif cmd == 'MovieSection': XMLtemplate = 'MovieSection.xml' elif cmd == 'TVSection': XMLtemplate = 'TVSection.xml' elif cmd.find('SectionPreview') != -1: XMLtemplate = cmd + '.xml' elif cmd == 'AllMovies': XMLtemplate = 'Movie_' + g_ATVSettings.getSetting( options['PlexConnectUDID'], 'movieview') + '.xml' elif cmd == 'MovieSecondary': XMLtemplate = 'MovieSecondary.xml' elif cmd == 'AllShows': XMLtemplate = 'Show_' + g_ATVSettings.getSetting( options['PlexConnectUDID'], 'showview') + '.xml' elif cmd == 'TVSecondary': XMLtemplate = 'TVSecondary.xml' elif cmd == 'PhotoSecondary': XMLtemplate = 'PhotoSecondary.xml' elif cmd == 'Directory': XMLtemplate = 'Directory.xml' elif cmd == 'DirectoryWithPreview': XMLtemplate = 'DirectoryWithPreview.xml' elif cmd == 'DirectoryWithPreviewActors': XMLtemplate = 'DirectoryWithPreviewActors.xml' elif cmd == 'Settings': XMLtemplate = 'Settings.xml' path = '' # clear path - we don't need PMS-XML elif cmd == 'SettingsVideoOSD': XMLtemplate = 'Settings_VideoOSD.xml' path = '' # clear path - we don't need PMS-XML elif cmd == 'SettingsMovies': XMLtemplate = 'Settings_Movies.xml' path = '' # clear path - we don't need PMS-XML elif cmd == 'SettingsTVShows': XMLtemplate = 'Settings_TVShows.xml' path = '' # clear path - we don't need PMS-XML elif cmd.startswith('SettingsToggle:'): opt = cmd[len('SettingsToggle:'):] # cut command: parts = opt.split('+') g_ATVSettings.toggleSetting(options['PlexConnectUDID'], parts[0].lower()) XMLtemplate = parts[1] + ".xml" dprint(__name__, 2, "ATVSettings->Toggle: {0} in template: {1}", parts[0], parts[1]) path = '' # clear path - we don't need PMS-XML elif cmd == ('MyPlexLogin'): dprint(__name__, 2, "MyPlex->Logging In...") if not 'PlexConnectCredentials' in options: return XML_Error('PlexConnect', 'MyPlex Sign In called without Credentials.') parts = options['PlexConnectCredentials'].split(':', 1) (username, auth_token) = PlexAPI.MyPlexSignIn(parts[0], parts[1], options) UDID = options['PlexConnectUDID'] g_ATVSettings.setSetting(UDID, 'myplex_user', username) g_ATVSettings.setSetting(UDID, 'myplex_auth', auth_token) XMLtemplate = 'Settings.xml' path = '' # clear path - we don't need PMS-XML elif cmd == 'MyPlexLogout': dprint(__name__, 2, "MyPlex->Logging Out...") UDID = options['PlexConnectUDID'] auth_token = g_ATVSettings.getSetting(UDID, 'myplex_auth') PlexAPI.MyPlexSignOut(auth_token) g_ATVSettings.setSetting(UDID, 'myplex_user', '') g_ATVSettings.setSetting(UDID, 'myplex_auth', '') XMLtemplate = 'Settings.xml' path = '' # clear path - we don't need PMS-XML elif cmd.startswith('Discover'): UDID = options['PlexConnectUDID'] auth_token = g_ATVSettings.getSetting(UDID, 'myplex_auth') PlexAPI.discoverPMS(UDID, g_param['CSettings'], auth_token) XMLtemplate = 'Settings.xml' path = '' # clear path - we don't need PMS-XML elif path.startswith('/search?'): XMLtemplate = 'Search_Results.xml' elif path == '/library/sections': XMLtemplate = 'Library.xml' path = '' elif path == '/channels/all': XMLtemplate = 'Channels.xml' path = '' # request PMS XML if not path == '': if 'PlexConnectUDID' in options: UDID = options['PlexConnectUDID'] PMS_uuid = PlexAPI.getPMSFromAddress(UDID, PMSaddress) auth_token = PlexAPI.getPMSProperty(UDID, PMS_uuid, 'accesstoken') else: auth_token = '' PMS = PlexAPI.getXMLFromPMS('http://' + PMSaddress, path, options, authtoken=auth_token) if PMS == False: return XML_Error('PlexConnect', 'No Response from Plex Media Server') PMSroot = PMS.getroot() dprint(__name__, 1, "viewGroup: " + PMSroot.get('ViewGroup', 'None')) # XMLtemplate defined by PMS XML content if path == '': pass # nothing to load elif not XMLtemplate == '': pass # template already selected elif PMSroot.get('viewGroup', '') == "secondary" and ( PMSroot.get('art', '').find('movie') != -1 or PMSroot.get('thumb', '').find('movie') != -1): XMLtemplate = 'MovieSectionTopLevel.xml' elif PMSroot.get('viewGroup', '') == "secondary" and ( PMSroot.get('art', '').find('show') != -1 or PMSroot.get('thumb', '').find('show') != -1): XMLtemplate = 'TVSectionTopLevel.xml' elif PMSroot.get('viewGroup', '') == "secondary" and ( PMSroot.get('art', '').find('photo') != -1 or PMSroot.get('thumb', '').find('photo') != -1): XMLtemplate = 'PhotoSectionTopLevel.xml' elif PMSroot.get('viewGroup', '') == "secondary": XMLtemplate = 'Directory.xml' elif PMSroot.get('viewGroup', '') == 'show': if PMSroot.get('title2') == 'By Folder': # By Folder View XMLtemplate = 'ByFolder.xml' else: # TV Show grid view XMLtemplate = 'Show_' + g_ATVSettings.getSetting( options['PlexConnectUDID'], 'showview') + '.xml' elif PMSroot.get('viewGroup', '') == 'season': # TV Season view XMLtemplate = 'Season_' + g_ATVSettings.getSetting( options['PlexConnectUDID'], 'seasonview') + '.xml' elif PMSroot.get('viewGroup', '') == 'movie': if PMSroot.get('title2') == 'By Folder': # By Folder View XMLtemplate = 'ByFolder.xml' else: # Movie listing XMLtemplate = 'Movie_' + g_ATVSettings.getSetting( options['PlexConnectUDID'], 'movieview') + '.xml' elif PMSroot.get('viewGroup', '') == 'track': XMLtemplate = 'Music_Track.xml' elif PMSroot.get('viewGroup', '') == 'episode': if PMSroot.get('title2')=='On Deck' or \ PMSroot.get('title2')=='Recently Viewed Episodes' or \ PMSroot.get('title2')=='Recently Aired' or \ PMSroot.get('title2')=='Recently Added': # TV On Deck View XMLtemplate = 'TV_OnDeck.xml' else: # TV Episode view XMLtemplate = 'Episode.xml' elif PMSroot.get('viewGroup', '') == 'photo': # Photo listing XMLtemplate = 'Photo.xml' else: XMLtemplate = 'Directory.xml' dprint(__name__, 1, "XMLTemplate: " + XMLtemplate) # get XMLtemplate aTVTree = etree.parse(sys.path[0] + '/assets/templates/' + XMLtemplate) aTVroot = aTVTree.getroot() # convert PMS XML to aTV XML using provided XMLtemplate global g_CommandCollection g_CommandCollection = CCommandCollection(options, PMSroot, PMSaddress, path) XML_ExpandTree(aTVroot, PMSroot, 'main') XML_ExpandAllAttrib(aTVroot, PMSroot, 'main') del g_CommandCollection dprint(__name__, 1, "====== generated aTV-XML ======") dprint(__name__, 1, prettyXML(aTVTree)) dprint(__name__, 1, "====== aTV-XML finished ======") return etree.tostring(aTVroot)
def XML_PMS2aTV(PMS_baseURL, path, options): # double check aTV UDID, redo from client IP if needed/possible if not 'PlexConnectUDID' in options: UDID = getATVFromIP(options['aTVAddress']) if UDID: options['PlexConnectUDID'] = UDID else: declareATV(options['PlexConnectUDID'], options['aTVAddress']) # update with latest info # check cmd to work on cmd = '' if 'PlexConnect' in options: cmd = options['PlexConnect'] dprint(__name__, 1, "PlexConnect Cmd: " + cmd) # check aTV language setting if not 'aTVLanguage' in options: dprint(__name__, 1, "no aTVLanguage - pick en") options['aTVLanguage'] = 'en' # XML Template selector # - PlexConnect command # - path # - PMS ViewGroup XMLtemplate = '' PMS = None PMSroot = None # XML direct request or # XMLtemplate defined by solely PlexConnect Cmd if path.endswith(".xml"): XMLtemplate = path.lstrip('/') path = '' # clear path - we don't need PMS-XML elif cmd == 'Play': XMLtemplate = 'PlayVideo.xml' elif cmd == 'PlayVideo_ChannelsV1': dprint(__name__, 1, "playing Channels XML Version 1: {0}".format(path)) UDID = options['PlexConnectUDID'] PMS_uuid = PlexAPI.getPMSFromAddress(UDID, PMS_baseURL) auth_token = PlexAPI.getPMSProperty(UDID, PMS_uuid, 'accesstoken') path = PlexAPI.getDirectVideoPath(path, auth_token) return XML_PlayVideo_ChannelsV1( PMS_baseURL, path) # direct link, no PMS XML available elif cmd == 'PlayTrailer': trailerID = options['PlexConnectTrailerID'] info = urllib2.urlopen("http://youtube.com/get_video_info?video_id=" + trailerID).read() parsed = urlparse.parse_qs(info) key = 'url_encoded_fmt_stream_map' if not key in parsed: return XML_Error('PlexConnect', 'Youtube: No Trailer Info available') streams = parsed[key][0].split(',') url = '' for i in range(len(streams)): stream = urlparse.parse_qs(streams[i]) if stream['itag'][0] == '18': url = stream['url'][0] + '&signature=' + stream['sig'][0] if url == '': return XML_Error('PlexConnect', 'Youtube: ATV compatible Trailer not available') return XML_PlayVideo_ChannelsV1('', url.replace('&', '&')) elif cmd == 'PhotoBrowser': XMLtemplate = 'Photo_Browser.xml' elif cmd == 'MoviePreview': XMLtemplate = 'MoviePreview.xml' elif cmd == 'MoviePrePlay': XMLtemplate = 'MoviePrePlay.xml' elif cmd == 'EpisodePrePlay': XMLtemplate = 'EpisodePrePlay.xml' elif cmd == 'ChannelPrePlay': XMLtemplate = 'ChannelPrePlay.xml' elif cmd == 'ChannelsVideo': XMLtemplate = 'ChannelsVideo.xml' elif cmd == 'ByFolder': XMLtemplate = 'ByFolder.xml' elif cmd == 'MovieSection': XMLtemplate = 'MovieSection.xml' elif cmd == 'TVSection': XMLtemplate = 'TVSection.xml' elif cmd.find('SectionPreview') != -1: XMLtemplate = cmd + '.xml' elif cmd == 'AllMovies': XMLtemplate = 'Movie_' + g_ATVSettings.getSetting( options['PlexConnectUDID'], 'movieview').replace(' ', '') + '.xml' elif cmd == 'MovieSecondary': XMLtemplate = 'MovieSecondary.xml' elif cmd == 'AllShows': XMLtemplate = 'Show_' + g_ATVSettings.getSetting( options['PlexConnectUDID'], 'showview') + '.xml' elif cmd == 'TVSecondary': XMLtemplate = 'TVSecondary.xml' elif cmd == 'PhotoSecondary': XMLtemplate = 'PhotoSecondary.xml' elif cmd == 'Directory': XMLtemplate = 'Directory.xml' elif cmd == 'DirectoryWithPreview': XMLtemplate = 'DirectoryWithPreview.xml' elif cmd == 'DirectoryWithPreviewActors': XMLtemplate = 'DirectoryWithPreviewActors.xml' elif cmd == 'Settings': XMLtemplate = 'Settings.xml' path = '' # clear path - we don't need PMS-XML elif cmd == 'SettingsVideoOSD': XMLtemplate = 'Settings_VideoOSD.xml' path = '' # clear path - we don't need PMS-XML elif cmd == 'SettingsMovies': XMLtemplate = 'Settings_Movies.xml' path = '' # clear path - we don't need PMS-XML elif cmd == 'SettingsTVShows': XMLtemplate = 'Settings_TVShows.xml' path = '' # clear path - we don't need PMS-XML elif cmd.startswith('SettingsToggle:'): opt = cmd[len('SettingsToggle:'):] # cut command: parts = opt.split('+') g_ATVSettings.toggleSetting(options['PlexConnectUDID'], parts[0].lower()) XMLtemplate = parts[1] + ".xml" dprint(__name__, 2, "ATVSettings->Toggle: {0} in template: {1}", parts[0], parts[1]) path = '' # clear path - we don't need PMS-XML elif cmd == ('MyPlexLogin'): dprint(__name__, 2, "MyPlex->Logging In...") if not 'PlexConnectCredentials' in options: return XML_Error('PlexConnect', 'MyPlex Sign In called without Credentials.') parts = options['PlexConnectCredentials'].split(':', 1) (username, auth_token) = PlexAPI.MyPlexSignIn(parts[0], parts[1], options) UDID = options['PlexConnectUDID'] g_ATVSettings.setSetting(UDID, 'myplex_user', username) g_ATVSettings.setSetting(UDID, 'myplex_auth', auth_token) XMLtemplate = 'Settings.xml' path = '' # clear path - we don't need PMS-XML elif cmd == 'MyPlexLogout': dprint(__name__, 2, "MyPlex->Logging Out...") UDID = options['PlexConnectUDID'] auth_token = g_ATVSettings.getSetting(UDID, 'myplex_auth') PlexAPI.MyPlexSignOut(auth_token) g_ATVSettings.setSetting(UDID, 'myplex_user', '') g_ATVSettings.setSetting(UDID, 'myplex_auth', '') XMLtemplate = 'Settings.xml' path = '' # clear path - we don't need PMS-XML elif cmd.startswith('Discover'): UDID = options['PlexConnectUDID'] auth_token = g_ATVSettings.getSetting(UDID, 'myplex_auth') PlexAPI.discoverPMS(UDID, g_param['CSettings'], auth_token) return XML_Error( 'PlexConnect', 'Discover!') # not an error - but aTV won't care anyways. elif path.startswith('/search?'): XMLtemplate = 'Search_Results.xml' elif path == '/library/sections': # from PlexConnect.xml -> for //local, //myplex XMLtemplate = 'Library.xml' elif path == '/channels/all': XMLtemplate = 'Channel_' + g_ATVSettings.getSetting( options['PlexConnectUDID'], 'channelview') + '.xml' path = '' # request PMS XML if not path == '': if 'PlexConnectUDID' in options: UDID = options['PlexConnectUDID'] PMS_uuid = PlexAPI.getPMSFromAddress(UDID, PMS_baseURL) auth_token = PlexAPI.getPMSProperty(UDID, PMS_uuid, 'accesstoken') else: auth_token = '' if PMS_baseURL.startswith('//'): # //local, //myplex UDID = options['PlexConnectUDID'] type = PMS_baseURL[2:] PMS = PlexAPI.getXMLFromMultiplePMS(UDID, path, type, options) else: PMS = PlexAPI.getXMLFromPMS(PMS_baseURL, path, options, authtoken=auth_token) if PMS == False: return XML_Error('PlexConnect', 'No Response from Plex Media Server') PMSroot = PMS.getroot() dprint(__name__, 1, "viewGroup: " + PMSroot.get('ViewGroup', 'None')) # XMLtemplate defined by PMS XML content if path == '': pass # nothing to load elif not XMLtemplate == '': pass # template already selected elif PMSroot.get('viewGroup', '') == "secondary" and ( PMSroot.get('art', '').find('movie') != -1 or PMSroot.get('thumb', '').find('movie') != -1): XMLtemplate = 'MovieSectionTopLevel.xml' elif PMSroot.get('viewGroup', '') == "secondary" and ( PMSroot.get('art', '').find('show') != -1 or PMSroot.get('thumb', '').find('show') != -1): XMLtemplate = 'TVSectionTopLevel.xml' elif PMSroot.get('viewGroup', '') == "secondary" and ( PMSroot.get('art', '').find('photo') != -1 or PMSroot.get('thumb', '').find('photo') != -1): XMLtemplate = 'PhotoSectionTopLevel.xml' elif PMSroot.get('viewGroup', '') == "secondary": XMLtemplate = 'Directory.xml' elif PMSroot.get('viewGroup', '') == 'show': if PMSroot.get('title2') == 'By Folder': # By Folder View XMLtemplate = 'ByFolder.xml' else: # TV Show grid view XMLtemplate = 'Show_' + g_ATVSettings.getSetting( options['PlexConnectUDID'], 'showview') + '.xml' elif PMSroot.get('viewGroup', '') == 'season': # TV Season view XMLtemplate = 'Season_' + g_ATVSettings.getSetting( options['PlexConnectUDID'], 'seasonview') + '.xml' elif PMSroot.get('viewGroup', '') == 'movie': if PMSroot.get('title2') == 'By Folder': # By Folder View XMLtemplate = 'ByFolder.xml' else: # Movie listing XMLtemplate = 'Movie_' + g_ATVSettings.getSetting( options['PlexConnectUDID'], 'movieview').replace(' ', '') + '.xml' elif PMSroot.get('viewGroup', '') == 'track': XMLtemplate = 'Music_Track.xml' elif PMSroot.get('viewGroup', '') == 'episode': if PMSroot.get('title2')=='On Deck' or \ PMSroot.get('title2')=='Recently Viewed Episodes' or \ PMSroot.get('title2')=='Recently Aired' or \ PMSroot.get('title2')=='Recently Added': # TV On Deck View XMLtemplate = 'TV_OnDeck.xml' else: # TV Episode view XMLtemplate = 'Episode.xml' elif PMSroot.get('viewGroup', '') == 'photo': # Photo listing XMLtemplate = 'Photo.xml' else: XMLtemplate = 'Directory.xml' dprint(__name__, 1, "XMLTemplate: " + XMLtemplate) # get XMLtemplate aTVTree = etree.parse(sys.path[0] + '/assets/templates/' + XMLtemplate) aTVroot = aTVTree.getroot() # convert PMS XML to aTV XML using provided XMLtemplate global g_CommandCollection g_CommandCollection = CCommandCollection(options, PMSroot, PMS_baseURL, path) XML_ExpandTree(aTVroot, PMSroot, 'main') XML_ExpandAllAttrib(aTVroot, PMSroot, 'main') del g_CommandCollection dprint(__name__, 1, "====== generated aTV-XML ======") dprint(__name__, 1, prettyXML(aTVTree)) dprint(__name__, 1, "====== aTV-XML finished ======") return etree.tostring(aTVroot)