LCDd, MPD e Python

D.I.Y.  |    06/11/2011   |   13751 hits   |   J. Ricardo Simões Rodrigues

Já havia utilizado PHP para controlar o LCDproc via sockets. Agora utilizei Python para criar um daemon que exibe num LCD paralelo informações acerca da música sendo executada pelo MPD (Music Player Daemon).

MPD Playing]

As bibliotecas utilizadas são python-mpd (Python MPD client library) e lcdproc (Python OOP Wrapper Library for LCDproc Telnet API)

A instalação dessas bibliotecas é simples com

 sudo easy_install python-mpd 

e

sudo easy_install lcdproc 

O pequeno programa possui o seguinte código:

Daemon

#!/usr/bin/env python
# -*- coding: utf-8 -*-

# Copyright (C) 2011 Ricardo Simoes
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
# By reading this code you agree not to ridicule the author =)

# IMPORTS
import os
import sys
import pprint
import time
import datetime
import pprint
import math
import daemon

#http://pypi.python.org/pypi/lcdproc
from lcdserver import Lcdserver
#http://pypi.python.org/pypi/python-mpd/
from mpd import (MPDClient, CommandError)
from socket import error as SocketError

__version__="0.1"
__author__="ricardo at ricardosimoes.com"
__doc__="""PyMPDLCD v%s (c) 2011 Ricardo Simoes

PyMPDLCD is a program that sends status of the MPD daemon to the LCDproc daemon.

This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any later
version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place, Suite 330, Boston, MA 02111-1307, USA.

Please e-mail bugs to: %s""" % (__version__, __author__)




HOST = 'localhost'
PORT = '6600'
PASSWORD = False
##
CON_ID = {'host':HOST, 'port':PORT}
##

## Some functions
def mpdConnect(client, con_id):
"""
Simple wrapper to connect MPD.
"""
try:
client.connect(**con_id)
except SocketError:
return False
return True

def mpdAuth(client, secret):
"""
Authenticate
"""
try:
client.password(secret)
except CommandError:
return False
return True
##

def GetInHMS(seconds):
hours = seconds / 3600
seconds -= 3600*hours
minutes = seconds / 60
seconds -= 60*minutes
if hours == 0:
return "%02d:%02d" % (minutes, seconds)
return "%02d:%02d:%02d" % (hours, minutes, seconds)


def main():
## MPD object instance
client = MPDClient()
if mpdConnect(client, CON_ID):
print 'Got connected!'
else:
print 'fail to connect MPD server.'
sys.exit(1)

# Auth if password is set non False
if PASSWORD:
if mpdAuth(client, PASSWORD):
print 'Pass auth!'
else:
print 'Error trying to pass auth.'
client.disconnect()
sys.exit(2)

## Fancy output
pp = pprint.PrettyPrinter(indent=4)

status = dict()
stats = dict()
currentsong = dict()
infosong = dict()

## LCdproc object instance
lcd = Lcdserver("mpdlcd", debug=False)
lcd.start_session()
print '\nLCD:'
pp.pprint(lcd)

screenMpdInfo = lcd.add_screen("Screen1")
screenMpdInfo.set_heartbeat("off")
screenMpdInfo.set_duration(10)

string1_widget = screenMpdInfo.add_scroller_widget("MyScrollerWidget1", text="Title", speed=3, left=1, top=1, right=20, bottom=1)
string2_widget = screenMpdInfo.add_scroller_widget("MyScrollerWidget2", text="Artist/Album", speed=3, left=1, top=2, right=20, bottom=1)
string3_widget = screenMpdInfo.add_string_widget("MyStringWidget1", text="> 00:00/00/00 V0", x=1, y=3)
hbar_widget = screenMpdInfo.add_hbar_widget("MyHBarWidget", x=1, y=4, length=0)
showinfo = 1

while True:
status.update(client.status())
##pp.pprint(status)
if status['state'] == 'play':
stats.update(client.stats())
currentsong['title'] = "Unknown Track"
currentsong['artist'] = "Unknown Artist"
currentsong['album'] = "Unknown Album"

currentsong.update(client.currentsong())
##pp.pprint(stats)
##pp.pprint(currentsong)

string1_widget.set_text(currentsong['title'])
string2_widget.set_text("%s/%s" % (currentsong['artist'], currentsong['album']))

bits1 = status['time'].split(":")
bits2 = currentsong['time'].split(":")
playbar = math.floor((int(bits1[0]) * (20*5)) / int(bits2[0]))

if showinfo == 1:
info = "> %s/%s vl %s" % (GetInHMS(seconds=int(bits1[0])), GetInHMS(seconds=int(bits2[0])), status['volume'])
showinfo = showinfo + 1
elif showinfo == 2:
info = "> %s/%s %sk" % (GetInHMS(seconds=int(bits1[0])), GetInHMS(seconds=int(bits2[0])), status['bitrate'])
showinfo = showinfo + 1
elif showinfo == 3:
bits3 = status['audio'].split(":")
info = "> %s/%s %skHz" % (GetInHMS(seconds=int(bits1[0])), GetInHMS(seconds=int(bits2[0])), int(math.floor(int(bits3[0])/1000)))
showinfo = showinfo + 1
elif showinfo == 4:
bits3 = status['audio'].split(":")
info = "> %s/%s %sch" % (GetInHMS(seconds=int(bits1[0])), GetInHMS(seconds=int(bits2[0])), bits3[2])
showinfo = showinfo + 1
elif showinfo == 5:
bits3 = status['audio'].split(":")
info = "> %s/%s %s" % (GetInHMS(seconds=int(bits1[0])),
GetInHMS(seconds=int(bits2[0])),
(currentsong['file'][len(currentsong['file'])-3:].upper()))
showinfo = 1

string3_widget.set_text(info)
hbar_widget.set_length(playbar)


elif status['state'] == 'pause':
stats.update(client.stats())
currentsong.update(client.currentsong())
string1_widget.set_text(currentsong['title'])
string2_widget.set_text("%s/%s" % (currentsong['artist'], currentsong['album']))
bits1 = status['time'].split(":")
bits2 = currentsong['time'].split(":")
playbar = math.floor((int(bits1[0]) * (20*5)) / int(bits2[0]))
string3_widget.set_text("|| %s/%s vl %s" % (GetInHMS(seconds=int(bits1[0])),
GetInHMS(seconds=int(bits2[0])), status['volume']))
hbar_widget.set_length(playbar)
else:
string1_widget.set_text('MPD@%s:%s' % (HOST, PORT))
string2_widget.set_text("%s/%s" % ("", ""))
string3_widget.set_text("Stop %s/%s vl %s" % ("0:0", "0:0", status['volume']))
hbar_widget.set_length(100)

time.sleep(1)

client.disconnect()
sys.exit(0)

# Script starts here
if __name__ == "__main__":
procParams = "%s" % (os.getpid())
with daemon.DaemonContext():
pidfile = "/var/run/lcdmpdclient-daemon.pid"
if os.path.exists(pidfile):
sys.exit(1)
else:
open(pidfile, "w").write(procParams + "\n")
main()






O arquivo disponível para dowload em lcdmpdclient.py.

MPD Paused

MPD Stoped

Última edição concluída em 06/11/2011 por J. Ricardo Simões Rodrigues.