class OSC_MPD(object): def __init__(self, osc=('0.0.0.0', 8000), mpd=('127.0.0.1', 6600)): self.mpc = MPDClient() self.mpc.connect(mpd[0], mpd[1]) self.server = OSCServer(osc) def musicManage(addr, tags, data, client_address): cmd = addr.strip('/').split('/')[-1] self.mpc.__getattr__(cmd)(*data) self.server.addMsgHandler('/bearstech/music/play', musicManage) self.server.addMsgHandler('/bearstech/music/pause', musicManage) self.server.addMsgHandler('/bearstech/music/next', musicManage) self.server.addMsgHandler('/bearstech/music/previous', musicManage) self.server.addMsgHandler('/bearstech/music/stop', musicManage) def serve_forever(self): self.server.serve_forever()
class __MPC(object): _mpdc = None _host = DEFAULT_CONFIG['host'] _port = DEFAULT_CONFIG['port'] verbose = bool(int(DEFAULT_CONFIG['verbose'])) debug = bool(int(DEFAULT_CONFIG['debug'])) # Switch automatically to created buffers autoswitch = bool(int(DEFAULT_CONFIG['autoswitch'])) # State symbols state_chars = { 'pause':DEFAULT_CONFIG['ch_pause'], 'play':DEFAULT_CONFIG['ch_play'], 'stop':DEFAULT_CONFIG['ch_stop'], } def __init__(self, wc_buffer=None): object.__init__(self) self._mpdc = MPDClient() self._commands = self._mpdc._commands self.wcb = wc_buffer self.verbose = bool(int((wc.config_get_plugin("verbose")))) self.debug = bool(int((wc.config_get_plugin("debug")))) self.autoswitch = bool(int((wc.config_get_plugin("autoswitch")))) for k, v in self.state_chars.iteritems(): self.state_chars[k] = wc.config_get_plugin('ch_' + k) self._commands['np'] = None @property def shortstats(self): return wc.config_get_plugin("shortstats") def __getattribute__(self, attr): try: return object.__getattribute__(self, attr) except AttributeError: return self._mpdc.__getattr__(attr) def _get_status(self, key): return self._mpdc.status()[key] def _print_current(f): """Do `f`, then prints the short_status in the buffer. """ def pf(self, *args, **kwargs): robj = f(self, *args, **kwargs) if not self.verbose: return robj # Show the status in the current buffer csong = self._mpdc.currentsong() csong.update({'state':self.state_chars[self._get_status('state')]}) wc.prnt(self.wcb or wc.current_buffer(), Template(self.shortstats).safe_substitute(csong)) return robj return pf def connect(self): self._host = wc.config_get_plugin("host") self._port = int(wc.config_get_plugin("port")) self._mpdc.connect(host=self._host, port=self._port) pw = wc.config_get_plugin("password") if len(pw) > 0: self._mpdc.password(pw) if self.debug: wc.prnt(self.wcb or wc.current_buffer(), 'mpc debug: Connected') def currentsong(self): ds = self._mpdc.currentsong() itime = int(ds['time']) ipos = int(ds['pos']) pct = int(100 * (ipos / itime)) ds.update({ "title_or_file" : ds['title'] or splitext(basename(ds['file']))[0], "pos_sec" : "%02d" % (ipos / 60), "pos_min" : str(ipos / 60), "length_sec" : "%02d" % (itime % 60), "length_min" : str(itime / 60), "pct" : "%2.0f" % pct, }) return ds def np(self): """Pushes result of np template substitution to current buffer. """ ds = self.currentsong() if len(ds) == 0: wc.prnt(wc.current_buffer(), "MPC: ERROR: mpd is stopped") return wc.command(wc.current_buffer(), Template(wc.config_get_plugin("format")).safe_substitute(ds)) @_print_current def next(self): self._mpdc.next() @_print_current def pause(self): self._mpdc.pause() @_print_current def play(self, *args): self._mpdc.play() def playlist(self, *args): def ifn( b, s, d): wc.prnt(b, Template(s).safe_substitute(d)) def cfn(): wc.prnt(None, "mpc closing playlist buffer") new_buf = wc.buffer_new('mpc: playlist', "ifn", "", "cfn", "") wc.buffer_set(new_buf, "localvar_set_no_log", "1") pl = self._mpdc.playlist() for line in pl: wc.prnt(new_buf, line) wc.buffer_set(new_buf, "display", "1") return pl def playlistinfo(self, sortkey='pos'): """Shows playlist information sorted by key """ new_buf = wc.buffer_search("", "mpc: playlist") if len(new_buf) == 0: new_buf = wc.buffer_new('mpc: playlist', "", "", "", "") pl = self._mpdc.playlistinfo() try: # Numerical sort spl = sorted(pl, cmp=lambda x,y: cmp(int(x), int(y)), key=itemgetter(sortkey)) except ValueError: # Alpha sort lcmp = lambda x,y: cmp(x.lower(), y.lower()) spl = sorted(pl, cmp=lambda x,y: cmp(x.lower(), y.lower()), key=itemgetter(sortkey)) t = Template(wc.config_get_plugin("playinfo")) for line in spl: wc.prnt(new_buf, t.safe_substitute(line)) return pl @_print_current def previous(self): self._mpdc.previous() def random(self, *args): """Toggles randomness if no argument is given. """ if len(args) == 0: args = [int(not int(self._get_status('random'))),] self._mpdc.random(*args) @_print_current def stop(self, *args): self._mpdc.stop()
class __MPC(object): _mpdc = None _host = DEFAULT_CONFIG['host'] _port = DEFAULT_CONFIG['port'] verbose = bool(int(DEFAULT_CONFIG['verbose'])) debug = bool(int(DEFAULT_CONFIG['debug'])) # Switch automatically to created buffers autoswitch = bool(int(DEFAULT_CONFIG['autoswitch'])) # State symbols state_chars = { 'pause':DEFAULT_CONFIG['ch_pause'], 'play':DEFAULT_CONFIG['ch_play'], 'stop':DEFAULT_CONFIG['ch_stop'], } def __init__(self, wc_buffer=None): object.__init__(self) self._mpdc = MPDClient() self._commands = self._mpdc._commands self.wcb = wc_buffer self.verbose = bool(int((wc.config_get_plugin("verbose")))) self.debug = bool(int((wc.config_get_plugin("debug")))) self.autoswitch = bool(int((wc.config_get_plugin("autoswitch")))) for k, v in self.state_chars.iteritems(): self.state_chars[k] = wc.config_get_plugin('ch_' + k) self._commands['np'] = None @property def shortstats(self): return wc.config_get_plugin("shortstats") def __getattribute__(self, attr): try: return object.__getattribute__(self, attr) except AttributeError: return self._mpdc.__getattr__(attr) def _get_status(self, key): return self._mpdc.status()[key] def _print_current(f): """Do `f`, then prints the short_status in the buffer. """ def pf(self, *args, **kwargs): robj = f(self, *args, **kwargs) if not self.verbose: return robj # Show the status in the current buffer csong = self._mpdc.currentsong() csong.update({'state':self.state_chars[self._get_status('state')]}) wc.prnt(self.wcb or wc.current_buffer(), Template(self.shortstats).safe_substitute(csong)) return robj return pf def connect(self): self._host = wc.config_get_plugin("host") self._port = int(wc.config_get_plugin("port")) self._mpdc.connect(host=self._host, port=self._port) pw = wc.config_get_plugin("password") if len(pw) > 0: self._mpdc.password(pw) if self.debug: wc.prnt(self.wcb or wc.current_buffer(), 'mpc debug: Connected') def currentsong(self): ds = self._mpdc.currentsong() itime = int(ds['time']) ipos = int(ds['pos']) pct = int(100 * (ipos / itime)) ds.update({ "title_or_file" : ds['title'] or splitext(basename(ds['file']))[0], "pos_sec" : "%02d" % (ipos / 60), "pos_min" : str(ipos / 60), "length_sec" : "%02d" % (itime % 60), "length_min" : str(itime / 60), "pct" : "%2.0f" % pct, "bitrate" : self._get_status('bitrate') + "kbps", }) return ds def np(self): """Pushes result of np template substitution to current buffer. """ ds = self.currentsong() if len(ds) == 0: wc.prnt(wc.current_buffer(), "MPC: ERROR: mpd is stopped") return wc.command(wc.current_buffer(), Template(wc.config_get_plugin("format")).safe_substitute(ds)) @_print_current def next(self): self._mpdc.next() @_print_current def pause(self): self._mpdc.pause() @_print_current def play(self, *args): self._mpdc.play() def playlist(self, *args): def ifn( b, s, d): wc.prnt(b, Template(s).safe_substitute(d)) def cfn(): wc.prnt(None, "mpc closing playlist buffer") new_buf = wc.buffer_new('mpc: playlist', "ifn", "", "cfn", "") wc.buffer_set(new_buf, "localvar_set_no_log", "1") pl = self._mpdc.playlist() for line in pl: wc.prnt(new_buf, line) wc.buffer_set(new_buf, "display", "1") return pl def playlistinfo(self, sortkey='pos'): """Shows playlist information sorted by key """ new_buf = wc.buffer_search("", "mpc: playlist") if len(new_buf) == 0: new_buf = wc.buffer_new('mpc: playlist', "", "", "", "") pl = self._mpdc.playlistinfo() try: # Numerical sort spl = sorted(pl, cmp=lambda x,y: cmp(int(x), int(y)), key=itemgetter(sortkey)) except ValueError: # Alpha sort lcmp = lambda x,y: cmp(x.lower(), y.lower()) spl = sorted(pl, cmp=lambda x,y: cmp(x.lower(), y.lower()), key=itemgetter(sortkey)) t = Template(wc.config_get_plugin("playinfo")) for line in spl: wc.prnt(new_buf, t.safe_substitute(line)) return pl @_print_current def previous(self): self._mpdc.previous() def random(self, *args): """Toggles randomness if no argument is given. """ if len(args) == 0: args = [int(not int(self._get_status('random'))),] self._mpdc.random(*args) @_print_current def stop(self, *args): self._mpdc.stop()
class MPDPrinter(Printer): def __init__(self,**kwargs): self.PAGES = ['PLAYER', 'OPTIONS'] # configurable variables self.mpdhost = 'localhost' self.mpdport = 6600 super(MPDPrinter,self).__init__(**kwargs) self.TASKS = ['player', 'playlist', 'options', 'mixer', 'update'] self.DEPS = { self.PAGE.PLAYER: ['player', 'playlist'], self.PAGE.OPTIONS: ['options', 'mixer', 'update'], } # internal variables self._mpd = MPDClient() self._thread = None def init_layout(self): super(MPDPrinter,self).init_layout() page = Page(self.lcd,idx=self.PAGE.PLAYER) self.statetext = page.add(Text(width=1)) self.songtext = page.add(ScrollText(width=page.cols-1)) page.newline() self.plstext = page.add(ScrollText(width=5)) self.timetext = page.add(ScrollText(width=page.cols-self.plstext.width)) self.pages.append(page) page = Page(self.lcd,idx=self.PAGE.OPTIONS) self.opttext = page.add(CycleText(width=11)) self.volumetext = page.add(Text(width=page.cols-self.opttext.width)) page.newline() self.updatetext = CycleText( [ chr(LCD.SYM_UP) + "Update " + chr(LCD.SYM_DOWN) + "Up RAM ", chr(LCD.SYM_LEFT) + "Vol- " + chr(LCD.SYM_RIGHT)+ "Vol+ ", ], width=page.cols-1) page.add(self.updatetext) self.updatestatus = page.add(Text(width=1)) self.pages.append(page) self.set_active(self.PAGE.PLAYER) def __del__(self): self.stop() def stop(self): if not self._thread: return self._thread.stop() self._thread = None def init(self): if not self._thread: self._thread = MPDThread(self.mpdhost,self.mpdport,self.logger) self._thread.start() self.lcd.set_color(*self.color) self.set_active(self.PAGE.PLAYER) self.render(True) def render(self,force=False): changed = self._thread.pop_data() if not changed: changed = [] deps = self.DEPS[self.active] changed = [ i for i in changed if i in deps ] if force: changed += deps self.update(list(set(changed))) super(MPDPrinter,self).render(force) def update(self,changed=[]): self._mpd.connect(self.mpdhost, self.mpdport) status = self._mpd.status() if len(changed): current = self._mpd.currentsong() self._mpd.disconnect() timetext = '/'.join( [ strtime(i) for i in status.get('time', '0:0').split(':') ]) self.timetext.setText( timetext.rjust(self.timetext.width)) if not len(changed): return if 'player' in changed and not 'playlist' in changed: changed.append('playlist') self.logger.debug( '%s updating %s' % (type(self).__name__,str(changed))) for i in changed: if i == 'player': #print current artist = current.get('artist',None) album = current.get('album' ,None) title = current.get('title' ,None) genre = current.get('genre' ,None) items = [] if artist: items.append(artist) if album and genre and genre in ['Books & Spoken', 'Drama', 'Podcast']: items.append(album) if title: items.append(title) songtext = " - ".join(items) self.songtext.setText(songtext) state = status['state'] if state == 'play': state = LCD.SYM_PLAY elif state == 'pause': state = LCD.SYM_PAUSE else: state = LCD.SYM_STOP self.statetext.setText(chr(state)) elif i == 'playlist': plstext = ("%d/%d" % (int(status.get('song', '-1'))+1,int(status.get('playlistlength', '-1')))) self.plstext.setText( plstext.ljust(self.plstext.width)) elif i == 'options': self.opttext.setList( [ 'Repeat '.ljust(8) + strswitch(int(status['repeat'])).rjust(3), 'Consume'.ljust(8) + strswitch(int(status['consume'])).rjust(3), 'Random '.ljust(8) + strswitch(int(status['random'])).rjust(3), 'Single '.ljust(8) + strswitch(int(status['single'])).rjust(3), ] ) elif i == 'mixer': volumetext = status['volume']+"%" self.volumetext.setText(volumetext.rjust(self.volumetext.width)) elif i == 'update': self.updatestatus.setText( chr(LCD.SYM_CLOCK) if status.get('updating_db', False) else ' ') elif i == 'sticker': pass else: self.logger.debug( "%s unhandled event %s" %( type(self).__name__, i)) def call_mpd(self,cmd, *args): self._mpd.connect(self.mpdhost, self.mpdport) ret = self._mpd.__getattr__(cmd)(*args) self._mpd.disconnect() return ret def toggle_play(self): self._mpd.connect(self.mpdhost, self.mpdport) status = self._mpd.status() if status['state'] == 'play': self._mpd.pause() else: self._mpd.play() self._mpd.disconnect() def button_clicked(self,btn): if self.active == self.PAGE.PLAYER: if btn == LCD.RIGHT: self.call_mpd('next') elif btn == LCD.LEFT: self.call_mpd('previous') super(MPDPrinter,self).button_clicked(btn) def button_pressed(self,btn,repeat): if self.active == self.PAGE.PLAYER: if (btn == LCD.LEFT or btn == LCD.RIGHT) and repeat: status = self.call_mpd('status') if not status.has_key('elapsed'): return secs = int(float(status['elapsed'])+0.5) songid = status['songid'] if btn == LCD.RIGHT: secs += 10 self.call_mpd('seek', songid, str(secs)) elif btn == LCD.LEFT: secs -= 10 self.call_mpd('seek', songid, str(secs)) elif btn == LCD.DOWN and not repeat: self.call_mpd('stop') elif btn == LCD.UP and not repeat: self.toggle_play() elif self.active == self.PAGE.OPTIONS: volumetext = self.volumetext.text[:-1] if len(volumetext): volume = int(volumetext) if btn == LCD.RIGHT: volume = min(volume+5,100) self.call_mpd('setvol', volume) self.volumetext.setText("%d%%" % volume) elif btn == LCD.LEFT: volume = max(volume-5,0) self.call_mpd('setvol', volume) self.volumetext.setText("%d%%" % volume) if btn == LCD.UP and not repeat: if self.updatestatus.text == ' ': self.show_splash('Updating all') self.call_mpd('update') else: self.show_splash('Update in\nprogress') elif btn == LCD.DOWN and not repeat: if self.updatestatus.text == ' ': self.show_splash('Updating ramdisk') self.call_mpd('update', 'RAMDISK') else: self.show_splash('Update in\nprogress') super(MPDPrinter,self).button_pressed(btn,repeat)