Python script for Windows to control ThinkPad features

From ThinkWiki
Revision as of 14:52, 30 November 2008 by Yak (Talk | contribs)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

This is a Python module for Windows that can control the volume, LCD brightness, ThinkLight, magnification (Fn+Space) and ThinkPad Button (AccessIBM button). It is based on the ctypes module (which is included by default with Python 2.5 and later). The ThinkPad Hotkey Features software from IBM/Lenovo must be installed. If the OSD is enabled, it will appear while changing the values using this module.

Since the script uses direct Win32 API calls, it should be pretty straightforward to base a program with similar functionality written in a different language on this script.

Written by Yak. Download the latest versions of the scripts here.

NOTE!
This script no longer works on Windows Vista.

thinkpad.py

 # Author: Arkadiusz Wahlig
 # License: public domain
 
 import sys
 from ctypes import *
 
 class Hotkeys:
     '''Gives control over hotkeys functionalities.'''
 
     def __init__(self):
         path = r'\\.\TPHKDRV'
         if sys.getwindowsversion()[3] != 2:
             # the path is different for Win 95/98/ME
             path += '.VXD'
         self.k32 = windll.kernel32
         self.dev = self.k32.CreateFileA(path, 0xC0000000, 3, 0, 3, 0, 0)
         if self.dev == 0xffffffff:
             raise IOError('Cannot open TPHKDRV.SYS driver!')
 
     def __del__(self):
         self.k32.CloseHandle(self.dev)
 
     def doio(self, ctrl, x):
         b_in = c_ulong(x)
         b_out = c_ulong()
         numbytes = c_ulong()
         if not self.k32.DeviceIoControl(self.dev, ctrl, byref(b_in), 4, byref(b_out), 4, byref(numbytes), 0):
             raise IOError('DeviceIoControl() failed!')
         return b_out.value
 
     def get(self, var):
         return self.doio(0x81008128, var)
 
     def set(self, var, value):
         self.doio(0x8100812c, (var << 24) | value)
 
     def is_thinklight_available(self):
         '''True if ThinkLight is available, False otherwise.'''
         return bool(self.doio(0x81008120, 0) & 0x4000000)
 
     def get_thinklight(self):
         '''True if ThinkLight is currently on, False if off.'''
         return bool(self.get(0x1a) & 0xff)
 
     def set_thinklight(self, on):
         '''If on=True, turns on the ThinkLight, if on=False, turns it off.'''
         self.set(0x1a, int(on))
 
     def get_brightness(self):
         '''Current LCD brightness level (0-7).'''
         return int(self.get(0xc) & 0xff)
 
     def set_brightness(self, brightness):
         '''Sets new LCD brightness level (0-7).'''
         self.set(0xc, brightness & 0xff)
 
     def get_volume(self):
         '''Current volume level (0-14).'''
         return int(self.get(0xe) & 0xff)
 
     def set_volume(self, volume):
         '''Sets new volume level (0-14).'''
         self.set(0xe, volume & 0xff)
 
     def get_mute(self):
         '''True if mute is active, False otherwise.'''
         return bool(self.get(0x10) & 0xff)
 
     def set_mute(self, mute):
         '''If mute=True, activates mute, if mute=False, turns it off.'''
         self.set(0x10, int(mute))
 
     def get_magnify(self):
         '''True if screen magnify is active, False otherwise.'''
         return bool(self.get(0x16) & 0xff)
 
     def set_magnify(self, on):
         '''If on=True, activates the screen magnify, if on=False, turns it off.'''
         self.set(0x16, int(on))
 
     def get_accessibm(self):
         '''The AccessIBM is really a toggle button. Every press toggles its value between 0 and 1.
         This method returns the current value. Can be used to detect single presses by comparing
         with previous value.'''
         return bool(self.get(0x18) & 0xff)

Example: blinking the ThinkLight

This script uses the above module to blink the ThinkLight. The original state of the light is restored afterwards. A number of times the LED should blink can be specified as an argument (defaults to 6).

 import thinkpad
 import time
 import sys

 if __name__ == '__main__':
     try:
         c = int(sys.argv[1])
     except IndexError:
         c = 6
     hk = thinkpad.Hotkeys()
     old = hk.get_thinklight()
     for i in range(c):
         hk.set_thinklight(True)
         time.sleep(0.2)
         hk.set_thinklight(False)
         time.sleep(0.2)
     hk.set_thinklight(old)