class Player(object): def __init__(self, media_dir): self.media_dir = media_dir self.player = None self.subtitles = True def play(self, filename): if self.player: self.player.quit() self.player = None video_path = Path(self.media_dir + filename) self.player = OMXPlayer(video_path, args=['--no-osd']) def quit(self): self.player.quit() self.player = None def pause(self): self.player.play_pause() def seek(self, val): self.player.set_position(val) def set_volume(self, val): self.player.set_volume(val) def toggle_subtitles(self): if self.subtitles: self.player.hide_subtitles() else: self.player.show_subtitles() self.subtitles = not self.subtitles def set_subtitle_track(self, val): self.player.select_subtitle(val) @property def status(self): if self.player != None: return { 'time': int(self.player.position()), 'length': int(self.player.duration()), 'volume': int(self.player.volume()), 'subtitle_tracks': self.player.list_subtitles() } return {'time': 0, 'length': 0, 'volume': 0, 'subtitle_tracks': []}
except Exception, e: print(time.strftime("%d-%m-%y %H:%M")) print(str(e)) print("problem init") kill_radio() lcd_string(" PLEASE RESTART ", LCD_LINE_2) time.sleep(5) f = open('/share/lastplay.txt', 'w') f.write(str(i)) f.close() lcd_string(radio_stations[i], LCD_LINE_1) else: try: lcd_string(" ".join([" PLAY", time.strftime("%H:%M")]), LCD_LINE_2) if (radio_player.volume() == 0): radio_player.set_volume(-2000) except: print(time.strftime("%d-%m-%y %H:%M")) print("No radioplayer found") lcd_string(" ERROR ", LCD_LINE_2) already_playing = False # Radio Station BBC if i == 5: # Increase sleep count sleep_count = sleep_count + 1 # After 20 seconds try scrobbling if sleep_count > 10: # reset sleep count sleep_count = 0
class VideoPlayer(object): def __init__(self): self.player = None self.logger = LogObject('Video Player') self.args = ['-b'] self.STATUS_MAP = { 'volume': self._videoVolume, 'length': self._videoLength, 'playback': self._playbackStatus, 'position': self._videoPosition } self.CONTROL_MAP = { 'playpause': self._playPause, 'stop': self._stop, 'mute': self._mute, 'unmute': self._unmute, 'play': self._play, 'pause': self._pause } self.SEEK_MAP = {'relative': self._seek, 'absolute': self._setPosition} def playUrl(self, url): if not self.player: self.player = OMXPlayer(url, args=self.args) else: self.player.load(url) def setVolume(self, volume): self._checkPlayerExist() try: self.player.set_volume(volume) return self.logger.writeAndReturnLog('VOL0003', {'volume': volume}) except (AttributeError, OMXPlayerDeadError): self._raisePlayerError('VOL0004') def sendCommand(self, command): self._checkPlayerExist() try: return self.CONTROL_MAP[command]() except (AttributeError, OMXPlayerDeadError): self._raisePlayerError('CTRL0003') def _stop(self): self.player.quit() return self.logger.writeAndReturnLog('CTRL0004') def _mute(self): self.player.mute() return self.logger.writeAndReturnLog('CTRL0006') def _unmute(self): self.player.unmute() return self.logger.writeAndReturnLog('CTRL0007') def _playPause(self): self.player.play_pause() return self.logger.writeAndReturnLog('CTRL0005') def _play(self): self.player.play() return self.logger.writeAndReturnLog('CTRL0008') def _pause(self): self.player.pause() return self.logger.writeAndReturnLog('CTRL0009') def seek(self, option, time): self._checkPlayerExist() try: return self.SEEK_MAP[option](time) except (AttributeError, OMXPlayerDeadError): self._raisePlayerError('SEEK0007') def _seek(self, seekTime): self.player.seek(seekTime) return self.logger.writeAndReturnLog('SEEK0005', {'position': seekTime}) def _setPosition(self, position): if position > self._videoLength() or position < 0: self._raisePlayerError('SEEK0004', {'position': position}) self.player.set_position(position) return self.logger.writeAndReturnLog('SEEK0006', {'position': position}) def _checkPlayerExist(self): if not self.player: self._raisePlayerError('CTRL0003') def videoStatus(self, status): if not self.player: self._raisePlayerError('STAT0003') try: return self.STATUS_MAP[status]() except (AttributeError, OMXPlayerDeadError): self._raisePlayerError('STAT0003') def _videoPosition(self): return self.player.position() def _videoLength(self): return self.player.duration() def _videoVolume(self): return self.player.volume() def _playbackStatus(self): return self.player.playback_status() def _raisePlayerError(self, logReference, variablesDict={}): returnMsg = self.logger.writeAndReturnLog(logReference, variablesDict) raise PlayerError(returnMsg)
class Omx: def __init__(self, media_folder): self.player = None self.media_folder = media_folder self.expects_loading_exit = False self.looping = False def play(self, filename, loop=False): if self.player: self.expects_loading_exit = True self.player.load(filename) else: args = ['-b', '--no-osd', '-o', 'both'] if loop: args += ['--loop'] self.looping = True else: self.looping = False try: self.player = OMXPlayer(filename, args=args) except SystemError as e: print(e) self.player.stopEvent += self.on_player_stop self.player.exitEvent += self.on_player_exit def on_player_stop(self, player): self.player = None def on_player_exit(self, player, exit_status): if self.expects_loading_exit: self.expects_loading_exit = False else: self.player = None def stop(self): if not self.player: return self.player.stop() self.player = None def pause(self): if not self.player: return self.player.play_pause() def seek_fraction(self, fraction): if not self.player: return duration = self.player.duration() self.player.set_position(fraction * duration) def set_volume(self, volume): if not self.player: return if volume > 10: volume = 10 elif volume < 0: volume = 0 self.player.set_volume(volume) def get_source(self): """ Get player source and remove media folder """ source = self.player.get_source() if source.startswith(self.media_folder + "/"): return source[len(self.media_folder) + 1:] else: return source def status(self): if not self.player: return { 'status': 'stopped', 'source': None, } return { 'status': self.player.playback_status(), 'source': self.get_source(), 'position': self.player.position(), 'duration': self.player.duration(), 'volume': self.player.volume(), 'looping': self.looping, }
class OmxPlayer(): def __init__(self): self.player = None self.paired = False self.masterIp = None self.audio_volume = 100.0 # omxplayer callbacks def posEvent(self, a, b): print('Position event!' + str(a) + " " + str(b)) # print('Position: ' + str(player.position()) + "s") return def seekEvent(self, a, b): print('seek event! ' + str(b)) return def triggerStart(self, pathToTrack, withPause=False): # lrpi_player#105 # Audio output can be routed through hdmi or the jack, # if settings.json is corrupted, default to the hdmi settings_json = settings.get_settings() output_route = settings_json.get("audio_output") normalised_output_route = 'hdmi' omxArgs = [] if output_route == 'hdmi': normalised_output_route = 'hdmi' omxArgs += ['-w', '--layout', '5.1'] elif output_route == 'jack': normalised_output_route = 'local' omxArgs += ['-o', normalised_output_route] print('OUTPUT: ' + normalised_output_route) print('Full playing args: ' + str(omxArgs)) if not withPause: self.player = OMXPlayer( pathToTrack, args=omxArgs, dbus_name='org.mpris.MediaPlayer2.omxplayer0') sleep(0.25) elif withPause: self.player = OMXPlayer( pathToTrack, args=omxArgs, dbus_name='org.mpris.MediaPlayer2.omxplayer0', pause=True) # Might need to set the volume to 0 a different way, # for some tracks omxplayer plays a short, sharp, shock # before setting the volume to 0 self.player.set_volume(0) sleep(0.5) def primeForStart(self, pathToTrack): self.triggerStart(pathToTrack, withPause=True) def start(self, pathToTrack, syncTimestamp=None, master=False): print("Playing on omx... :", master) print("\n") print(pathToTrack) settings_json = settings.get_settings() volume = settings_json.get("audio_volume") try: if not master: if self.player: self.player.quit() self.player = None if syncTimestamp: pause.until(syncTimestamp) if self.player is None or syncTimestamp is None: self.triggerStart(pathToTrack) self.player.positionEvent += self.posEvent self.player.seekEvent += self.seekEvent # self.player.set_position(0) if volume is not None: self.audio_volume = volume print("Volume set to %s" % self.audio_volume) self.player.set_volume(float(self.audio_volume) / 100.0) print('synctime in omxplayer: ', ctime(syncTimestamp)) if master: self.player.play() return str(self.player.duration()) except Exception as e: print( "ERROR: Could not start player... but audio may still be playing!" ) print("Why: ", e) print("returning position 0...") return str(0) # action 16 is emulated keypress for playPause def playPause(self, syncTimestamp=None): print("Playpausing with syncTimeStamp: ", syncTimestamp) if syncTimestamp: pause.until(syncTimestamp) self.player.action(16) return str(self.player.duration()) def getPosition(self): return self.player.position() def getDuration(self): return str(self.player.duration()) def mute(self): print(self.player.volume()) self.player.mute() def volumeUp(self): print("upper: ", self.player.volume()) self.player.set_volume(self.player.volume() + 0.1) def volumeDown(self, interval): # If we're right at the end of the track, don't try to # lower the volume or else dbus will disconnect and # the server will look at though it's crashed if self.player.duration() - self.player.position() > 1: print("omx downer: ", self.player.volume()) if (self.player.volume() <= 0.07 or interval == 0): return False else: self.player.set_volume(self.player.volume() - ((1.0 / interval) / 4.0)) return True return False def seek(self, position, syncTimestamp=None): if self.player.can_seek(): self.player.set_position(self.player.duration() * (position / 100.0)) return self.player.duration() * (position / 100.0) def status(self, status): if self.player != None: print('status requested from omxplayer!') try: status["source"] = self.player.get_source() status["playerState"] = self.player.playback_status() status["canControl"] = self.player.can_control() status["position"] = self.player.position() status["trackDuration"] = self.player.duration() status["error"] = "" except Exception as e: status["playerState"] = "" status["canControl"] = False status[ "error"] = "Something went wrong with player status request: " + str( e) else: status["playerState"] = "" status["canControl"] = False status["error"] = "Player is not initialized!" status["paired"] = self.paired status["master_ip"] = self.masterIp return status def setPaired(self, val, masterIp): self.paired = val self.masterIp = masterIp print('paired set to: ', val) print('master_ip set to: ', masterIp) def exit(self, syncTimestamp=None): if syncTimestamp: pause.until(syncTimestamp) if self.player: self.player.quit() self.__del__() killOmx() else: return 1 def __del__(self): if self.player: self.player.quit() self.player = None killOmx() print("OMX died")
class PlaybackController(object): def __init__(self): self.player = None self.queue = [] self.current_playbackitem = None self.volume = 0.6 def __str__(self): if self.current_playbackitem: return f"{self.get_status()} {self.current_playbackitem.get_title()}. {len(self.queue)} items in queue." else: return f"{self.get_status()}. {len(self.queue)} items in queue." def get_title(self): if self.current_playbackitem: return self.current_playbackitem.get_title() else: return "Not playing anything." def _on_omxplayer_exit(self, player, exit_status): log.info("OMXPlayer exit: {}".format(exit_status)) self.player = None if exit_status == 0: self.current_playbackitem = None self._new_player() def _new_player(self): """Creates a new player by popping from queue.""" log.info("Creating new OMXplayer.") if self.player is not None: self.player.quit() if self.current_playbackitem is None: if len(self.queue) == 0: raise ValueError("Nothing to play.") else: self.current_playbackitem = self.queue.pop(0) log.info("Creating player for video: {}".format( self.current_playbackitem)) self.player = OMXPlayer(self.current_playbackitem.get_direct_url()) self.player.set_volume(self.volume) self.player.exitEvent.subscribe(self._on_omxplayer_exit) def add_single_url(self, url): n_item = PlaybackItem(url) if n_item is not None: self.queue.append(n_item) return True raise ValueError("Could not get URL") def playlist(self, url): log.info("Adding every videos from playlist to queue.") ydl = youtube_dl.YoutubeDL({ 'logger': log, 'extract_flat': 'in_playlist', 'ignoreerrors': True, }) with ydl: # Downloading youtub-dl infos result = ydl.extract_info(url, download=False) for i in result['entries']: logger.info("queuing video") if i != result['entries'][0]: try: if "://" not in i['url']: self.add_single_url("https://youtube.com/?v=" + i['url']) else: self.add_single_url(i['url']) except Exception as e: log.error("Could not enqueue " + i['url']) log.error(e) def play(self): if self.get_status() == "Playing": log.debug("Playback already playing.") return if self.player is None and len(self.queue) > 0: self._new_player() else: log.error("Nothing to play!") def stop(self): if self.player is not None: self.player.stop() self.player = None def playpause(self): if self.player is None: log.error("No player running.") if len(self.queue) > 0: self.play() else: self.player.play_pause() def pause(self): if self.get_status() == "Paused": log.debug("Playback is already paused.") return def seek(self, seconds): if self.player is None: raise Exception("Player is not running") self.player.seek(seconds) def change_volume(self, increment): self.volume += increment if self.volume < 0.0: self.volume = 0.0 elif self.volume > 1.0: self.volume = 1.0 if self.player is not None: self.player.set_volume(self.volume) def get_volume(self): if self.player is not None: return self.player.volume() else: return self.volume def get_status(self): if self.player is None: return "Stopped" try: return self.player.playback_status() except OMXPlayerDeadError: log.error("OMXPlayer is dead.") self.player = None return "Stopped" def next_video(self): self.stop() self.current_playbackitem = None self._new_player() def shutdown(self): self.stop()