def hasAccess(self): # Plex: always return True for now return True # hasAccess is verified in service.py log = self.logMsg window = utils.window url = "{server}/emby/Users?format=json" result = self.doUtils.downloadUrl(url) if result == False: # Access is restricted, set in downloadutils.py via exception log("Access is restricted.", 1) self.HasAccess = False elif window('emby_online') != "true": # Server connection failed pass elif window('emby_serverStatus') == "restricted": log("Access is granted.", 1) self.HasAccess = True window('emby_serverStatus', clear=True) xbmcgui.Dialog().notification(self.addonName, utils.language(33007))
def singleNode(self, indexnumber, tagname, mediatype, itemtype): window = utils.window tagname = tagname.encode('utf-8') cleantagname = utils.normalize_nodes(tagname) nodepath = xbmc.translatePath( "special://profile/library/video/").decode('utf-8') nodeXML = "%splex_%s.xml" % (nodepath, cleantagname) path = "library://video/plex_%s.xml" % cleantagname windowpath = "ActivateWindow(Video,%s,return)" % path # Create the video node directory if not xbmcvfs.exists(nodepath): # We need to copy over the default items shutil.copytree( src=xbmc.translatePath( "special://xbmc/system/library/video").decode('utf-8'), dst=xbmc.translatePath( "special://profile/library/video").decode('utf-8')) xbmcvfs.exists(path) labels = { 'Favorite movies': 30180, 'Favorite tvshows': 30181, 'channels': 30173 } label = utils.language(labels[tagname]) embynode = "Emby.nodes.%s" % indexnumber window('%s.title' % embynode, value=label) window('%s.path' % embynode, value=windowpath) window('%s.content' % embynode, value=path) window('%s.type' % embynode, value=itemtype) if xbmcvfs.exists(nodeXML): # Don't recreate xml if already exists return if itemtype == "channels": root = self.commonRoot(order=1, label=label, tagname=tagname, roottype=2) etree.SubElement( root, 'path' ).text = "plugin://plugin.video.plexkodiconnect/?id=0&mode=channels" else: root = self.commonRoot(order=1, label=label, tagname=tagname) etree.SubElement(root, 'order', { 'direction': "ascending" }).text = "sorttitle" etree.SubElement(root, 'content').text = mediatype try: utils.indent(root) except: pass etree.ElementTree(root).write(nodeXML)
def singleNode(self, indexnumber, tagname, mediatype, itemtype): window = utils.window tagname = utils.tryEncode(tagname) cleantagname = utils.normalize_nodes(tagname) nodepath = utils.tryDecode(xbmc.translatePath( "special://profile/library/video/")) nodeXML = "%splex_%s.xml" % (nodepath, cleantagname) path = "library://video/plex_%s.xml" % cleantagname windowpath = "ActivateWindow(Video,%s,return)" % path # Create the video node directory if not xbmcvfs.exists(nodepath): # We need to copy over the default items shutil.copytree( src=utils.tryDecode(xbmc.translatePath( "special://xbmc/system/library/video")), dst=utils.tryDecode(xbmc.translatePath( "special://profile/library/video"))) xbmcvfs.exists(path) labels = { 'Favorite movies': 30180, 'Favorite tvshows': 30181, 'channels': 30173 } label = utils.language(labels[tagname]) embynode = "Emby.nodes.%s" % indexnumber window('%s.title' % embynode, value=label) window('%s.path' % embynode, value=windowpath) window('%s.content' % embynode, value=path) window('%s.type' % embynode, value=itemtype) if xbmcvfs.exists(nodeXML): # Don't recreate xml if already exists return if itemtype == "channels": root = self.commonRoot(order=1, label=label, tagname=tagname, roottype=2) etree.SubElement(root, 'path').text = "plugin://plugin.video.plexkodiconnect/?id=0&mode=channels" else: root = self.commonRoot(order=1, label=label, tagname=tagname) etree.SubElement(root, 'order', {'direction': "ascending"}).text = "sorttitle" etree.SubElement(root, 'content').text = mediatype try: utils.indent(root) except: pass etree.ElementTree(root).write(nodeXML)
def hasAccess(self): # hasAccess is verified in service.py window = utils.window result = self.doUtils.downloadUrl("{server}/emby/Users?format=json") if result == False: # Access is restricted, set in downloadutils.py via exception self.logMsg("Access is restricted.", 1) self.HasAccess = False elif window('emby_online') != "true": # Server connection failed pass elif window('emby_serverStatus') == "restricted": self.logMsg("Access is granted.", 1) self.HasAccess = True window('emby_serverStatus', clear=True) xbmcgui.Dialog().notification("Emby for Kodi", utils.language(33007))
def client_update(self): self.update_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP) update_sock = self.update_sock # Set socket reuse, may not work on all OSs. try: update_sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) except: pass # Attempt to bind to the socket to recieve and send data. If we cant # do this, then we cannot send registration try: update_sock.bind(('0.0.0.0', self.client_update_port)) except: log.error("Unable to bind to port [%s] - Plex Companion will not " "be registered. Change the Plex Companion update port!" % self.client_update_port) if settings('companion_show_gdm_port_warning') == 'true': if dialog( 'yesno', language(29999), 'Port %s' % self.client_update_port, language(39079), yeslabel=language(30013), # Never show again nolabel=language(30012)): # OK settings('companion_show_gdm_port_warning', value='false') from xbmc import executebuiltin executebuiltin( 'Addon.OpenSettings(plugin.video.plexkodiconnect)') return update_sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 255) update_sock.setsockopt( socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, socket.inet_aton(self._multicast_address) + socket.inet_aton('0.0.0.0')) update_sock.setblocking(0) # Send initial client registration self.register_as_client() # Now, listen format client discovery reguests and respond. while self._registration_is_running: try: data, addr = update_sock.recvfrom(1024) log.debug("Recieved UDP packet from [%s] containing [%s]" % (addr, data.strip())) except socket.error: pass else: if "M-SEARCH * HTTP/1." in data: log.debug("Detected client discovery request from %s. " " Replying" % str(addr)) try: update_sock.sendto( "HTTP/1.0 200 OK\n%s" % self.client_data, addr) except: log.error("Unable to send client update message") log.debug("Sending registration data HTTP/1.0 200 OK") self.client_registered = True sleep(500) log.info("Client Update loop stopped") # When we are finished, then send a final goodbye message to # deregister cleanly. log.debug("Sending registration data: BYE %s\n%s" % (self.client_header, self.client_data)) try: update_sock.sendto( "BYE %s\n%s" % (self.client_header, self.client_data), self.client_register_group) except: log.error("Unable to send client update message") self.client_registered = False
def viewNode(self, indexnumber, tagname, mediatype, viewtype, delete=False): kodiversion = self.kodiversion if mediatype == "homevideos": # Treat homevideos as movies mediatype = "movies" tagname = tagname.encode('utf-8') cleantagname = utils.normalize_nodes(tagname) if viewtype == "mixed": dirname = "%s - %s" % (cleantagname, mediatype) else: dirname = cleantagname path = xbmc.translatePath("special://profile/library/video/").decode('utf-8') nodepath = xbmc.translatePath( "special://profile/library/video/Emby - %s/" % dirname).decode('utf-8') # Verify the video directory if not xbmcvfs.exists(path): shutil.copytree( src=xbmc.translatePath("special://xbmc/system/library/video/").decode('utf-8'), dst=xbmc.translatePath("special://profile/library/video/").decode('utf-8')) xbmcvfs.exists(path) # Create the node directory if not xbmcvfs.exists(nodepath): # We need to copy over the default items xbmcvfs.mkdirs(nodepath) else: if delete: dirs, files = xbmcvfs.listdir(nodepath) for file in files: xbmcvfs.delete(nodepath + file) self.logMsg("Sucessfully removed videonode: %s." % tagname, 1) return # Create index entry nodeXML = "%sindex.xml" % nodepath # Set windows property path = "library://video/Emby - %s/" % dirname for i in range(1, indexnumber): # Verify to make sure we don't create duplicates if utils.window('Emby.nodes.%s.index' % i) == path: return utils.window('Emby.nodes.%s.index' % indexnumber, value=path) # Root root = self.commonRoot(order=0, label=dirname, tagname=tagname, roottype=0) try: utils.indent(root) except: pass etree.ElementTree(root).write(nodeXML) nodetypes = { '1': "all", '2': "recent", '3': "recentepisodes", '4': "inprogress", '5': "inprogressepisodes", '6': "unwatched", '7': "nextupepisodes", '8': "sets", '9': "genres", '10': "random", '11': "recommended" } mediatypes = { # label according to nodetype per mediatype 'movies': { '1': tagname, '2': 30174, '4': 30177, '6': 30189, '8': 20434, '9': 135, '10': 30229, '11': 30230}, 'tvshows': { '1': tagname, '2': 30170, '3': 30175, '4': 30171, '5': 30178, '7': 30179, '9': 135, '10': 30229, '11': 30230}, } nodes = mediatypes[mediatype] for node in nodes: nodetype = nodetypes[node] nodeXML = "%s%s_%s.xml" % (nodepath, cleantagname, nodetype) # Get label stringid = nodes[node] if node != '1': label = utils.language(stringid) if not label: label = xbmc.getLocalizedString(stringid) else: label = stringid # Set window properties if nodetype == "nextupepisodes": # Custom query path = "plugin://plugin.video.emby/?id=%s&mode=nextup&limit=25" % tagname elif kodiversion == 14 and nodetype == "recentepisodes": # Custom query path = "plugin://plugin.video.emby/?id=%s&mode=recentepisodes&limit=25" % tagname elif kodiversion == 14 and nodetype == "inprogressepisodes": # Custom query path = "plugin://plugin.video.emby/?id=%s&mode=inprogressepisodes&limit=25"% tagname else: path = "library://video/Emby - %s/%s_%s.xml" % (dirname, cleantagname, nodetype) windowpath = "ActivateWindow(Video, %s, return)" % path if nodetype == "all": if viewtype == "mixed": templabel = dirname else: templabel = label embynode = "Emby.nodes.%s" % indexnumber utils.window('%s.title' % embynode, value=templabel) utils.window('%s.path' % embynode, value=windowpath) utils.window('%s.content' % embynode, value=path) utils.window('%s.type' % embynode, value=mediatype) else: embynode = "Emby.nodes.%s.%s" % (indexnumber, nodetype) utils.window('%s.title' % embynode, value=label) utils.window('%s.path' % embynode, value=windowpath) utils.window('%s.content' % embynode, value=path) if xbmcvfs.exists(nodeXML): # Don't recreate xml if already exists continue # Create the root if nodetype == "nextupepisodes" or (kodiversion == 14 and nodetype in ('recentepisodes', 'inprogressepisodes')): # Folder type with plugin path root = self.commonRoot(order=node, label=label, tagname=tagname, roottype=2) etree.SubElement(root, 'path').text = path etree.SubElement(root, 'content').text = "episodes" else: root = self.commonRoot(order=node, label=label, tagname=tagname) if nodetype in ('recentepisodes', 'inprogressepisodes'): etree.SubElement(root, 'content').text = "episodes" else: etree.SubElement(root, 'content').text = mediatype limit = "25" # Elements per nodetype if nodetype == "all": etree.SubElement(root, 'order', {'direction': "ascending"}).text = "sorttitle" elif nodetype == "recent": etree.SubElement(root, 'order', {'direction': "descending"}).text = "dateadded" etree.SubElement(root, 'limit').text = limit rule = etree.SubElement(root, 'rule', {'field': "playcount", 'operator': "is"}) etree.SubElement(rule, 'value').text = "0" elif nodetype == "inprogress": etree.SubElement(root, 'rule', {'field': "inprogress", 'operator': "true"}) etree.SubElement(root, 'limit').text = limit elif nodetype == "genres": etree.SubElement(root, 'order', {'direction': "ascending"}).text = "sorttitle" etree.SubElement(root, 'group').text = "genres" elif nodetype == "unwatched": etree.SubElement(root, 'order', {'direction': "ascending"}).text = "sorttitle" rule = etree.SubElement(root, "rule", {'field': "playcount", 'operator': "is"}) etree.SubElement(rule, 'value').text = "0" elif nodetype == "sets": etree.SubElement(root, 'order', {'direction': "ascending"}).text = "sorttitle" etree.SubElement(root, 'group').text = "sets" elif nodetype == "random": etree.SubElement(root, 'order', {'direction': "ascending"}).text = "random" etree.SubElement(root, 'limit').text = limit elif nodetype == "recommended": etree.SubElement(root, 'order', {'direction': "descending"}).text = "rating" etree.SubElement(root, 'limit').text = limit rule = etree.SubElement(root, 'rule', {'field': "playcount", 'operator': "is"}) etree.SubElement(rule, 'value').text = "0" rule2 = etree.SubElement(root, 'rule', attrib={'field': "rating", 'operator': "greaterthan"}) etree.SubElement(rule2, 'value').text = "7" elif nodetype == "recentepisodes": # Kodi Isengard, Jarvis etree.SubElement(root, 'order', {'direction': "descending"}).text = "dateadded" etree.SubElement(root, 'limit').text = limit rule = etree.SubElement(root, 'rule', {'field': "playcount", 'operator': "is"}) etree.SubElement(rule, 'value').text = "0" elif nodetype == "inprogressepisodes": # Kodi Isengard, Jarvis etree.SubElement(root, 'limit').text = "25" rule = etree.SubElement(root, 'rule', attrib={'field': "inprogress", 'operator':"true"}) try: utils.indent(root) except: pass etree.ElementTree(root).write(nodeXML)
def viewNode(self, indexnumber, tagname, mediatype, viewtype, viewid, delete=False): # Plex: reassign mediatype due to Kodi inner workings # How many items do we get at most? limit = "100" mediatypes = { 'movie': 'movies', 'show': 'tvshows', 'photo': 'photos', 'homevideo': 'homevideos', 'musicvideos': 'musicvideos' } mediatype = mediatypes[mediatype] window = utils.window kodiversion = self.kodiversion if viewtype == "mixed": dirname = "%s-%s" % (viewid, mediatype) else: dirname = viewid path = xbmc.translatePath("special://profile/library/video/").decode( 'utf-8') nodepath = xbmc.translatePath( "special://profile/library/video/Plex-%s/" % dirname).decode('utf-8') # Verify the video directory # KODI BUG # Kodi caches the result of exists for directories # so try creating a file if utils.IfExists(path) is False: shutil.copytree( src=xbmc.translatePath( "special://xbmc/system/library/video").decode('utf-8'), dst=xbmc.translatePath( "special://profile/library/video").decode('utf-8')) # Create the node directory if mediatype != "photo": if utils.IfExists(nodepath) is False: # folder does not exist yet self.logMsg('Creating folder %s' % nodepath, 1) xbmcvfs.mkdirs(nodepath.encode('utf-8')) if delete: dirs, files = xbmcvfs.listdir(nodepath.encode('utf-8')) for file in files: xbmcvfs.delete( (nodepath + file.decode('utf-8')).encode('utf-8')) self.logMsg("Sucessfully removed videonode: %s." % tagname, 1) return # Create index entry nodeXML = "%sindex.xml" % nodepath # Set windows property path = "library://video/Plex-%s/" % dirname for i in range(1, indexnumber): # Verify to make sure we don't create duplicates if window('Emby.nodes.%s.index' % i) == path: return if mediatype == "photo": path = "plugin://plugin.video.plexkodiconnect/?id=%s&mode=getsubfolders" % indexnumber window('Emby.nodes.%s.index' % indexnumber, value=path) # Root if not mediatype == "photo": if viewtype == "mixed": specialtag = "%s-%s" % (tagname, mediatype) root = self.commonRoot(order=0, label=specialtag, tagname=tagname, roottype=0) else: root = self.commonRoot(order=0, label=tagname, tagname=tagname, roottype=0) try: utils.indent(root) except: pass etree.ElementTree(root).write(nodeXML) nodetypes = { '1': "all", '2': "recent", '3': "recentepisodes", '4': "inprogress", '5': "inprogressepisodes", '6': "unwatched", '7': "nextepisodes", '8': "sets", '9': "genres", '10': "random", '11': "recommended", '12': "ondeck" } mediatypes = { # label according to nodetype per mediatype 'movies': { '1': tagname, '2': 30174, # '4': 30177, # '6': 30189, '8': 39501, '9': 135, '10': 30227, '11': 30230, '12': 39500, }, 'tvshows': { '1': tagname, # '2': 30170, '3': 30174, # '4': 30171, # '5': 30178, # '7': 30179, '9': 135, '10': 30227, # '11': 30230, '12': 39500, }, 'homevideos': { '1': tagname, '2': 30251, '11': 30253 }, 'photos': { '1': tagname, '2': 30252, '8': 30255, '11': 30254 }, 'musicvideos': { '1': tagname, '2': 30256, '4': 30257, '6': 30258 } } # Key: nodetypes, value: sort order in Kodi sortorder = { '1': '3', # "all", '2': '2', # "recent", '3': '2', # "recentepisodes", # '4': # "inprogress", # '5': # "inprogressepisodes", # '6': # "unwatched", # '7': # "nextepisodes", '8': '7', # "sets", '9': '6', # "genres", '10': '8', # "random", '11': '5', # "recommended", '12': '1', # "ondeck" } nodes = mediatypes[mediatype] for node in nodes: nodetype = nodetypes[node] nodeXML = "%s%s_%s.xml" % (nodepath, viewid, nodetype) # Get label stringid = nodes[node] if node != "1": label = utils.language(stringid) if not label: label = xbmc.getLocalizedString(stringid) else: label = stringid # Set window properties if (mediatype == "homevideos" or mediatype == "photo") and nodetype == "all": # Custom query path = ( "plugin://plugin.video.plexkodiconnect/?id=%s&mode=browsecontent&type=%s" % (tagname, mediatype)) elif (mediatype == "homevideos" or mediatype == "photo"): # Custom query path = ( "plugin://plugin.video.plexkodiconnect/?id=%s&mode=browsecontent&type=%s&folderid=%s" % (tagname, mediatype, nodetype)) elif nodetype == "nextepisodes": # Custom query path = "plugin://plugin.video.plexkodiconnect/?id=%s&mode=nextup&limit=%s" % ( tagname, limit) # elif kodiversion == 14 and nodetype == "recentepisodes": elif nodetype == "recentepisodes": # Custom query path = ( "plugin://plugin.video.plexkodiconnect/?id=%s&mode=recentepisodes&type=%s&tagname=%s&limit=%s" % (viewid, mediatype, tagname, limit)) elif kodiversion == 14 and nodetype == "inprogressepisodes": # Custom query path = "plugin://plugin.video.plexkodiconnect/?id=%s&mode=inprogressepisodes&limit=%s" % ( tagname, limit) elif nodetype == 'ondeck': # PLEX custom query if mediatype == "tvshows": path = ( "plugin://plugin.video.plexkodiconnect/?id=%s&mode=ondeck&type=%s&tagname=%s&limit=%s" % (viewid, mediatype, tagname, limit)) elif mediatype == "movies": # Reset nodetype; we got the label nodetype = 'inprogress' else: path = "library://video/Plex-%s/%s_%s.xml" % (dirname, viewid, nodetype) if mediatype == "photo": windowpath = "ActivateWindow(Pictures,%s,return)" % path else: windowpath = "ActivateWindow(Video,%s,return)" % path if nodetype == "all": if viewtype == "mixed": templabel = "%s-%s" % (tagname, mediatype) else: templabel = label embynode = "Emby.nodes.%s" % indexnumber window('%s.title' % embynode, value=templabel) window('%s.path' % embynode, value=windowpath) window('%s.content' % embynode, value=path) window('%s.type' % embynode, value=mediatype) else: embynode = "Emby.nodes.%s.%s" % (indexnumber, nodetype) window('%s.title' % embynode, value=label) window('%s.path' % embynode, value=windowpath) window('%s.content' % embynode, value=path) if mediatype == "photo": # For photos, we do not create a node in videos but we do want the window props # to be created. # To do: add our photos nodes to kodi picture sources somehow continue if xbmcvfs.exists(nodeXML.encode('utf-8')): # Don't recreate xml if already exists continue # Create the root if (nodetype in ("nextepisodes", "ondeck", 'recentepisodes') or mediatype == "homevideos"): # Folder type with plugin path root = self.commonRoot(order=sortorder[node], label=label, tagname=tagname, roottype=2) etree.SubElement(root, 'path').text = path etree.SubElement(root, 'content').text = "episodes" else: root = self.commonRoot(order=sortorder[node], label=label, tagname=tagname) if nodetype in ('recentepisodes', 'inprogressepisodes'): etree.SubElement(root, 'content').text = "episodes" else: etree.SubElement(root, 'content').text = mediatype # Elements per nodetype if nodetype == "all": etree.SubElement(root, 'order', { 'direction': "ascending" }).text = "sorttitle" elif nodetype == "recent": etree.SubElement(root, 'order', { 'direction': "descending" }).text = "dateadded" etree.SubElement(root, 'limit').text = limit rule = etree.SubElement(root, 'rule', { 'field': "playcount", 'operator': "is" }) etree.SubElement(rule, 'value').text = "0" elif nodetype == "inprogress": etree.SubElement(root, 'rule', { 'field': "inprogress", 'operator': "true" }) etree.SubElement(root, 'limit').text = limit etree.SubElement(root, 'order', { 'direction': 'descending' }).text = 'lastplayed' elif nodetype == "genres": etree.SubElement(root, 'order', { 'direction': "ascending" }).text = "sorttitle" etree.SubElement(root, 'group').text = "genres" elif nodetype == "unwatched": etree.SubElement(root, 'order', { 'direction': "ascending" }).text = "sorttitle" rule = etree.SubElement(root, "rule", { 'field': "playcount", 'operator': "is" }) etree.SubElement(rule, 'value').text = "0" elif nodetype == "sets": etree.SubElement(root, 'order', { 'direction': "ascending" }).text = "sorttitle" etree.SubElement(root, 'group').text = "tags" elif nodetype == "random": etree.SubElement(root, 'order', { 'direction': "ascending" }).text = "random" etree.SubElement(root, 'limit').text = limit elif nodetype == "recommended": etree.SubElement(root, 'order', { 'direction': "descending" }).text = "rating" etree.SubElement(root, 'limit').text = limit rule = etree.SubElement(root, 'rule', { 'field': "playcount", 'operator': "is" }) etree.SubElement(rule, 'value').text = "0" rule2 = etree.SubElement(root, 'rule', attrib={ 'field': "rating", 'operator': "greaterthan" }) etree.SubElement(rule2, 'value').text = "7" elif nodetype == "recentepisodes": # Kodi Isengard, Jarvis etree.SubElement(root, 'order', { 'direction': "descending" }).text = "dateadded" etree.SubElement(root, 'limit').text = limit rule = etree.SubElement(root, 'rule', { 'field': "playcount", 'operator': "is" }) etree.SubElement(rule, 'value').text = "0" elif nodetype == "inprogressepisodes": # Kodi Isengard, Jarvis etree.SubElement(root, 'limit').text = limit rule = etree.SubElement(root, 'rule', attrib={ 'field': "inprogress", 'operator': "true" }) try: utils.indent(root) except: pass etree.ElementTree(root).write(nodeXML)
(plexid, itemtype)) if plexid: item = PF.GetPlexMetadata(plexid) if item is None or item == 401: logMsg('Could not get item metadata for item %s' % plexid, -1) return API = PlexAPI.API(item[0]) userdata = API.getUserData() likes = userdata['Likes'] favourite = userdata['Favorite'] options = [] if likes == True: #clear like for the item options.append(utils.language(30402)) if likes == False or likes == None: #Like the item options.append(utils.language(30403)) if likes == True or likes == None: #Dislike the item options.append(utils.language(30404)) if favourite == False: #Add to emby favourites options.append(utils.language(30405)) if favourite == True: #Remove from emby favourites options.append(utils.language(30406)) if itemtype == "song": #Set custom song rating options.append(utils.language(30407))
def viewNode(self, indexnumber, tagname, mediatype, viewtype, viewid, delete=False): window = utils.window kodiversion = self.kodiversion if viewtype == "mixed": dirname = "%s - %s" % (viewid, mediatype) else: dirname = viewid path = xbmc.translatePath("special://profile/library/video/").decode( 'utf-8') nodepath = xbmc.translatePath( "special://profile/library/video/Emby - %s/" % dirname).decode('utf-8') # Verify the video directory if not xbmcvfs.exists(path): shutil.copytree( src=xbmc.translatePath( "special://xbmc/system/library/video").decode('utf-8'), dst=xbmc.translatePath( "special://profile/library/video").decode('utf-8')) xbmcvfs.exists(path) # Create the node directory if not xbmcvfs.exists(nodepath) and not mediatype == "photos": # We need to copy over the default items xbmcvfs.mkdirs(nodepath) else: if delete: dirs, files = xbmcvfs.listdir(nodepath) for file in files: xbmcvfs.delete(nodepath + file) self.logMsg("Sucessfully removed videonode: %s." % tagname, 1) return # Create index entry nodeXML = "%sindex.xml" % nodepath # Set windows property path = "library://video/Emby - %s/" % dirname for i in range(1, indexnumber): # Verify to make sure we don't create duplicates if window('Emby.nodes.%s.index' % i) == path: return if mediatype == "photos": path = "plugin://plugin.video.emby/?id=%s&mode=getsubfolders" % indexnumber window('Emby.nodes.%s.index' % indexnumber, value=path) # Root if not mediatype == "photos": if viewtype == "mixed": specialtag = "%s - %s" % (tagname, mediatype) root = self.commonRoot(order=0, label=specialtag, tagname=tagname, roottype=0) else: root = self.commonRoot(order=0, label=tagname, tagname=tagname, roottype=0) try: utils.indent(root) except: pass etree.ElementTree(root).write(nodeXML) nodetypes = { '1': "all", '2': "recent", '3': "recentepisodes", '4': "inprogress", '5': "inprogressepisodes", '6': "unwatched", '7': "nextepisodes", '8': "sets", '9': "genres", '10': "random", '11': "recommended", } mediatypes = { # label according to nodetype per mediatype 'movies': { '1': tagname, '2': 30174, '4': 30177, '6': 30189, '8': 20434, '9': 135, '10': 30229, '11': 30230 }, 'tvshows': { '1': tagname, '2': 30170, '3': 30175, '4': 30171, '5': 30178, '7': 30179, '9': 135, '10': 30229, '11': 30230 }, 'homevideos': { '1': tagname, '2': 30251, '11': 30253 }, 'photos': { '1': tagname, '2': 30252, '8': 30255, '11': 30254 }, 'musicvideos': { '1': tagname, '2': 30256, '4': 30257, '6': 30258 } } nodes = mediatypes[mediatype] for node in nodes: nodetype = nodetypes[node] nodeXML = "%s%s_%s.xml" % (nodepath, viewid, nodetype) # Get label stringid = nodes[node] if node != "1": label = utils.language(stringid) if not label: label = xbmc.getLocalizedString(stringid) else: label = stringid # Set window properties if (mediatype == "homevideos" or mediatype == "photos") and nodetype == "all": # Custom query path = ( "plugin://plugin.video.emby/?id=%s&mode=browsecontent&type=%s" % (tagname, mediatype)) elif (mediatype == "homevideos" or mediatype == "photos"): # Custom query path = ( "plugin://plugin.video.emby/?id=%s&mode=browsecontent&type=%s&folderid=%s" % (tagname, mediatype, nodetype)) elif nodetype == "nextepisodes": # Custom query path = "plugin://plugin.video.emby/?id=%s&mode=nextup&limit=25" % tagname elif kodiversion == 14 and nodetype == "recentepisodes": # Custom query path = "plugin://plugin.video.emby/?id=%s&mode=recentepisodes&limit=25" % tagname elif kodiversion == 14 and nodetype == "inprogressepisodes": # Custom query path = "plugin://plugin.video.emby/?id=%s&mode=inprogressepisodes&limit=25" % tagname else: path = "library://video/Emby - %s/%s_%s.xml" % ( dirname, viewid, nodetype) if mediatype == "photos": windowpath = "ActivateWindow(Pictures,%s,return)" % path else: windowpath = "ActivateWindow(Video,%s,return)" % path if nodetype == "all": if viewtype == "mixed": templabel = "%s - %s" % (tagname, mediatype) else: templabel = label embynode = "Emby.nodes.%s" % indexnumber window('%s.title' % embynode, value=templabel) window('%s.path' % embynode, value=windowpath) window('%s.content' % embynode, value=path) window('%s.type' % embynode, value=mediatype) else: embynode = "Emby.nodes.%s.%s" % (indexnumber, nodetype) window('%s.title' % embynode, value=label) window('%s.path' % embynode, value=windowpath) window('%s.content' % embynode, value=path) if mediatype == "photos": # For photos, we do not create a node in videos but we do want the window props # to be created. # To do: add our photos nodes to kodi picture sources somehow continue if xbmcvfs.exists(nodeXML): # Don't recreate xml if already exists continue # Create the root if (nodetype == "nextepisodes" or mediatype == "homevideos" or (kodiversion == 14 and nodetype in ('recentepisodes', 'inprogressepisodes'))): # Folder type with plugin path root = self.commonRoot(order=node, label=label, tagname=tagname, roottype=2) etree.SubElement(root, 'path').text = path etree.SubElement(root, 'content').text = "episodes" else: root = self.commonRoot(order=node, label=label, tagname=tagname) if nodetype in ('recentepisodes', 'inprogressepisodes'): etree.SubElement(root, 'content').text = "episodes" else: etree.SubElement(root, 'content').text = mediatype limit = "25" # Elements per nodetype if nodetype == "all": etree.SubElement(root, 'order', { 'direction': "ascending" }).text = "sorttitle" elif nodetype == "recent": etree.SubElement(root, 'order', { 'direction': "descending" }).text = "dateadded" etree.SubElement(root, 'limit').text = limit rule = etree.SubElement(root, 'rule', { 'field': "playcount", 'operator': "is" }) etree.SubElement(rule, 'value').text = "0" elif nodetype == "inprogress": etree.SubElement(root, 'rule', { 'field': "inprogress", 'operator': "true" }) etree.SubElement(root, 'limit').text = limit elif nodetype == "genres": etree.SubElement(root, 'order', { 'direction': "ascending" }).text = "sorttitle" etree.SubElement(root, 'group').text = "genres" elif nodetype == "unwatched": etree.SubElement(root, 'order', { 'direction': "ascending" }).text = "sorttitle" rule = etree.SubElement(root, "rule", { 'field': "playcount", 'operator': "is" }) etree.SubElement(rule, 'value').text = "0" elif nodetype == "sets": etree.SubElement(root, 'order', { 'direction': "ascending" }).text = "sorttitle" etree.SubElement(root, 'group').text = "sets" elif nodetype == "random": etree.SubElement(root, 'order', { 'direction': "ascending" }).text = "random" etree.SubElement(root, 'limit').text = limit elif nodetype == "recommended": etree.SubElement(root, 'order', { 'direction': "descending" }).text = "rating" etree.SubElement(root, 'limit').text = limit rule = etree.SubElement(root, 'rule', { 'field': "playcount", 'operator': "is" }) etree.SubElement(rule, 'value').text = "0" rule2 = etree.SubElement(root, 'rule', attrib={ 'field': "rating", 'operator': "greaterthan" }) etree.SubElement(rule2, 'value').text = "7" elif nodetype == "recentepisodes": # Kodi Isengard, Jarvis etree.SubElement(root, 'order', { 'direction': "descending" }).text = "dateadded" etree.SubElement(root, 'limit').text = limit rule = etree.SubElement(root, 'rule', { 'field': "playcount", 'operator': "is" }) etree.SubElement(rule, 'value').text = "0" elif nodetype == "inprogressepisodes": # Kodi Isengard, Jarvis etree.SubElement(root, 'limit').text = "25" rule = etree.SubElement(root, 'rule', attrib={ 'field': "inprogress", 'operator': "true" }) try: utils.indent(root) except: pass etree.ElementTree(root).write(nodeXML)
embycursor.close() if item: embyid = item[0] logMsg("Contextmenu opened for embyid: %s - itemtype: %s" %(embyid,itemtype)) if embyid: item = emby.getItem(embyid) API = api.API(item) userdata = API.getUserData() likes = userdata['Likes'] favourite = userdata['Favorite'] options=[] if likes == True: #clear like for the item options.append(utils.language(30402)) if likes == False or likes == None: #Like the item options.append(utils.language(30403)) if likes == True or likes == None: #Dislike the item options.append(utils.language(30404)) if favourite == False: #Add to emby favourites options.append(utils.language(30405)) if favourite == True: #Remove from emby favourites options.append(utils.language(30406)) if itemtype == "song": #Set custom song rating options.append(utils.language(30407))
def db_reset(): dialog = xbmcgui.Dialog() if not dialog.yesno(language(29999), language(33074)): return # first stop any db sync window('emby_online', value="reset") window('emby_shouldStop', value="true") count = 10 while window('emby_dbScan') == "true": log.info("Sync is running, will retry: %s..." % count) count -= 1 if count == 0: dialog.ok(language(29999), language(33085)) return xbmc.sleep(1000) # Clean up the playlists Playlist().delete_playlists() # Clean up the video nodes VideoNodes().deleteNodes() # Wipe the kodi databases log.warn("Resetting the Kodi video database.") with DatabaseConn('video') as cursor: cursor.execute('SELECT tbl_name FROM sqlite_master WHERE type="table"') rows = cursor.fetchall() for row in rows: tablename = row[0] if tablename != "version": cursor.execute("DELETE FROM " + tablename) if settings('enableMusic') == "true": log.warn("Resetting the Kodi music database.") with DatabaseConn('music') as cursor: cursor.execute( 'SELECT tbl_name FROM sqlite_master WHERE type="table"') rows = cursor.fetchall() for row in rows: tablename = row[0] if tablename != "version": cursor.execute("DELETE FROM " + tablename) # Wipe the emby database log.warn("Resetting the Emby database.") with DatabaseConn('emby') as cursor: cursor.execute('SELECT tbl_name FROM sqlite_master WHERE type="table"') rows = cursor.fetchall() for row in rows: tablename = row[0] if tablename != "version": cursor.execute("DELETE FROM " + tablename) cursor.execute('DROP table IF EXISTS emby') cursor.execute('DROP table IF EXISTS view') cursor.execute("DROP table IF EXISTS version") # Offer to wipe cached thumbnails if dialog.yesno(language(29999), language(33086)): log.warn("Resetting all cached artwork") # Remove all existing textures first import artwork artwork.Artwork().delete_cache() # reset the install run flag settings('SyncInstallRunDone', value="false") # Remove emby info resp = dialog.yesno(language(29999), language(33087)) if resp: import connectmanager # Delete the settings addondir = xbmc.translatePath( "special://profile/addon_data/plugin.video.emby/").decode('utf-8') dataPath = "%ssettings.xml" % addondir xbmcvfs.delete(dataPath) connectmanager.ConnectManager().clear_data() dialog.ok(heading=language(29999), line1=language(33088)) xbmc.executebuiltin('RestartApp') try: xbmcplugin.setResolvedUrl(int(sys.argv[1]), False, xbmcgui.ListItem()) except: pass
def db_reset(): dialog = xbmcgui.Dialog() if not dialog.yesno(language(29999), language(33074)): return # first stop any db sync window('emby_online', value="reset") window('emby_shouldStop', value="true") count = 10 while window('emby_dbScan') == "true": log.info("Sync is running, will retry: %s..." % count) count -= 1 if count == 0: dialog.ok(language(29999), language(33085)) return xbmc.sleep(1000) # Clean up the playlists Playlist().delete_playlists() # Clean up the video nodes VideoNodes().deleteNodes() # Wipe the kodi databases log.warn("Resetting the Kodi video database.") with DatabaseConn('video') as cursor: cursor.execute('SELECT tbl_name FROM sqlite_master WHERE type="table"') rows = cursor.fetchall() for row in rows: tablename = row[0] if tablename != "version": cursor.execute("DELETE FROM " + tablename) if settings('enableMusic') == "true": log.warn("Resetting the Kodi music database.") with DatabaseConn('music') as cursor: cursor.execute('SELECT tbl_name FROM sqlite_master WHERE type="table"') rows = cursor.fetchall() for row in rows: tablename = row[0] if tablename != "version": cursor.execute("DELETE FROM " + tablename) # Wipe the emby database log.warn("Resetting the Emby database.") with DatabaseConn('emby') as cursor: cursor.execute('SELECT tbl_name FROM sqlite_master WHERE type="table"') rows = cursor.fetchall() for row in rows: tablename = row[0] if tablename != "version": cursor.execute("DELETE FROM " + tablename) cursor.execute('DROP table IF EXISTS emby') cursor.execute('DROP table IF EXISTS view') cursor.execute("DROP table IF EXISTS version") # Offer to wipe cached thumbnails if dialog.yesno(language(29999), language(33086)): log.warn("Resetting all cached artwork") # Remove all existing textures first import artwork artwork.Artwork().delete_cache() # reset the install run flag settings('SyncInstallRunDone', value="false") # Remove emby info resp = dialog.yesno(language(29999), language(33087)) if resp: import connectmanager # Delete the settings addondir = xbmc.translatePath( "special://profile/addon_data/plugin.video.emby/").decode('utf-8') dataPath = "%ssettings.xml" % addondir xbmcvfs.delete(dataPath) connectmanager.ConnectManager().clear_data() dialog.ok(heading=language(29999), line1=language(33088)) xbmc.executebuiltin('RestartApp') try: xbmcplugin.setResolvedUrl(int(sys.argv[1]), False, xbmcgui.ListItem()) except: pass
def viewNode(self, indexnumber, tagname, mediatype, viewtype, viewid, delete=False): # Plex: reassign mediatype due to Kodi inner workings # How many items do we get at most? limit = "100" mediatypes = { 'movie': 'movies', 'show': 'tvshows', 'photo': 'photos', 'homevideo': 'homevideos', 'musicvideos': 'musicvideos' } mediatype = mediatypes[mediatype] window = utils.window kodiversion = self.kodiversion if viewtype == "mixed": dirname = "%s-%s" % (viewid, mediatype) else: dirname = viewid path = xbmc.translatePath("special://profile/library/video/").decode('utf-8') nodepath = xbmc.translatePath( "special://profile/library/video/Plex-%s/" % dirname).decode('utf-8') # Verify the video directory # KODI BUG # Kodi caches the result of exists for directories # so try creating a file if utils.IfExists(path) is False: shutil.copytree( src=xbmc.translatePath("special://xbmc/system/library/video").decode('utf-8'), dst=xbmc.translatePath("special://profile/library/video").decode('utf-8')) # Create the node directory if mediatype != "photo": if utils.IfExists(nodepath) is False: # folder does not exist yet self.logMsg('Creating folder %s' % nodepath, 1) xbmcvfs.mkdirs(nodepath.encode('utf-8')) if delete: dirs, files = xbmcvfs.listdir(nodepath.encode('utf-8')) for file in files: xbmcvfs.delete( (nodepath + file.decode('utf-8')).encode('utf-8')) self.logMsg("Sucessfully removed videonode: %s." % tagname, 1) return # Create index entry nodeXML = "%sindex.xml" % nodepath # Set windows property path = "library://video/Plex-%s/" % dirname for i in range(1, indexnumber): # Verify to make sure we don't create duplicates if window('Emby.nodes.%s.index' % i) == path: return if mediatype == "photo": path = "plugin://plugin.video.plexkodiconnect/?id=%s&mode=getsubfolders" % indexnumber window('Emby.nodes.%s.index' % indexnumber, value=path) # Root if not mediatype == "photo": if viewtype == "mixed": specialtag = "%s-%s" % (tagname, mediatype) root = self.commonRoot(order=0, label=specialtag, tagname=tagname, roottype=0) else: root = self.commonRoot(order=0, label=tagname, tagname=tagname, roottype=0) try: utils.indent(root) except: pass etree.ElementTree(root).write(nodeXML) nodetypes = { '1': "all", '2': "recent", '3': "recentepisodes", '4': "inprogress", '5': "inprogressepisodes", '6': "unwatched", '7': "nextepisodes", '8': "sets", '9': "genres", '10': "random", '11': "recommended", '12': "ondeck" } mediatypes = { # label according to nodetype per mediatype 'movies': { '1': tagname, '2': 30174, # '4': 30177, # '6': 30189, '8': 20434, '9': 135, '10': 30227, '11': 30230, '12': 39500, }, 'tvshows': { '1': tagname, # '2': 30170, '3': 30174, # '4': 30171, # '5': 30178, # '7': 30179, '9': 135, '10': 30227, # '11': 30230, '12': 39500, }, 'homevideos': { '1': tagname, '2': 30251, '11': 30253 }, 'photos': { '1': tagname, '2': 30252, '8': 30255, '11': 30254 }, 'musicvideos': { '1': tagname, '2': 30256, '4': 30257, '6': 30258 } } # Key: nodetypes, value: sort order in Kodi sortorder = { '1': '3', # "all", '2': '2', # "recent", '3': '2', # "recentepisodes", # '4': # "inprogress", # '5': # "inprogressepisodes", # '6': # "unwatched", # '7': # "nextepisodes", '8': '7', # "sets", '9': '6', # "genres", '10': '8', # "random", '11': '5', # "recommended", '12': '1', # "ondeck" } nodes = mediatypes[mediatype] for node in nodes: nodetype = nodetypes[node] nodeXML = "%s%s_%s.xml" % (nodepath, viewid, nodetype) # Get label stringid = nodes[node] if node != "1": label = utils.language(stringid) if not label: label = xbmc.getLocalizedString(stringid) else: label = stringid # Set window properties if (mediatype == "homevideos" or mediatype == "photo") and nodetype == "all": # Custom query path = ("plugin://plugin.video.plexkodiconnect/?id=%s&mode=browsecontent&type=%s" % (tagname, mediatype)) elif (mediatype == "homevideos" or mediatype == "photo"): # Custom query path = ("plugin://plugin.video.plexkodiconnect/?id=%s&mode=browsecontent&type=%s&folderid=%s" % (tagname, mediatype, nodetype)) elif nodetype == "nextepisodes": # Custom query path = "plugin://plugin.video.plexkodiconnect/?id=%s&mode=nextup&limit=%s" % (tagname, limit) # elif kodiversion == 14 and nodetype == "recentepisodes": elif nodetype == "recentepisodes": # Custom query path = ("plugin://plugin.video.plexkodiconnect/?id=%s&mode=recentepisodes&type=%s&tagname=%s&limit=%s" % (viewid, mediatype, tagname, limit)) elif kodiversion == 14 and nodetype == "inprogressepisodes": # Custom query path = "plugin://plugin.video.plexkodiconnect/?id=%s&mode=inprogressepisodes&limit=%s" % (tagname, limit) elif nodetype == 'ondeck': # PLEX custom query if mediatype == "tvshows": path = ("plugin://plugin.video.plexkodiconnect/?id=%s&mode=ondeck&type=%s&tagname=%s&limit=%s" % (viewid, mediatype, tagname, limit)) elif mediatype =="movies": # Reset nodetype; we got the label nodetype = 'inprogress' else: path = "library://video/Plex-%s/%s_%s.xml" % (dirname, viewid, nodetype) if mediatype == "photo": windowpath = "ActivateWindow(Pictures,%s,return)" % path else: windowpath = "ActivateWindow(Video,%s,return)" % path if nodetype == "all": if viewtype == "mixed": templabel = "%s-%s" % (tagname, mediatype) else: templabel = label embynode = "Emby.nodes.%s" % indexnumber window('%s.title' % embynode, value=templabel) window('%s.path' % embynode, value=windowpath) window('%s.content' % embynode, value=path) window('%s.type' % embynode, value=mediatype) else: embynode = "Emby.nodes.%s.%s" % (indexnumber, nodetype) window('%s.title' % embynode, value=label) window('%s.path' % embynode, value=windowpath) window('%s.content' % embynode, value=path) if mediatype == "photo": # For photos, we do not create a node in videos but we do want the window props # to be created. # To do: add our photos nodes to kodi picture sources somehow continue if xbmcvfs.exists(nodeXML.encode('utf-8')): # Don't recreate xml if already exists continue # Create the root if (nodetype in ("nextepisodes", "ondeck", 'recentepisodes') or mediatype == "homevideos"): # Folder type with plugin path root = self.commonRoot(order=sortorder[node], label=label, tagname=tagname, roottype=2) etree.SubElement(root, 'path').text = path etree.SubElement(root, 'content').text = "episodes" else: root = self.commonRoot(order=sortorder[node], label=label, tagname=tagname) if nodetype in ('recentepisodes', 'inprogressepisodes'): etree.SubElement(root, 'content').text = "episodes" else: etree.SubElement(root, 'content').text = mediatype # Elements per nodetype if nodetype == "all": etree.SubElement(root, 'order', {'direction': "ascending"}).text = "sorttitle" elif nodetype == "recent": etree.SubElement(root, 'order', {'direction': "descending"}).text = "dateadded" etree.SubElement(root, 'limit').text = limit rule = etree.SubElement(root, 'rule', {'field': "playcount", 'operator': "is"}) etree.SubElement(rule, 'value').text = "0" elif nodetype == "inprogress": etree.SubElement(root, 'rule', {'field': "inprogress", 'operator': "true"}) etree.SubElement(root, 'limit').text = limit elif nodetype == "genres": etree.SubElement(root, 'order', {'direction': "ascending"}).text = "sorttitle" etree.SubElement(root, 'group').text = "genres" elif nodetype == "unwatched": etree.SubElement(root, 'order', {'direction': "ascending"}).text = "sorttitle" rule = etree.SubElement(root, "rule", {'field': "playcount", 'operator': "is"}) etree.SubElement(rule, 'value').text = "0" elif nodetype == "sets": etree.SubElement(root, 'order', {'direction': "ascending"}).text = "sorttitle" etree.SubElement(root, 'group').text = "sets" elif nodetype == "random": etree.SubElement(root, 'order', {'direction': "ascending"}).text = "random" etree.SubElement(root, 'limit').text = limit elif nodetype == "recommended": etree.SubElement(root, 'order', {'direction': "descending"}).text = "rating" etree.SubElement(root, 'limit').text = limit rule = etree.SubElement(root, 'rule', {'field': "playcount", 'operator': "is"}) etree.SubElement(rule, 'value').text = "0" rule2 = etree.SubElement(root, 'rule', attrib={'field': "rating", 'operator': "greaterthan"}) etree.SubElement(rule2, 'value').text = "7" elif nodetype == "recentepisodes": # Kodi Isengard, Jarvis etree.SubElement(root, 'order', {'direction': "descending"}).text = "dateadded" etree.SubElement(root, 'limit').text = limit rule = etree.SubElement(root, 'rule', {'field': "playcount", 'operator': "is"}) etree.SubElement(rule, 'value').text = "0" elif nodetype == "inprogressepisodes": # Kodi Isengard, Jarvis etree.SubElement(root, 'limit').text = limit rule = etree.SubElement(root, 'rule', attrib={'field': "inprogress", 'operator':"true"}) try: utils.indent(root) except: pass etree.ElementTree(root).write(nodeXML)
def play(self, itemid, dbid=None): log = self.logMsg window = utils.window settings = utils.settings doUtils = self.doUtils item = self.item API = self.API listitem = xbmcgui.ListItem() playutils = putils.PlayUtils(item) log("Play called.", 1) playurl = playutils.getPlayUrl() if not playurl: return xbmcplugin.setResolvedUrl(int(sys.argv[1]), False, listitem) if dbid is None: # Item is not in Kodi database listitem.setPath(playurl) self.setProperties(playurl, listitem) return xbmcplugin.setResolvedUrl(int(sys.argv[1]), True, listitem) ############### ORGANIZE CURRENT PLAYLIST ################ homeScreen = xbmc.getCondVisibility('Window.IsActive(home)') playlist = xbmc.PlayList(xbmc.PLAYLIST_VIDEO) startPos = max(playlist.getposition(), 0) # Can return -1 sizePlaylist = playlist.size() currentPosition = startPos propertiesPlayback = window('emby_playbackProps') == "true" introsPlaylist = False dummyPlaylist = False log("Playlist start position: %s" % startPos, 2) log("Playlist plugin position: %s" % currentPosition, 2) log("Playlist size: %s" % sizePlaylist, 2) ############### RESUME POINT ################ userdata = API.getUserData() seektime = API.adjustResume(userdata['Resume']) # We need to ensure we add the intro and additional parts only once. # Otherwise we get a loop. if not propertiesPlayback: window('emby_playbackProps', value="true") log("Setting up properties in playlist.", 1) if (not homeScreen and not seektime and window('emby_customPlaylist') != "true"): log("Adding dummy file to playlist.", 2) dummyPlaylist = True playlist.add(playurl, listitem, index=startPos) # Remove the original item from playlist self.pl.removefromPlaylist(startPos+1) # Readd the original item to playlist - via jsonrpc so we have full metadata self.pl.insertintoPlaylist(currentPosition+1, dbid, item['Type'].lower()) currentPosition += 1 ############### -- CHECK FOR INTROS ################ if settings('enableCinema') == "true" and not seektime: # if we have any play them when the movie/show is not being resumed url = "{server}/emby/Users/{UserId}/Items/%s/Intros?format=json" % itemid intros = doUtils(url) if intros['TotalRecordCount'] != 0: getTrailers = True if settings('askCinema') == "true": resp = xbmcgui.Dialog().yesno("Emby for Kodi", utils.language(33016)) if not resp: # User selected to not play trailers getTrailers = False log("Skip trailers.", 1) if getTrailers: for intro in intros['Items']: # The server randomly returns intros, process them. introListItem = xbmcgui.ListItem() introPlayurl = putils.PlayUtils(intro).getPlayUrl() log("Adding Intro: %s" % introPlayurl, 1) # Set listitem and properties for intros pbutils = PlaybackUtils(intro) pbutils.setProperties(introPlayurl, introListItem) self.pl.insertintoPlaylist(currentPosition, url=introPlayurl) introsPlaylist = True currentPosition += 1 ############### -- ADD MAIN ITEM ONLY FOR HOMESCREEN ############### if homeScreen and not seektime and not sizePlaylist: # Extend our current playlist with the actual item to play # only if there's no playlist first log("Adding main item to playlist.", 1) self.pl.addtoPlaylist(dbid, item['Type'].lower()) # Ensure that additional parts are played after the main item currentPosition += 1 ############### -- CHECK FOR ADDITIONAL PARTS ################ if item.get('PartCount'): # Only add to the playlist after intros have played partcount = item['PartCount'] url = "{server}/emby/Videos/%s/AdditionalParts?format=json" % itemid parts = doUtils(url) for part in parts['Items']: additionalListItem = xbmcgui.ListItem() additionalPlayurl = putils.PlayUtils(part).getPlayUrl() log("Adding additional part: %s" % partcount, 1) # Set listitem and properties for each additional parts pbutils = PlaybackUtils(part) pbutils.setProperties(additionalPlayurl, additionalListItem) pbutils.setArtwork(additionalListItem) playlist.add(additionalPlayurl, additionalListItem, index=currentPosition) self.pl.verifyPlaylist() currentPosition += 1 if dummyPlaylist: # Added a dummy file to the playlist, # because the first item is going to fail automatically. log("Processed as a playlist. First item is skipped.", 1) return xbmcplugin.setResolvedUrl(int(sys.argv[1]), False, listitem) # We just skipped adding properties. Reset flag for next time. elif propertiesPlayback: log("Resetting properties playback flag.", 2) window('emby_playbackProps', clear=True) #self.pl.verifyPlaylist() ########## SETUP MAIN ITEM ########## # For transcoding only, ask for audio/subs pref if window('emby_%s.playmethod' % playurl) == "Transcode": playurl = playutils.audioSubsPref(playurl, listitem) window('emby_%s.playmethod' % playurl, value="Transcode") listitem.setPath(playurl) self.setProperties(playurl, listitem) ############### PLAYBACK ################ if homeScreen and seektime and window('emby_customPlaylist') != "true": log("Play as a widget item.", 1) self.setListItem(listitem) xbmcplugin.setResolvedUrl(int(sys.argv[1]), True, listitem) elif ((introsPlaylist and window('emby_customPlaylist') == "true") or (homeScreen and not sizePlaylist)): # Playlist was created just now, play it. log("Play playlist.", 1) xbmc.Player().play(playlist, startpos=startPos) else: log("Play as a regular item.", 1) xbmcplugin.setResolvedUrl(int(sys.argv[1]), True, listitem)
def client_update(self): self.update_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP) update_sock = self.update_sock # Set socket reuse, may not work on all OSs. try: update_sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) except: pass # Attempt to bind to the socket to recieve and send data. If we cant # do this, then we cannot send registration try: update_sock.bind(('0.0.0.0', self.client_update_port)) except: log.error("Unable to bind to port [%s] - Plex Companion will not " "be registered. Change the Plex Companion update port!" % self.client_update_port) if settings('companion_show_gdm_port_warning') == 'true': if dialog('yesno', language(29999), 'Port %s' % self.client_update_port, language(39079), yeslabel=language(30013), # Never show again nolabel=language(30012)): # OK settings('companion_show_gdm_port_warning', value='false') from xbmc import executebuiltin executebuiltin( 'Addon.OpenSettings(plugin.video.plexkodiconnect)') return update_sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 255) update_sock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, socket.inet_aton( self._multicast_address) + socket.inet_aton('0.0.0.0')) update_sock.setblocking(0) # Send initial client registration self.register_as_client() # Now, listen format client discovery reguests and respond. while self._registration_is_running: try: data, addr = update_sock.recvfrom(1024) log.debug("Recieved UDP packet from [%s] containing [%s]" % (addr, data.strip())) except socket.error: pass else: if "M-SEARCH * HTTP/1." in data: log.debug("Detected client discovery request from %s. " " Replying" % str(addr)) try: update_sock.sendto("HTTP/1.0 200 OK\n%s" % self.client_data, addr) except: log.error("Unable to send client update message") log.debug("Sending registration data HTTP/1.0 200 OK") self.client_registered = True sleep(500) log.info("Client Update loop stopped") # When we are finished, then send a final goodbye message to # deregister cleanly. log.debug("Sending registration data: BYE %s\n%s" % (self.client_header, self.client_data)) try: update_sock.sendto("BYE %s\n%s" % (self.client_header, self.client_data), self.client_register_group) except: log.error("Unable to send client update message") self.client_registered = False