utility-scripts/backup_mpd_playlist.py

150 lines
5.0 KiB
Python
Raw Normal View History

2015-06-14 23:58:20 +00:00
#!/usr/bin/env python
2015-10-23 14:34:21 +00:00
# Back up the state of MPD (current playlist and so on)
2015-06-14 23:58:20 +00:00
import ast
import datetime
import os
import re
import sys
import pprint
import mpd
from optparse import OptionParser
2015-10-23 14:34:21 +00:00
from subprocess import Popen, PIPE
2015-06-14 23:58:20 +00:00
parser = OptionParser()
parser.add_option("-s", "--server", dest="host",
help="set the MPD hostname (default: localhost)", metavar="HOST")
parser.add_option("-p", "--port", dest="port",
help="set the MPD port (default: 6600)", metavar="6600")
parser.add_option("-d", dest="dest",
help="save or load the backup to directory <DIR>", metavar="DIR")
parser.add_option("-l", dest="load", action="store_true",
help="load the last backup")
parser.add_option("-f", "--file", dest="load_file",
help="load the backup in file <FILE>", metavar="FILE")
(options, args) = parser.parse_args()
host = options.host or 'localhost'
port = options.port or '6600'
2015-10-23 14:34:21 +00:00
#backup_dir = options.dest or '/var/lib/mpd/backups'
backup_dir = options.dest or '/home/tim/.mpd/backups'
2015-06-14 23:58:20 +00:00
now = datetime.datetime.now().strftime("%Y%m%d@%H:%M")
2015-10-23 14:34:21 +00:00
ps = Popen(['ps', 'ax'], shell=False, stdout=PIPE).communicate()[0]
if not re.search("\d+\s+mpd\s+", ps):
sys.exit()
2015-06-14 23:58:20 +00:00
client = mpd.MPDClient()
client.timeout = 10
client.idletimeout = 10
client.connect(host, port)
# Get the contents of the most recent backup
all_backups = [os.path.join(backup_dir, f) for f in os.listdir(backup_dir) if f.startswith('mpd_state')]
last_backup = max(all_backups, key=os.path.getctime) if all_backups else []
backup_output = open(last_backup).read() if last_backup else ''
if options.load or options.load_file:
# Override the last backup if the user desires
if options.load_file:
if not os.path.exists(options.load_file):
sys.exit("No such file: " + options.load_file)
backup_output = open(options.load_file).read()
# load file into backup_output
backup = ast.literal_eval(backup_output)
# Check server and port
if backup['src'] != host+":"+port:
if not sys.stdin.isatty():
sys.exit("Error: Backup is from a different server or port.")
c = raw_input("Error: Backup is from a different server or port. Continue? (y/N) ").rstrip('\n')
if c != 'Y' and c != 'y':
sys.exit("Exiting.")
# Clear playlist
client.clear()
# Load songs
for song in backup['playlist']:
try:
client.add(song)
except mpd.CommandError as e:
print("File not found: %s" % e)
pass
# Parse and communicate extra info
if 'repeat' in backup:
client.repeat(backup['repeat'])
if 'random' in backup:
client.random(backup['random'])
if 'single' in backup:
client.single(backup['single'])
if 'consume' in backup:
client.consume(backup['consume'])
id = None
if 'current' in backup:
for song in client.playlistinfo():
if song['file'] == backup['current']:
id = song['id']
print song['file']
print id
next
if not id:
print "Error: Can't find currently-playing song on playlist."
if 'time' in backup and id:
client.seekid(id, backup['time'])
if 'state' in backup:
if backup['state'] == 'play':
client.play()
elif backup['state'] == 'pause':
client.pause(1)
elif backup['state'] == 'stop':
client.stop()
# setvol returns an error, for some reason
# mpd.CommandError: [52@0] {setvol} problems setting volume
#if 'volume' in backup:
# client.setvol(backup['volume'])
else:
# Get current state
get_status = client.status()
get_playlist = client.playlistinfo()
get_currentsong = client.currentsong()
state = {}
playlist = []
for song in get_playlist:
2015-10-23 14:34:21 +00:00
playlist.append(song.get('file', ''))
2015-06-14 23:58:20 +00:00
state = dict(
playlist = playlist,
src = host+":"+port,
2015-10-23 14:34:21 +00:00
consume = get_status.get('consume', ''),
current = get_currentsong.get('file', ''),
time = get_status.get('time', '').split(":")[0],
random = get_status.get('random', ''),
repeat = get_status.get('repeat', ''),
single = get_status.get('single', ''),
state = get_status.get('state', ''),
volume = get_status.get('volume', ''),
2015-06-14 23:58:20 +00:00
)
pp = pprint.PrettyPrinter(indent=4)
current_output = pp.pformat(state)
2015-10-23 14:34:21 +00:00
# We don't care if the volume or currently-playing song has changed, only
# the playlist
2015-06-14 23:58:20 +00:00
strip = re.compile(r'\s*?[\'\"](consume|current|random|repeat|single|state|time|volume)[\'\"]:\s*?[\'\"].*?[\'\"],?');
curr = strip.sub('', current_output)
prev = strip.sub('', backup_output)
# Only copy if the current playlist has changed
2015-06-15 06:48:49 +00:00
if curr != prev:
2015-06-14 23:58:20 +00:00
new_backup_file = os.path.join(backup_dir, 'mpd_state' + "-" + now)
# Write backup
new_backup = open(new_backup_file, 'w')
new_backup.write(current_output)
new_backup.close()
client.close()
client.disconnect()
2015-10-23 14:34:21 +00:00
# vim: set expandtab shiftwidth=4 softtabstop=4 textwidth=79: