Skip to content

Instantly share code, notes, and snippets.

@icgood
Created November 7, 2011 21:52
Show Gist options
  • Save icgood/1346311 to your computer and use it in GitHub Desktop.
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.
#!/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