CoolProgrammer's Linux-Powered Home

userspace.py

#!/usr/bin/python

import pygtk
import gtk
import sys

liststore = gtk.ListStore('gboolean', str)
restore = ''

def init():
        """Initialize CPUFreq, setting it to the userspace governor"""
        restore = get_governor()
        set_governor()

def exiting(button, data):
        """Callback to exit program"""
        set_governor(restore)
        sys.exit()

def set_property(prop, value):
        """Set property prop of cpufreq
        
        Properties can be found in /sys/devices/system/cpu/cpun/cpufreq/*,where
        n is the CPU number (0 for most normal systems, including those with
        hyperthreading since the virtual CPUs must run at the same speed)"""
        f = open('/sys/devices/system/cpu/cpu0/cpufreq/' + prop, 'w')
        f.write(value + "\n")
        f.close

def get_property(prop):
        """Get property prop of cpufreq
        
        Properties can be found in /sys/devices/system/cpu/cpun/cpufreq/*,where
        n is the CPU number (0 for most normal systems, including those with
        hyperthreading since the virtual CPUs must run at the same speed)"""
        f = open('/sys/devices/system/cpu/cpu0/cpufreq/' + prop, 'r')
        text = f.readline()
        text = text[:-1]
        return text

def text_to_speed(x):
        """Convert human-readable text back to integer speed"""
        for i in range(len(x)):
                if x[i] == 'M':
                        speed = int(x[:i])*1000
                        break
                elif x[i] == 'G':
                        speed = int(float(x[:i])*1000000)
                        break
        else:
                print "Aaaah! Bad internal value for speed!"
                sys.exit()
        return speed

def speed_to_text(x):
        """Convert speed to human-readable text"""
        if x < 1000000:
                return str(x/1000) + 'MHz'
        else:
                return str(x/1000000.) + 'GHz'

def get_speeds():
        """Get list of supported CPU speeds"""
        ret = []
        f = open('/sys/devices/system/cpu/cpu0/cpufreq/scaling_available_freque
ncies', 'r')
        text = f.readline()
        f.close
        i, j = 0, 0
        for i in range(len(text)):
                if text[i] == ' ':
                        ret.append(int(text[j:i]))
                        j = i
        return ret

def get_governor():
        """Get current governor"""
        return get_property('scaling_governor')

def set_governor(governor='userspace'):
        """Set governor, defaults to userspace"""
        set_property('scaling_governor', governor)

def set_speed(x):
        """Set CPU speed"""
        set_property('scaling_setspeed', str(x))

def apply(button, treeview):
        """Callback to apply currently selected setting"""
        c, bogus = treeview.get_cursor()
        iter = liststore.get_iter_first()
        while iter:
                liststore.set_value(iter, 0, False)
                iter = liststore.iter_next(iter)
        iter = liststore.get_iter(c)
        liststore.set_value(iter, 0, True)
        speed = text_to_speed(liststore.get_value(iter, 1))
        set_speed(speed)

def get_current_speed():
        """Get the current CPU speed"""
        return int(get_property('scaling_cur_freq'))

def create_main():
        """Creates main window
        
        This is mostly for when this is run as a program, not imported as a
        module."""
        window = gtk.Window(gtk.WINDOW_TOPLEVEL)
        window.set_title(u"Userspace CPUFreq Interface")
        window.set_size_request(260, 240)
        return window

def create_userspace(window):
        """Unwieldly function to create the userspace UI element
        
        The only argument is a window (or other container) into which to insert
        the control."""
        vbox = gtk.VBox(False, 0)
        window.add(vbox)
        scroll = gtk.ScrolledWindow()
        vbox.pack_start(scroll, True, True, 0)
        scroll.set_shadow_type(gtk.SHADOW_IN)
        speed = get_current_speed()
        speeds = get_speeds();
        for i in speeds:
                liststore.append([i == speed, speed_to_text(i)])
        treeview = gtk.TreeView(liststore)
        cellt = gtk.CellRendererText()
        cellt.set_property('mode',gtk.CELL_RENDERER_MODE_INERT)
        cellb = gtk.CellRendererToggle()
        cellb.set_property('mode', gtk.CELL_RENDERER_MODE_INERT)
        cellb.set_property('radio', True)
        oncol = gtk.TreeViewColumn('')
        spcol = gtk.TreeViewColumn('Speeds')
        oncol.pack_start(cellb, True)
        spcol.pack_start(cellt, True)
        oncol.set_attributes(cellb, active=0);
        spcol.set_attributes(cellt, text=1);
        treeview.append_column(oncol)
        treeview.append_column(spcol)
        scroll.add(treeview)
        hbox = gtk.HBox(False, 0)
        vbox.pack_start(hbox, False, False, 0)
        exitbutton = gtk.Button(stock=gtk.STOCK_QUIT)
        exitbutton.connect("clicked", exiting, None)
        hbox.pack_start(exitbutton, True, True, 0)
        applybutton = gtk.Button(stock=gtk.STOCK_APPLY)
        applybutton.connect("clicked", apply, treeview)
        hbox.pack_start(applybutton, True, True, 0)
        window.show_all()

if __name__ == "__main__":
        init()
        create_userspace(create_main())
        gtk.main()
1