#!/usr/bin/env python
#usage: simple-mpc-remote [options]
#based on mplayer-remote v0.0.4, http://www.gwenn.dk/mplayer-remote.html
import BaseHTTPServer, commands, sys, os, pwd, grp, socket
from optparse import OptionParser
parser = OptionParser(description='%prog - a simple mpc web control', usage='%prog [options]')
parser.add_option("-p", "--port", dest="port", action="store", help='local port to bind (default 80).')
(options, args) = parser.parse_args()
if options.port:
port = int(options.port)
else:
port = 80
if port < 1024:
if not os.geteuid() == 0:
sys.exit(os.path.basename(__file__) + ": root permitions are necessary to bind to port " + str(port) + ", use -p to specify a non privileged port or run as root.")
# The following string variables contain the HTML code that we will
# serve to the client
# pagehead: Code that is common to all pages, including CSS code
# pageend: Code that is common to all pages, closing the HTML page
# pagectrl: Code for control widgets
pagehead = """
Remote mpc
"""
pagectrl = """
Mpd Control
"""
pageend = """
"""
ctrlcmd = { "%7C%3C" :"prev", # |<
"%3C%3C" :"seek -20%", # <<
"%3C" :"seek -5%", # <
"%3E%7C%7C" :"toggle", # >||
"%3E" :"seek +5%", # >
"%3E%3E" :"seek +20%", # >>
"%3E%7C" :"next", # >|
"quit" :"stop", # quit
"fullscreen":"vo_fullscreen" # fullscreen
}
volcmd = {"%2B" :"amixer --quiet set Master 1%+", #+
"-" :"amixer --quiet set Master 1%-", #-
"mute":"amixer --quiet set Master toggle"} #mute
def drop_privileges():
if os.getuid() != 0:
#we're not root so, whatever dude
return
#get the uid/gid from the name
user_name = os.getenv("SUDO_USER")
pwnam = pwd.getpwnam(user_name)
#remove group privileges
os.setgroups([])
#try setting the new uid/gid
os.setgid(pwnam.pw_gid)
os.setuid(pwnam.pw_uid)
#ensure a reasonable umask
old_umask = os.umask(0o22)
print "Dropping user privileges: root -> " + user_name
def execute(cmd):
""" Execute a shell command, while handling errors gracefully"""
(stat, out) = commands.getstatusoutput(cmd)
if stat != 0:
print >>sys.stderr, "ERROR: '"+cmd+"' returned "+ str(out)
return out
class myHandler(BaseHTTPServer.BaseHTTPRequestHandler):
"""Handles all http requests."""
def __init__(self, *args):
"""Initialise the handler (called each time we handle a request)"""
BaseHTTPServer.BaseHTTPRequestHandler.__init__(self, *args)
def write(self, x):
"""Send some html code to the browser"""
return self.wfile.write(x)
def handleCmd(self,param):
"""Global handler of commands, doesn't care what the page is, just
executes the correct commands if possible"""
if "mpc" in param:
if param["mpc"] in ctrlcmd:
self.write(execute("mpc " + ctrlcmd[param["mpc"]]))
print "exec: mpc " + ctrlcmd[param["mpc"]]
if "volume" in param:
if param["volume"] in volcmd:
self.write(execute(volcmd[param["volume"]]))
print "exec: " + volcmd[param["volume"]]
def volumebar(self):
"""Get the current volume setting and plot it as a "bar diagram", or
if muted, indicate this"""
out = execute("amixer get Master").split()
vol = execute("amixer get 'Master',0|egrep -m1 -o '[0-9]{1,3}%'")
if vol != "0%":
self.write('')
else:
self.write('')
def do_GET(self):
"""Handle the GET request. This identifies the page that is
being served, and handles the submitted form variables"""
self.send_response(200)
self.send_header('Content-type','text/html')
self.end_headers()
self.write(pagehead)
file = self.path.split('/')[-1]
paramstr=file.split('?')
print "args:", paramstr
param = {}
if len(paramstr) > 1:
for p in paramstr[1].split('&'):
s = p.split('=')
param[s[0]] = s[1]
self.handleCmd(param)
#self.volumebar()
self.write(pagectrl)
self.write(pageend)
class StoppableHTTPServer(BaseHTTPServer.HTTPServer):
"""
This is a simple change to the normal basehttp server which is
not blocked waiting for HTTP connections
"""
def server_bind(self):
BaseHTTPServer.HTTPServer.server_bind(self)
self.socket.settimeout(1)
self.run = True
def get_request(self):
while self.run:
try:
sock, addr = self.socket.accept()
sock.settimeout(None)
return (sock, addr)
except socket.timeout:
pass
def run():
"""
This is the "main" function, that gets called from the
end of the file, after everything has been parsed.
"""
try:
server = StoppableHTTPServer(('', port), myHandler)
print 'Started httpserver on port ' , port
drop_privileges()
server.serve_forever()
except KeyboardInterrupt:
print '^C received, shutting down the web server'
finally:
if 'server' in locals():
server.socket.close()
# Finally, just execute it all
run()