actual scripts
This commit is contained in:
parent
7c4bc93b3c
commit
5b9d32f886
143
backup_mpd_playlist.py
Executable file
143
backup_mpd_playlist.py
Executable file
@ -0,0 +1,143 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
# Back up the state of MPD (current playlist and so on)
|
||||||
|
|
||||||
|
import ast
|
||||||
|
import datetime
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
import pprint
|
||||||
|
import mpd
|
||||||
|
from optparse import OptionParser
|
||||||
|
|
||||||
|
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'
|
||||||
|
backup_dir = options.dest or '/var/lib/mpd/backups'
|
||||||
|
now = datetime.datetime.now().strftime("%Y%m%d@%H:%M")
|
||||||
|
|
||||||
|
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:
|
||||||
|
playlist.append(song["file"])
|
||||||
|
|
||||||
|
state = dict(
|
||||||
|
playlist = playlist,
|
||||||
|
src = host+":"+port,
|
||||||
|
consume = get_status['consume'],
|
||||||
|
current = get_currentsong['file'] if get_currentsong['file'] else '',
|
||||||
|
time = get_status['time'].split(":")[0] if get_status['time'] else '',
|
||||||
|
random = get_status['random'],
|
||||||
|
repeat = get_status['repeat'],
|
||||||
|
single = get_status['single'],
|
||||||
|
state = get_status['state'],
|
||||||
|
volume = get_status['volume'],
|
||||||
|
)
|
||||||
|
|
||||||
|
pp = pprint.PrettyPrinter(indent=4)
|
||||||
|
current_output = pp.pformat(state)
|
||||||
|
|
||||||
|
# We don't care if the volume or currently-playing song has changed, only
|
||||||
|
# the playlist
|
||||||
|
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
|
||||||
|
if current_output != backup_output:
|
||||||
|
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()
|
||||||
|
|
||||||
|
# vim: set expandtab shiftwidth=4 softtabstop=4 textwidth=79:
|
20
decode_mime.pl
Executable file
20
decode_mime.pl
Executable file
@ -0,0 +1,20 @@
|
|||||||
|
#!/usr/bin/perl
|
||||||
|
|
||||||
|
use Email::MIME;
|
||||||
|
use warnings;
|
||||||
|
use strict;
|
||||||
|
|
||||||
|
unless ($ARGV[0] and -f $ARGV[0]) {
|
||||||
|
die "pass in the filename of the email as an argument.";
|
||||||
|
}
|
||||||
|
|
||||||
|
open FILE, "<$ARGV[0]";
|
||||||
|
undef $/;
|
||||||
|
my $email = <FILE>;
|
||||||
|
|
||||||
|
my $parsed = Email::MIME->new($email);
|
||||||
|
my @parts = $parsed->parts;
|
||||||
|
foreach my $el (@parts) {
|
||||||
|
print $el->body;
|
||||||
|
last;
|
||||||
|
}
|
81
detect_bluetooth.py
Executable file
81
detect_bluetooth.py
Executable file
@ -0,0 +1,81 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
# Ensure that the default device gets set to bluetooth when a bluetooth
|
||||||
|
# device is plugged in
|
||||||
|
#
|
||||||
|
# This allows the system volume meter to set the volume
|
||||||
|
#
|
||||||
|
# Also make it not full volume too (currently 50%)
|
||||||
|
#
|
||||||
|
# Timothy Allen <tim@treehouse.org.za>
|
||||||
|
|
||||||
|
import dbus
|
||||||
|
import gobject
|
||||||
|
import atexit
|
||||||
|
import re
|
||||||
|
|
||||||
|
from subprocess import Popen, PIPE
|
||||||
|
from dbus.mainloop.glib import DBusGMainLoop
|
||||||
|
|
||||||
|
def get_sinks():
|
||||||
|
sinks = Popen(["pacmd", "list-sinks"], shell=False, stdout=PIPE).communicate()[0]
|
||||||
|
m = re.findall(r"name: <(.*?)>", sinks)
|
||||||
|
return m
|
||||||
|
|
||||||
|
def get_default_sink():
|
||||||
|
sinks = Popen(["pacmd", "info"], shell=False, stdout=PIPE).communicate()[0]
|
||||||
|
m = re.findall(r"Default sink name: (.*?)\s", sinks)
|
||||||
|
return m
|
||||||
|
|
||||||
|
def set_default_sink(sink):
|
||||||
|
print "Setting sink: %s" % sink
|
||||||
|
Popen(["pacmd", "set-default-sink", sink], shell=False, stdout=PIPE).communicate()[0]
|
||||||
|
|
||||||
|
# Volume is a percent
|
||||||
|
def set_volume(sink, volume):
|
||||||
|
print "Setting volume for sink %s to: %d" % (sink, volume)
|
||||||
|
volume = str(int(65536*(float(str(volume).strip("%"))/100)))
|
||||||
|
Popen(["pacmd", "set-sink-volume", sink, volume], shell=False, stdout=PIPE).communicate()[0]
|
||||||
|
|
||||||
|
|
||||||
|
def device_change(name, value, iface=None, path=None):
|
||||||
|
#print "Name: %s \nValue: %s\nInterface: %s \nPath: %s" % (name, value, iface, path)
|
||||||
|
if (value == "connected"):
|
||||||
|
# set path as default pulse device
|
||||||
|
for sink in get_sinks():
|
||||||
|
if re.match("bluez", sink):
|
||||||
|
set_default_sink(sink)
|
||||||
|
# change volume
|
||||||
|
set_volume(sink, volume)
|
||||||
|
# elif (value == "disconnected"):
|
||||||
|
# # change default device is there's one sink left
|
||||||
|
# sinks = get_sinks()
|
||||||
|
# if isinstance(sinks, basestring):
|
||||||
|
# set_default_sink(sink)
|
||||||
|
# else:
|
||||||
|
# set_default_sink(initial_sink)
|
||||||
|
|
||||||
|
# Volume is a value out of 100
|
||||||
|
volume=50
|
||||||
|
|
||||||
|
loop = gobject.MainLoop()
|
||||||
|
dbus_loop = DBusGMainLoop()
|
||||||
|
bus = dbus.SystemBus(mainloop=dbus_loop)
|
||||||
|
|
||||||
|
#bluez = bus.get_object("org.bluez", "/");
|
||||||
|
#manager = dbus.Interface(bluez, "org.bluez.Manager")
|
||||||
|
#adapter = dbus.Interface(manager.DefaultAdapter(), "org.bluez.Adapter")
|
||||||
|
#proxy = bus.get_object("org.bluez", manager.DefaultAdapter())
|
||||||
|
|
||||||
|
bus.add_signal_receiver(device_change,
|
||||||
|
signal_name=None,
|
||||||
|
dbus_interface="org.bluez.Audio",
|
||||||
|
interface_keyword="iface",
|
||||||
|
path_keyword="path")
|
||||||
|
|
||||||
|
initial_sink = get_default_sink();
|
||||||
|
atexit.register(loop.quit)
|
||||||
|
|
||||||
|
loop.run()
|
||||||
|
|
||||||
|
# vi: filetype=python:expandtab:shiftwidth=4:softtabstop=4:tw=0
|
71
get_firefox_tabs.py
Executable file
71
get_firefox_tabs.py
Executable file
@ -0,0 +1,71 @@
|
|||||||
|
#!/usr/bin/python
|
||||||
|
#
|
||||||
|
# Taken in part from https://gist.github.com/ssokolow/35097553e5173935e597
|
||||||
|
|
||||||
|
import glob, json, os, re
|
||||||
|
|
||||||
|
def get_tab_metadata(tab):
|
||||||
|
grp_id = None
|
||||||
|
grp_data = tab.get('extData', {}).get('tabview-tab', {})
|
||||||
|
if grp_data:
|
||||||
|
grp_data = json.loads(grp_data)
|
||||||
|
if grp_data:
|
||||||
|
grp_id = grp_data.get('groupID', None)
|
||||||
|
del grp_data
|
||||||
|
|
||||||
|
content = tab['entries'][-1] # -1 is most recent
|
||||||
|
return {
|
||||||
|
'index' : tab.get('index'),
|
||||||
|
'group' : grp_id,
|
||||||
|
'title' : content.get('title', content.get('url')),
|
||||||
|
'url' : content.get('url'),
|
||||||
|
'pinned': tab.get('pinned', False)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def get_tabgroups(data):
|
||||||
|
windows = []
|
||||||
|
for window in data['windows']:
|
||||||
|
grp_names = json.loads(window.get('extData', {}).get(
|
||||||
|
'tabview-group', '{}'))
|
||||||
|
grp_names = {int(x): grp_names[x]['title'] for x in grp_names.keys()}
|
||||||
|
|
||||||
|
tabs = []
|
||||||
|
for tab in window['tabs']:
|
||||||
|
tabs.append(get_tab_metadata(tab))
|
||||||
|
|
||||||
|
# Group the tabs by group ID and then replace the IDs with the
|
||||||
|
# group names without risking naming collisions
|
||||||
|
groups = {}
|
||||||
|
for tab in tabs:
|
||||||
|
groups.setdefault(tab['group'], []).append(tab)
|
||||||
|
groups = [(grp_names.get(k, None), v) for k, v in groups.items()]
|
||||||
|
groups.sort() # TODO: Sort case-insensitively
|
||||||
|
|
||||||
|
windows.append(groups)
|
||||||
|
return windows
|
||||||
|
|
||||||
|
|
||||||
|
def print_tabs(groups):
|
||||||
|
for pos, window in enumerate(groups):
|
||||||
|
#print 'Window ' + str(pos+1)
|
||||||
|
for group, tabs in window:
|
||||||
|
if not group and all(x.get('pinned') for x in tabs):
|
||||||
|
grp_name = 'Window ' + str(pos+1) + ' | Pinned Tabs'
|
||||||
|
else:
|
||||||
|
grp_name = group or 'Unnamed'
|
||||||
|
print 'Window ' + str(pos+1) + ' | Group: ' + grp_name
|
||||||
|
for x in tabs:
|
||||||
|
print '\t' + x['title']
|
||||||
|
print '\t' + x['url']
|
||||||
|
print
|
||||||
|
|
||||||
|
|
||||||
|
filenames = glob.glob(os.path.expanduser('~/.mozilla/firefox/*/sessionstore-backups/recovery.js'))
|
||||||
|
for filename in filenames:
|
||||||
|
with open(filename, 'r') as fobj:
|
||||||
|
data = json.load(fobj)
|
||||||
|
groups = get_tabgroups(data)
|
||||||
|
print_tabs(groups)
|
||||||
|
|
||||||
|
# vim: expandtab shiftwidth=4 softtabstop=4 tw=500
|
6
lock_screen
Executable file
6
lock_screen
Executable file
@ -0,0 +1,6 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
source ~/bin/get_dbus_session
|
||||||
|
|
||||||
|
dbus-send --type=method_call --dest=org.gnome.ScreenSaver \
|
||||||
|
/org/gnome/ScreenSaver org.gnome.ScreenSaver.Lock
|
76
netflix-screensaver.py
Executable file
76
netflix-screensaver.py
Executable file
@ -0,0 +1,76 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
# Send a signal to DBus to inhibit the screensaver
|
||||||
|
# if Netflix is running (and playing a movie)
|
||||||
|
#
|
||||||
|
# Timothy Allen <tim@treehouse.org.za>
|
||||||
|
|
||||||
|
import dbus
|
||||||
|
import gobject
|
||||||
|
import atexit
|
||||||
|
|
||||||
|
from re import match, search
|
||||||
|
from time import sleep
|
||||||
|
from subprocess import Popen, PIPE
|
||||||
|
from dbus.mainloop.glib import DBusGMainLoop
|
||||||
|
|
||||||
|
debugging=0
|
||||||
|
|
||||||
|
loop = gobject.MainLoop()
|
||||||
|
dbus_loop = DBusGMainLoop()
|
||||||
|
bus = dbus.SessionBus(mainloop=dbus_loop)
|
||||||
|
screensaver = bus.get_object("org.freedesktop.ScreenSaver", "/org/freedesktop/ScreenSaver");
|
||||||
|
|
||||||
|
def debug(text):
|
||||||
|
if debugging:
|
||||||
|
print text
|
||||||
|
|
||||||
|
# Inhibit
|
||||||
|
def inhibit():
|
||||||
|
debug("Inhibiting...")
|
||||||
|
return screensaver.Inhibit("netflix-desktop", "Playing a movie", dbus_interface="org.freedesktop.ScreenSaver")
|
||||||
|
|
||||||
|
# Uninhibit
|
||||||
|
def uninhibit(cookie):
|
||||||
|
if match("\d{2,}", str(cookie)):
|
||||||
|
debug("Uninhibiting...")
|
||||||
|
# Should return None
|
||||||
|
return screensaver.UnInhibit(cookie, dbus_interface="org.freedesktop.ScreenSaver")
|
||||||
|
else:
|
||||||
|
debug("No cookie, not uninhibiting")
|
||||||
|
return None
|
||||||
|
|
||||||
|
atexit.register(loop.quit)
|
||||||
|
|
||||||
|
if loop.is_running:
|
||||||
|
cookie=None
|
||||||
|
netflix_on=False
|
||||||
|
while True:
|
||||||
|
# Get process list
|
||||||
|
ps = Popen(['ps', 'ax'], shell=False, stdout=PIPE).communicate()[0]
|
||||||
|
|
||||||
|
# Search for the netflix process (and Silverlight to
|
||||||
|
# only inhibit if a movie is playing)
|
||||||
|
#if search("netflix-desktop", ps):
|
||||||
|
if search("netflix-desktop", ps) and search("Silverlight", ps):
|
||||||
|
netflix_on=True
|
||||||
|
else:
|
||||||
|
netflix_on=False
|
||||||
|
|
||||||
|
if netflix_on == True and cookie == None:
|
||||||
|
cookie = inhibit()
|
||||||
|
atexit.register(uninhibit, cookie)
|
||||||
|
debug(cookie)
|
||||||
|
elif netflix_on == False and cookie != None:
|
||||||
|
cookie = uninhibit(cookie)
|
||||||
|
try:
|
||||||
|
atexit.unregister(uninhibit)
|
||||||
|
except (SyntaxError, AttributeError):
|
||||||
|
debug("No unregister for atexit. We must be running on an earlier version of python. No problem.")
|
||||||
|
pass
|
||||||
|
debug(cookie)
|
||||||
|
sleep(30)
|
||||||
|
|
||||||
|
loop.run()
|
||||||
|
|
||||||
|
# vi: filetype=python:expandtab:shiftwidth=4:softtabstop=4:tw=0
|
9
set_volume
Executable file
9
set_volume
Executable file
@ -0,0 +1,9 @@
|
|||||||
|
#!/bin/dash
|
||||||
|
|
||||||
|
if [ -z "$1" ] || [ -n "$(echo $1|sed 's/[0-9]//g')" ]; then
|
||||||
|
echo "Usage: $0 <volume 0-100>"
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
|
||||||
|
pacmd set-sink-volume 0 $(($1 * 65536/100)) >/dev/null
|
||||||
|
exit $?
|
Loading…
Reference in New Issue
Block a user