def __init__(self, proxy, playername): super().__init__(proxy, playername) self._inited = False self._metadata = None self._songid = -1 self._playlist = -1 self._repeat = None self._single = None self._random = None self._state = None self._elapsed = Timer(100) self._send_cmd(Cmds.STATUS, sync=True) self._inited = True
def __init__(self, proxy, playername): super(MpdPlayer, self).__init__(proxy, playername) self._inited = False self._metadata = None self._songid = -1 self._playlist = -1 self._repeat = None self._single = None self._random = None self._state = None self._elapsed = Timer(100) self._send_cmd(Cmds.STATUS, sync=True) self._inited = True
class MpdPlayer(BasePlayer): CMD_HANDLERS = { Cmds.CURRENTSONG: '_handle_currentsong', Cmds.NEXT: None, Cmds.PAUSE: None, Cmds.PLAY: None, Cmds.PREVIOUS: None, Cmds.RANDOM: None, Cmds.REPEAT: None, Cmds.REPLAY_GAIN_MODE: None, Cmds.REPLAY_GAIN_STATUS: '_handle_replay_gain_status', Cmds.SEEK: None, Cmds.SEEKCUR: None, Cmds.SEEKID: None, Cmds.SETVOL: None, Cmds.SINGLE: None, Cmds.STATUS: '_handle_status', Cmds.STOP: None, } CHANGE_CMDS = { 'player': [Cmds.STATUS], 'options': [Cmds.STATUS], } STATUS_CHANGE_MAP = { 'songid': (int, 'track'), 'playlist': (int, 'track'), 'repeat': (int, 'repeat'), 'single': (int, 'repeat'), 'random': (int, 'shuffle'), 'state': ('_parse_status', 'status'), } def __init__(self, proxy, playername): super().__init__(proxy, playername) self._inited = False self._metadata = None self._songid = -1 self._playlist = -1 self._repeat = None self._single = None self._random = None self._state = None self._elapsed = Timer(100) self._send_cmd(Cmds.STATUS, sync=True) self._inited = True def _send_cmd(self, cmd, *args, **kwargs): """ Send a cmd. Can use sync=[True|False] to send in a blocking or non-blocking way. Default is non-blocking """ sync = False if 'sync' not in kwargs else kwargs['sync'] if cmd not in self.CMD_HANDLERS: raise RuntimeError('Unknown command: %s', cmd) handler = self.CMD_HANDLERS[cmd] if handler is not None: handler = getattr(self, handler) else: handler = self._handle_nothing if sync: self.proxy.send_command_sync(cmd, handler, *args) else: self.proxy.send_command(cmd, handler, *args) def _handle_status(self, status): logging.debug('status\n%s', status) changes = set() for prop, handler in self.STATUS_CHANGE_MAP.items(): if prop not in status: value = None else: func = handler[0] if not callable(func): func = getattr(self, func) value = func(status[prop]) if value != getattr(self, '_' + prop): logging.debug('prop %s changed to %s', prop, value) setattr(self, '_' + prop, value) changes.add(handler[1]) if 'track' in changes: if self._songid is None: self._metadata = Metadata() else: self._send_cmd(Cmds.CURRENTSONG, sync=True) if 'status' in changes: if self._state == STATUS.PAUSED: self._elapsed.pause() elif self._state == STATUS.PLAYING: self._elapsed.play() else: self._elapsed.stop() if self._state == STATUS.STOPPED: elapsed = 0 else: elapsed = float(status['elapsed']) * 1000 if self._elapsed.set_time(elapsed): changes.add('position') if not self._inited: # Initializing, do not emit the change signals changes = set() for change in changes: getattr(self, change + '_changed')() def _handle_currentsong(self, metadata): logging.debug('currentsong: %s', metadata) args = {} for key in ('title', 'artist', 'album'): if key in metadata: args[key] = metadata[key] if 'time' in metadata: args['length'] = int(metadata['time']) * 1000 if 'track' in metadata: args['tracknum'] = int(metadata['track'].split('/')[0]) self._metadata = Metadata(**args) @staticmethod def _parse_status(value): status_map = { 'play': STATUS.PLAYING, 'pause': STATUS.PAUSED, 'stop': STATUS.STOPPED, } if value not in status_map: raise RuntimeError('Unknown status ' + value) return status_map[value] def _handle_replay_gain_status(self, status): pass def _handle_nothing(self, *args): pass def handle_changes(self, changes): cmds = set() for change in changes: if change in self.CHANGE_CMDS: for cmd in self.CHANGE_CMDS[change]: cmds.add(cmd) logging.debug('changes: %s', changes) logging.debug('cmds: %s', cmds) for cmd in cmds: self._send_cmd(cmd) def get_status(self): return self._state def get_metadata(self): return self._metadata def get_position(self): return self._elapsed.time def get_caps(self): return set([CAPS.PLAY, CAPS.PAUSE, CAPS.NEXT, CAPS.PREV, CAPS.SEEK]) def get_repeat(self): if not self._repeat: return REPEAT.NONE if not self._single: return REPEAT.ALL return REPEAT.TRACK def set_repeat(self, mode): repeat_mode_map = { REPEAT.NONE: (0, 0), REPEAT.TRACK: (1, 1), REPEAT.ALL: (1, 0), } if mode not in repeat_mode_map: raise ValueError('Unknown repeat mode: %s', mode) self._repeat = repeat_mode_map[mode][0] self._single = repeat_mode_map[mode][1] self._send_cmd(Cmds.REPEAT, self._repeat) self._send_cmd(Cmds.SINGLE, self._single) def get_shuffle(self): return bool(self._random) def set_shuffle(self, shuffle): self._random = 1 if shuffle else 0 self._send_cmd(Cmds.RANDOM, self._random) def play(self): if self._state == STATUS.PAUSED: self._send_cmd(Cmds.PAUSE, 0) elif self._state == STATUS.STOPPED: self._send_cmd(Cmds.PLAY) def pause(self): self._send_cmd(Cmds.PAUSE, 1) def stop(self): self._send_cmd(Cmds.STOP) def prev(self): self._send_cmd(Cmds.PREVIOUS) def next(self): self._send_cmd(Cmds.NEXT) def set_position(self, pos): self._send_cmd(Cmds.SEEK, self._songid, int(pos // 1000)) def debug_info(self): ret = dbus.Dictionary(signature='sv') ret.update({ 'state': self._state, 'metadata': self._metadata.to_mpris1(), 'repeat': self._repeat, 'single': self._single, 'position': self.get_position() }) return ret
class MpdPlayer(BasePlayer): CMD_HANDLERS = { Cmds.CURRENTSONG: '_handle_currentsong', Cmds.NEXT: None, Cmds.PAUSE: None, Cmds.PLAY: None, Cmds.PREVIOUS: None, Cmds.RANDOM: None, Cmds.REPEAT: None, Cmds.REPLAY_GAIN_MODE: None, Cmds.REPLAY_GAIN_STATUS: '_handle_replay_gain_status', Cmds.SEEK: None, Cmds.SEEKCUR: None, Cmds.SEEKID: None, Cmds.SETVOL: None, Cmds.SINGLE: None, Cmds.STATUS: '_handle_status', Cmds.STOP: None, } CHANGE_CMDS = { 'player': [Cmds.STATUS], 'options': [Cmds.STATUS], } STATUS_CHANGE_MAP = { 'songid': ('int', 'track'), 'playlist': ('int', 'track'), 'repeat': ('int', 'repeat'), 'single': ('int', 'repeat'), 'random': ('int', 'shuffle'), 'state': ('_parse_status', 'status'), } def __init__(self, proxy, playername): super(MpdPlayer, self).__init__(proxy, playername) self._inited = False self._metadata = None self._songid = -1 self._playlist = -1 self._repeat = None self._single = None self._random = None self._state = None self._elapsed = Timer(100) self._send_cmd(Cmds.STATUS, sync=True) self._inited = True def _send_cmd(self, cmd, *args, **kwargs): """ Send a cmd. Can use sync=[True|False] to send in a blocking or non-blocking way. Default is non-blocking """ sync = False if 'sync' not in kwargs else kwargs['sync'] if cmd not in self.CMD_HANDLERS: raise RuntimeError('Unknown command: %s', cmd) handler = self.CMD_HANDLERS[cmd] if handler is not None: handler = getattr(self, handler) else: handler = self._handle_nothing if sync: self.proxy.send_command_sync(cmd, handler, *args) else: self.proxy.send_command(cmd, handler, *args) def _handle_status(self, status): logging.debug('status\n%s', status) changes = set() for prop, handler in self.STATUS_CHANGE_MAP.items(): if not prop in status: value = None else: funcname = handler[0] func = getattr(__builtin__, funcname) \ if not funcname.startswith('_') \ else getattr(self, funcname) value = func(status[prop]) if value != getattr(self, '_' + prop): logging.debug('prop %s changed to %s', prop, value) setattr(self, '_' + prop, value) changes.add(handler[1]) if 'track' in changes: if self._songid is None: self._metadata = Metadata() else: self._send_cmd(Cmds.CURRENTSONG, sync=True) if 'status' in changes: if self._state == STATUS_PAUSED: self._elapsed.pause() elif self._state == STATUS_PLAYING: self._elapsed.play() else: self._elapsed.stop() if self._state == STATUS_STOPPED: elapsed = 0 else: elapsed = float(status['elapsed']) * 1000 if self._elapsed.set_time(elapsed): changes.add('position') if not self._inited: # Initializing, do not emit the change signals changes = set() for change in changes: getattr(self, change + '_changed')() def _handle_currentsong(self, metadata): logging.debug('currentsong: %s', metadata) args = {} for key in ('title', 'artist', 'album'): if key in metadata: args[key] = metadata[key] if 'time' in metadata: args['length'] = int(metadata['time']) * 1000 if 'track' in metadata: args['tracknum'] = int(metadata['track'].split('/')[0]) self._metadata = Metadata(**args) def _parse_status(self, value): status_map = { 'play': STATUS_PLAYING, 'pause': STATUS_PAUSED, 'stop': STATUS_STOPPED, } if value not in status_map: raise RuntimeError('Unknown status ' + value) return status_map[value] def _handle_replay_gain_status(self, status): pass def _handle_nothing(self, *args): pass def handle_changes(self, changes): cmds = set() for change in changes: if change in self.CHANGE_CMDS: for cmd in self.CHANGE_CMDS[change]: cmds.add(cmd) logging.debug('changes: %s', changes) logging.debug('cmds: %s', cmds) for cmd in cmds: self._send_cmd(cmd) def get_status(self): return self._state def get_metadata(self): return self._metadata def get_position(self): return self._elapsed.time def get_caps(self): return set([CAPS_PLAY, CAPS_PAUSE, CAPS_NEXT, CAPS_PREV, CAPS_SEEK]) def get_repeat(self): if not self._repeat: return REPEAT_NONE if not self._single: return REPEAT_ALL return REPEAT_TRACK def set_repeat(self, mode): repeat_mode_map = { REPEAT_NONE: (0, 0), REPEAT_TRACK: (1, 1), REPEAT_ALL: (1, 0), } if mode not in repeat_mode_map: raise ValueError('Unknown repeat mode: %s', mode) self._repeat = repeat_mode_map[mode][0] self._single = repeat_mode_map[mode][1] self._send_cmd(Cmds.REPEAT, self._repeat) self._send_cmd(Cmds.SINGLE, self._single) def get_shuffle(self): return bool(self._random) def set_shuffle(self, shuffle): self._random = 1 if shuffle else 0 self._send_cmd(Cmds.RANDOM, self._random) def play(self): if self._state == STATUS_PAUSED: self._send_cmd(Cmds.PAUSE, 0) elif self._state == STATUS_STOPPED: self._send_cmd(Cmds.PLAY) def pause(self): self._send_cmd(Cmds.PAUSE, 1) def stop(self): self._send_cmd(Cmds.STOP) def prev(self): self._send_cmd(Cmds.PREVIOUS) def next(self): self._send_cmd(Cmds.NEXT) def set_position(self, pos): self._send_cmd(Cmds.SEEK, self._songid, int(pos / 1000)) def debug_info(self): ret = dbus.Dictionary(signature='sv') ret.update({ 'state': self._state, 'metadata': self._metadata.to_mpris1(), 'repeat': self._repeat, 'single': self._single, 'position': self.get_position() }) return ret