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 $?