class Player: def __init__(self, appli): self.currVideo = None self.formatId = 0 self.subtitleId = -1 self.audioStreamId = 0 self.omxProcess = None self.currTotViewed = 0 self.lastPos = 0 self.appli = appli self.wasPlaying = False def LoadVideo(self, video): if self.isStarted(): self.stop() self.wasPlaying = False self.currVideo = video self.formatId = 0 self.subtitleId = -1 self.audioStreamId = 0 self.currTotViewed = 0 self.lastPos = 0 # Set the format of the video def setVideoFormat(self, formatId): if self.currVideo and formatId != self.formatId: # If the video has this format if self.currVideo.getFormat(formatId): oldFormat = self.formatId self.formatId = formatId if self.isStarted(): self.wasPlaying = False oldPos = self.getPosition() wasPlaying = self.isPlaying() # Try to play the new format but fallback on the previous one if it fails if self.tryPlayingFormat( formatId) or self.tryPlayingFormat(oldFormat): self.setPosition(oldPos) if not wasPlaying: self.playPause() else: return False return True return False # Set a different audio stream def setAudioFormat(self, formatId): try: if self.isStarted(): if self.omxProcess.select_audio(formatId): self.audioStreamId = formatId return True else: return False else: return False except: self.clearPlayer() return False # Set a subtitle track def setSubtitlesFormat(self, formatId): try: if self.isStarted(): if formatId > -1: self.omxProcess.show_subtitles() if self.omxProcess.select_subtitle(formatId): self.subtitleId = formatId return True else: return False else: self.subtitleId = -1 return self.omxProcess.hide_subtitles() else: return False except: self.clearPlayer() return False # Tries to play or pause the current video def playPause(self): if self.currVideo: if self.isStarted(): try: if self.isPlaying(): self.omxProcess.pause() else: self.omxProcess.play() return True except: self.clearPlayer() return False else: ok = False if self.formatId != 0: ok = self.tryPlayingFormat(self.formatId) if not ok: # Try to play formats starting from the highest resolution one for fid in range(1, len(self.currVideo.getFormatList())): if self.tryPlayingFormat(fid): ok = True break return ok return False def stop(self): self.wasPlaying = False try: if self.omxProcess: self.omxProcess.quit() self.omxProcess = None return True return False except: self.clearPlayer() return False # Tries to play a given format of the video def tryPlayingFormat(self, formatId): if self.isStarted(): self.stop() try: self.formatId = formatId print('Trying to play ', formatId, 'path:', self.currVideo.getRessourcePath(formatId)) self.omxProcess = OMXPlayer( self.currVideo.getRessourcePath(formatId), args=['-b']) # Wait a bit for loading before disqualifying the format while self.omxProcess.playback_status() == 'Paused': sleep(0.01) if self.isPlaying(): print('isplaying:True') return True except Exception as e: self.clearPlayer() print(str(e), str(self.currVideo.getFormatList())) # Handle the case in which the format couldn't be played self.stop() self.formatId = 0 return False def isPlaying(self): try: return self.omxProcess and self.omxProcess.is_playing() except: self.clearPlayer() return False def isStarted(self): try: return self.omxProcess and self.omxProcess.can_play() except: self.clearPlayer() return False def isPaused(self): return self.isStarted() and not self.isPlaying() def getPosition(self): try: if self.isStarted(): return self.omxProcess.position() else: return 0 except: self.clearPlayer() return 0 def getDuration(self): try: if self.isStarted(): return int(self.omxProcess.duration()) elif self.currVideo: return self.currVideo.duration else: return 1 except: self.clearPlayer() return 1 def getSubtitles(self): subs = {-1: 'None'} try: if self.isStarted(): for substr in self.omxProcess.list_subtitles(): idx, lng, name, cdc, actv = substr.split(':') subs[idx] = lng + (('-' + name) if len(name) > 0 else '') if actv: self.subtitleId = idx return subs except: self.clearPlayer() return subs def hasSubtitles(self): try: return self.isStarted() and len( self.omxProcess.list_subtitles()) > 0 except: self.clearPlayer() return False def getAudioStreams(self): auds = {} try: if self.isStarted(): for audstr in self.omxProcess.list_audio(): idx, lng, name, cdc, actv = audstr.split(':') auds[idx] = lng + (('-' + name) if len(name) > 0 else '') if actv: self.audioStreamId = idx return auds except: self.clearPlayer() return auds def hasAudioStreams(self): try: return self.isStarted() and len(self.omxProcess.list_audio()) > 1 except: self.clearPlayer() return False def hasVideoStreams(self): if self.currVideo: okFormatList = json.loads(self.currVideo.okFormatsList) return len(okFormatList) > 2 else: return False def getStatus(self): isPlaying = self.isPlaying() isPaused = self.isPaused() currPos = self.getPosition() dur = self.getDuration() if isPlaying or isPaused: self.wasPlaying = True self.currTotViewed += currPos - self.lastPos self.lastPos = currPos with self.appli.threadLock: if self.currTotViewed / dur > Parameters.get().viewedThreshold: self.currVideo.viewed = True self.currVideo.save() self.appli.updatePart('playlist') else: with self.appli.threadLock: pt = Parameters.get().autoRestartPosThresh if self.wasPlaying and pt < self.lastPos < self.getDuration() - pt: self.tryPlayingFormat(self.formatId) self.setPosition(self.lastPos) return { 'position': currPos, 'duration': dur, 'isPlaying': isPlaying, 'isPaused': isPaused } def setPosition(self, newPos): try: # If the video is not started, start it and jump to the position if self.isStarted() or self.playPause(): self.omxProcess.set_position(newPos) return True else: return False except: self.clearPlayer() return False def getFormatList(self): return self.currVideo.getFormatList() if self.currVideo else [] def getFormatListItems(self): return [(fid, f['name']) for fid, f in enumerate(self.getFormatList())] def clearPlayer(self): if self.omxProcess: try: self.omxProcess.quit() except: pass self.omxProcess = None