Created
November 7, 2011 21:52
-
-
Save icgood/1346311 to your computer and use it in GitHub Desktop.
Sets and clears away status in pidgin/purple when xscreensaver locks and unlocks the screen.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python2 | |
# Author: Ian Good <[email protected]> | |
# Inspired by http://costela.net/projects/awayonlock/ | |
# Use at your own risk! | |
import os | |
import sys | |
import signal | |
import hashlib | |
import subprocess | |
import fcntl | |
import time | |
import dbus, gobject | |
# {{{ class AwayOnLock | |
class AwayOnLock(object): | |
# {{{ __init__() | |
def __init__(self): | |
self.prev = None | |
# }}} | |
# {{{ _start_xscreensaver_watch() | |
def _start_xscreensaver_watch(self): | |
return subprocess.Popen(['xscreensaver-command', '-watch'], | |
stdin=subprocess.PIPE, | |
stdout=subprocess.PIPE) | |
# }}} | |
# {{{ _get_purple() | |
def _get_purple(self): | |
try: | |
bus = dbus.SessionBus() | |
dbus_obj = bus.get_object("im.pidgin.purple.PurpleService", "/im/pidgin/purple/PurpleObject") | |
purple = dbus.Interface(dbus_obj, "im.pidgin.purple.PurpleInterface") | |
return purple | |
except dbus.exceptions.DBusException: | |
return None | |
# }}} | |
# {{{ _set_status | |
def _set_status(self, screensaver_active): | |
purple = self._get_purple() | |
if not purple: | |
return | |
away = purple.PurpleSavedstatusGetIdleaway() | |
current = purple.PurpleSavedstatusGetCurrent() | |
if screensaver_active: | |
self.prev = current | |
purple.PurpleSavedstatusActivate(away) | |
elif self.prev: | |
purple.PurpleSavedstatusActivate(self.prev) | |
self.prev = None | |
# }}} | |
# {{{ _handle_watch_lines() | |
def _handle_watch_lines(self, watch): | |
while True: | |
line = watch.stdout.readline() | |
if not line: | |
raise OSError | |
if line.startswith("UNBLANK"): | |
time.sleep(1) | |
self._set_status(False) | |
elif line.startswith("LOCK"): | |
self._set_status(True) | |
# }}} | |
# {{{ loop() | |
def loop(self): | |
while True: | |
watch = self._start_xscreensaver_watch() | |
try: | |
self._handle_watch_lines(watch) | |
except (KeyboardInterrupt, SystemExit): | |
watch.terminate() | |
break | |
except OSError: | |
pass | |
watch.terminate() | |
# }}} | |
# }}} | |
# {{{ _daemonize() | |
# Daemonize the current process. | |
def _daemonize(): | |
# Fork once. | |
try: | |
pid = os.fork() | |
if pid > 0: | |
os._exit(0) | |
except OSError: | |
return | |
# Set some options to detach from the terminal. | |
os.chdir('/') | |
os.setsid() | |
os.umask(0) | |
# Fork again. | |
try: | |
pid = os.fork() | |
if pid > 0: | |
os._exit(0) | |
except OSError: | |
return | |
# Find the OS /dev/null equivalent. | |
nullfile = getattr(os, 'devnull', '/dev/null') | |
# Redirect all standard I/O to /dev/null. | |
sys.stdout.flush() | |
sys.stderr.flush() | |
si = file(nullfile, 'r') | |
so = file(nullfile, 'a+') | |
se = file(nullfile, 'a+', 0) | |
os.dup2(si.fileno(), sys.stdin.fileno()) | |
os.dup2(so.fileno(), sys.stdout.fileno()) | |
os.dup2(se.fileno(), sys.stderr.fileno()) | |
# }}} | |
# {{{ _exclusive_lock() | |
def _exclusive_lock(): | |
f = open('/tmp/away-on-lock.lock', 'w') | |
fcntl.lockf(f, fcntl.LOCK_EX | fcntl.LOCK_NB) | |
return f | |
# }}} | |
if __name__ == '__main__': | |
_daemonize() | |
lock = _exclusive_lock() | |
def handle_sigterm(signum, frame): | |
sys.exit(0) | |
signal.signal(signal.SIGTERM, handle_sigterm) | |
aonl = AwayOnLock() | |
aonl.loop() | |
# vim:et:fdm=marker:sts=4:sw=4:ts=4 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment