def postPlay(self, video=None, playlist=None, handler=None, **kwargs): util.DEBUG_LOG('VideoPlayer: Starting post-play') self.showPostPlay() self.prev = video self.playlist = playlist self.handler = handler self.getHubs() self.setProperty( 'thumb.fallback', 'script.plex/thumb_fallbacks/{0}.png'.format( self.prev.type in ('show', 'season', 'episode') and 'show' or 'movie')) util.DEBUG_LOG('PostPlay: Showing video info') if self.next: self.next.reload(includeRelated=1, includeRelatedCount=10, includeExtras=1, includeExtrasCount=10) self.setInfo() self.fillOnDeck() hasPrev = self.fillRelated() self.fillRoles(hasPrev) self.startTimer() if self.next: self.setFocusId(self.NEXT_BUTTON_ID) else: self.setFocusId(self.PREV_BUTTON_ID)
def loadChannels(self): self.cancelTasks() # path = os.path.join(self.workPath, 'channels.data') # if not os.path.exists(path): # return False # util.DEBUG_LOG('Loading saved grid data...') # with open(path, 'r') as f: # self.channels = json.load(f) util.DEBUG_LOG('Loading grid data...') self.channels = {} channels = tablo.API.batch.post(self.paths) for path in channels: channel = tablo.Channel(channels[path]) self.channels[path] = channel if path not in self._airings: self._airings[path] = [] self.updateCallback(channel) self.loadAirings(channel) for path in channels: self.getChannelData(self.channels[path]) util.DEBUG_LOG('Loading of grid data done.') return True
def getSkinPath(): skin = currentKodiSkin() default = util.ADDON.getAddonInfo('path') if skin == 'skin.confluence': return default if skin not in FONT_TRANSLATIONS: return default if updateNeeded(): util.DEBUG_LOG('Updating custom skin') try: setupDynamicSkin() for xml in SKINS_XMLS: customizeSkinXML(skin, xml) with open(VERSION_FILE, 'w') as f: f.write('{0}:{1}:{2}'.format(currentKodiSkin(), VERSION, OLD_API and ':old' or '')) except: util.ERROR() return default util.DEBUG_LOG('Using custom fonts for: {0}'.format(skin)) return os.path.join( xbmc.translatePath(util.ADDON.getAddonInfo('profile')).decode('utf-8'), 'skin')
def createDevice(self, packet, address): try: header = packet[:4] data = packet[4:-4] chksum = packet[-4:] self.responseType, packetLength = struct.unpack('>HH', header) if not self.responseType == DISCOVER_RESPONSE: util.DEBUG_LOG('WRONG RESPONSE TYPE') return None if packetLength != len(data): util.DEBUG_LOG('BAD PACKET LENGTH') return None if chksum != struct.pack('>I', crc32c.cksum(header + data)): util.DEBUG_LOG('BAD CRC') return None except: traceback.print_exc() return None dataIO = StringIO.StringIO(data) tag, length = struct.unpack('>BB', dataIO.read(2)) deviceType = struct.unpack('>I', dataIO.read(length))[0] if deviceType == TUNER_DEVICE: return self.processData(TunerDevice(address), dataIO) elif deviceType == STORAGE_SERVER: return self.processData(StorageServer(address), dataIO) else: return self.processData(Device(address), dataIO)
def search(deviceAuth, category='', terms=''): url = None if terms: url = SEARCH_URL.format(deviceAuth=urllib.quote(deviceAuth, ''), search=urllib.quote(terms.encode('utf-8'), '')) elif category: url = SUGGEST_URL.format(deviceAuth=urllib.quote(deviceAuth, ''), category=category) if not url: util.DEBUG_LOG('Search: No category or terms') return util.DEBUG_LOG('Search URL: {0}'.format(url)) req = requests.get(url) try: results = req.json() if not results: return [] return [Series(r) for r in results] except: util.ERROR() return None
def discover(self, device=None): import netif ifaces = netif.getInterfaces() sockets = [] for i in ifaces: if not i.broadcast: continue #if i.ip.startswith('127.'): continue s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) s.settimeout(0.01) #10ms s.bind((i.ip, 0)) s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) sockets.append((s, i)) payload = struct.pack('>BBI', 0x01, 0x04, 0xFFFFFFFF) #Device Type Filter (any) payload += struct.pack('>BBI', 0x02, 0x04, 0xFFFFFFFF) #Device ID Filter (any) header = struct.pack('>HH', 0x0002, len(payload)) data = header + payload crc = crc32c.cksum(data) packet = data + struct.pack('>I', crc) util.DEBUG_LOG(' o-> Broadcast Packet({0})'.format( binascii.hexlify(packet))) for attempt in (0, 1): for s, i in sockets: util.DEBUG_LOG(' o-> Broadcasting to {0}: {1}'.format( i.name, i.broadcast)) try: s.sendto(packet, (i.broadcast, DEVICE_DISCOVERY_PORT)) except: util.ERROR() end = time.time() + 0.25 #250ms while time.time() < end: for s, i in sockets: try: message, address = s.recvfrom(8096) added = self.add(message, address) if added: util.DEBUG_LOG( '<-o Response Packet[{0}]({1})'.format( i.name, binascii.hexlify(message))) elif added == False: util.DEBUG_LOG( '<-o Response Packet[{0}](Duplicate)'.format( i.name)) elif added == None: util.DEBUG_LOG( '<-o INVALID RESPONSE[{0}]({1})'.format( i.name, binascii.hexlify(message))) except socket.timeout: pass except: traceback.print_exc()
def showHub(self, hub, items=None): identifier = re.sub('\.\d+$', '', hub.hubIdentifier) if identifier in self.HUBMAP: util.DEBUG_LOG('Hub: {0} ({1})'.format(identifier, len(hub.items))) self._showHub(hub, hubitems=items, **self.HUBMAP[identifier]) return True else: util.DEBUG_LOG('UNHANDLED - Hub: {0} ({1})'.format(hub.hubIdentifier, len(hub.items))) return
def _modify(self, url, mtype): util.DEBUG_LOG('{0} rule: {1}'.format(mtype.title(), url)) try: req = requests.get(url) util.DEBUG_LOG('{0} rule response: {1}'.format(mtype.title(), repr(req.text))) except: e = util.ERROR() raise errors.RuleModException(e) return req.json()
def slideshow(self): util.DEBUG_LOG('Slideshow: STARTED') self.slideshowRunning = True self.resetSlideshowTimeout() while not util.MONITOR.waitForAbort(0.1) and self.slideshowRunning: if not self.slideshowNext or time.time() < self.slideshowNext: continue next(self) util.DEBUG_LOG('Slideshow: STOPPED')
def deleteRecording(self, recording, rerecord=False): try: url = recording.cmdURL + '&cmd=delete' + (rerecord and '&rerecord=1' or '') util.DEBUG_LOG('Delete recording URL: {0}'.format(url)) req = requests.get(url) util.DEBUG_LOG('Delete recording response: {0}'.format(repr(req.text))) self.updateRecordings() return True except: e = util.ERROR() raise errors.RecordingDelException(e)
def sessionEnded(self, session_id=None, **kwargs): if session_id != id(self): util.DEBUG_LOG( 'VideoPlayerWindow: Ignoring session end (ID: {0} - SessionID: {1})' .format(id(self), session_id)) return util.DEBUG_LOG( 'VideoPlayerWindow: Session ended - closing (ID: {0})'.format( id(self))) self.doClose()
def addTeamRule(self, team, **kwargs): url = RULES_ADD_TEAM_URL.format(deviceAuth=urllib.quote( self._devices.apiAuthID(), ''), team=team) if kwargs: url += '&' + urllib.urlencode(kwargs) util.DEBUG_LOG('Team rule add URL: {0}'.format(url)) resp = RecordingRule._modify(url, 'add') util.DEBUG_LOG('Team rule add response: {0}'.format(repr(resp)))
def onPlayBackSeek(self, time, offset): if self.seeking: return self.seeking = True self.trickWindow.setPosition(self.absolutePosition) self.trickWindow.unBlank() if self.player.isPlayingVideo(): util.DEBUG_LOG('Player (Recording): Stopping video for seek') self.player.stop() util.DEBUG_LOG( 'Player (Recording): Seek started at {0} (absolute: {1})'.format( self.position, self.absolutePosition))
def _collectLineUp(self): if not self.devices.hasTunerDevices: util.DEBUG_LOG('ERROR: No tuner devices responded!') raise errors.NoTunersException() lineUps = [] err = None for d in self.devices.tunerDevices: try: lineUp = d.lineUp() if lineUp: lineUps.append((d, lineUp)) except: err = util.ERROR() continue if not lineUps: if err: util.LOG('ERROR: No compatible devices found!') raise errors.NoCompatibleDevicesException() else: util.DEBUG_LOG('ERROR: Empty lineup!') raise errors.EmptyLineupException() hideDRM = not util.getSetting('show.DRM', False) while lineUps: lowest = min( lineUps, key=lambda l: l[1] and chanTuple(l[1][0]['GuideNumber'], l[0]. channelCount) or (0, 0, 0) ) #Prefer devices with the most channels assuming (possibly wrongly) that they are getting a better signal if not lowest[1]: lineUps.pop(lineUps.index(lowest)) continue chanData = lowest[1].pop(0) if hideDRM and chanData.get('DRM'): continue channelNumber = chanData['GuideNumber'] if '.' in channelNumber: self.hasSubChannels = True if channelNumber in self.channels: self.channels[chanData['GuideNumber']].add(chanData, lowest[0]) else: self.channels[chanData['GuideNumber']] = Channel( chanData, lowest[0]) if not self.channels: util.DEBUG_LOG(lineUps)
def getSeriesRule(self, series_id): url = RULES_URL.format(deviceAuth=urllib.quote(self._devices.apiAuthID(), '')) + '&SeriesID={0}'.format(series_id) util.DEBUG_LOG('Get series rule URL: {0}'.format(url)) req = requests.get(url) util.DEBUG_LOG('Get series rule response: {0}'.format(repr(req.text))) data = req.json() if not data: return None for r in data: if not 'DateTimeOnly' in r and not 'TeamOnly' in r: return RecordingRule(r).init(self) return None
def hideSeries(self,series): try: url = SUGGEST_URL.format(deviceAuth=urllib.quote(self._devices.apiAuthID(), ''),command=series.hidden and 'unhide' or 'hide',seriesID=series.ID) util.DEBUG_LOG('Series hide URL: {0}'.format(url)) req = requests.get(url) if 'SuggestHide' in series: del series['SuggestHide'] else: series['SuggestHide'] = 1 util.DEBUG_LOG('Series hide response: {0}'.format(repr(req.text))) except: e = util.ERROR() raise errors.SeriesHideException(e)
def skipNextButtonClicked(self): if not xbmc.getCondVisibility('MusicPlayer.HasNext') and self.playlist and self.playlist.isRemote: util.DEBUG_LOG('MusicPlayer: No next in Kodi playlist - refreshing remote PQ') if not self.playlist.refresh(force=True, wait=True): return xbmc.executebuiltin('PlayerControl(Next)')
def roleClicked(self): mli = self.rolesListControl.getSelectedItem() if not mli: return sectionRoles = busy.widthDialog(mli.dataSource.sectionRoles, '') if not sectionRoles: util.DEBUG_LOG('No sections found for actor') return if len(sectionRoles) > 1: x, y = self.getRoleItemDDPosition() options = [{ 'role': r, 'display': r.reasonTitle } for r in sectionRoles] choice = dropdown.showDropdown(options, (x, y), pos_is_bottom=True, close_direction='bottom') if not choice: return role = choice['role'] else: role = sectionRoles[0] self.processCommand(opener.open(role))
def checkWindow(self,newN): winID = xbmcgui.getCurrentWindowId() dialogID = xbmcgui.getCurrentWindowDialogId() if dialogID != 9999: winID = dialogID if winID == self.winID: return newN self.winID = winID self.updateWindowReader() if util.DEBUG: util.DEBUG_LOG('Window ID: {0} Handler: {1} File: {2}'.format(winID,self.windowReader.ID,xbmc.getInfoLabel('Window.Property(xmlfile)'))) name = self.windowReader.getName() if name: self.sayText(u'{0}: {1}'.format(T(32105),name),interrupt=not newN) self.insertPause() else: self.sayText(u' ',interrupt=not newN) heading = self.windowReader.getHeading() if heading: self.sayText(heading) self.insertPause() texts = self.windowReader.getWindowTexts() if texts: self.insertPause() for t in texts: self.sayText(t) self.insertPause() return True
def end(self): if util.DEBUG: xbmc.sleep(500) #Give threads a chance to finish import threading util.LOG('Remaining Threads:') for t in threading.enumerate(): util.DEBUG_LOG(' {0}'.format(t.name))
def playVideo(self, prev=False): self.cancelTimer() try: if not self.next and self.playlist: if prev: self.playlist.prev() self.aborted = False self.playQueue = self.playlist self.video = None self.play(handler=self.handler) else: video = self.next if prev: video = self.prev if not video: util.DEBUG_LOG( 'Trying to play next video with no next video available' ) self.video = None return self.playQueue = None self.video = video self.play(handler=self.handler) except: util.ERROR()
def set(self, val): old = self.get() if old != val: util.DEBUG_LOG('Setting: {0} - changed from [{1}] to [{2}]'.format( self.ID, old, val)) plexnet.plexapp.APP.trigger('change:{0}'.format(self.ID)) return util.setSetting(self.ID, val)
def setPosition(self, position): position = min(position, self.maxTimestamp) self.setProperty('current', util.durationToShortText(position)) util.DEBUG_LOG('TrickMode: Setting position at {0} of {1}'.format( position, self.duration)) if not (self.maxTimestamp): return self.setProgress(position) self.setProgressSelect(position) if self.bif: i = -1 for i, frame in enumerate(self.bif.frames): if position > frame['timestamp']: continue break i -= 1 if i >= 0: self.select = i else: timestamp = 0 for i, segment in enumerate(self.playlist.segments): timestamp += segment.duration if timestamp > position: self.select = i break else: self.select = 0
def onVideoWindowClosed(self): util.DEBUG_LOG('Player: Video window closed') try: self.handler.onVideoWindowClosed() self.stop() except: util.ERROR()
def onVideoWindowClosed(self): if not self.seeking: if self.player.isPlayingVideo(): util.DEBUG_LOG( 'Player (Recording): Stopping video on video window closed' ) self.player.stop()
def onReInit(self): if self.lastFocusID: # try focusing the last focused ID. if that's a hub and it's empty (=not focusable), try focusing the # next best hub if 399 < self.lastFocusID < 500: hubControlIndex = self.lastFocusID - 400 if hubControlIndex in self.hubFocusIndexes and self.hubControls[hubControlIndex]: util.DEBUG_LOG("Re-focusing %i" % self.lastFocusID) self.setFocusId(self.lastFocusID) else: util.DEBUG_LOG("Focus requested on %i, which can't focus. Trying next hub" % self.lastFocusID) self.focusFirstValidHub(hubControlIndex) else: self.setFocusId(self.lastFocusID)
def _removeRule(self, ruleID): rule = self.getRuleById(ruleID) if not rule: util.DEBUG_LOG( 'StorageServers: Attempted to remove rule not in list') return self._rules.pop(self._rules.index(rule))
def cancelTasks(self): if not self._tasks: return util.DEBUG_LOG('Canceling {0} show tasks'.format(len(self._tasks))) for t in self._tasks: t.cancel() self._tasks = []
def _sectionReallyChanged(self): section = self.lastSection self.setProperty('hub.focus', '') util.DEBUG_LOG('Section changed ({0}): {1}'.format( section.key, repr(section.title))) self.showHubs(section) self.lastSection = section self.checkSectionItem(force=True)
def addData(self): util.DEBUG_LOG('NOW SHOWING: Adding data') self.atEnd = False self.data = self.getData(self.highestStart + 1) if not self.data: self.atEnd = True raise EndOfNowShowingException() self.createBuckets(add=True)