diff --git a/backup_mpd_playlist.py b/backup_mpd_playlist.py
new file mode 100755
index 0000000..444a906
--- /dev/null
+++ b/backup_mpd_playlist.py
@@ -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
", 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 ", 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:
diff --git a/decode_mime.pl b/decode_mime.pl
new file mode 100755
index 0000000..39425cc
--- /dev/null
+++ b/decode_mime.pl
@@ -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 = ;
+
+my $parsed = Email::MIME->new($email);
+my @parts = $parsed->parts;
+foreach my $el (@parts) {
+ print $el->body;
+ last;
+}
diff --git a/detect_bluetooth.py b/detect_bluetooth.py
new file mode 100755
index 0000000..0e08c3d
--- /dev/null
+++ b/detect_bluetooth.py
@@ -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
+
+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
diff --git a/get_firefox_tabs.py b/get_firefox_tabs.py
new file mode 100755
index 0000000..60a37b3
--- /dev/null
+++ b/get_firefox_tabs.py
@@ -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
diff --git a/lock_screen b/lock_screen
new file mode 100755
index 0000000..aa128e3
--- /dev/null
+++ b/lock_screen
@@ -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
diff --git a/netflix-screensaver.py b/netflix-screensaver.py
new file mode 100755
index 0000000..0ab0bcf
--- /dev/null
+++ b/netflix-screensaver.py
@@ -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
+
+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
diff --git a/set_volume b/set_volume
new file mode 100755
index 0000000..bf5a308
--- /dev/null
+++ b/set_volume
@@ -0,0 +1,9 @@
+#!/bin/dash
+
+if [ -z "$1" ] || [ -n "$(echo $1|sed 's/[0-9]//g')" ]; then
+ echo "Usage: $0 "
+ exit
+fi
+
+pacmd set-sink-volume 0 $(($1 * 65536/100)) >/dev/null
+exit $?