Viewing file: monitor.py (12.23 KB) -rw-r--r-- Select action/file-type: (+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
# # monitor.py - monitor probing and install data # # Mike Fulbright <msf@redhat.com> # # Copyright 2001-2002 Red Hat, Inc. # # This software may be freely redistributed under the terms of the GNU # library public license. # # You should have received a copy of the GNU Library Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. #
import string import exceptions
from rhpl.log import log from rhpl.executil import execWithCapture from rhpl.translate import _ import rhpl.translate as translate
translate.textdomain('rhpl')
def isValidSyncRange(syncrange):
def isValidPiece(piece): try: tmp = string.split(piece, "-") except: return 0 if len(tmp) > 2: return 0
for i in tmp: try: tmp2 = float(i) except ValueError: return 0
# make sure the values are not crazy if tmp2 < 0.0 or tmp2 > 1000.0: return 0 return 1
try: pieces = string.split(syncrange, ",") except: return 0 for piece in pieces: if not isValidPiece(piece): return 0
return 1
class MonitorInfo:
# # This class represents the monitor on the system. Values from ddcprobing # are provided if available. LCDs are not currently probed. # # Internal members (use methods to access): # # monEisa - probed monitor ID (string) # monName - human readable description (string) # monID - human readable ID (string) # monHoriz - horizontal rating (kHz) # monVert - vertical rating (Hz) # def readMonitorsDB (self, lines = None): if self.monlist: return self.monlist if not lines: db = open ('/usr/share/hwdata/MonitorsDB') lines = db.readlines () db.close ()
for line in lines: line = string.strip (line) if not line: continue if line and line[0] == '#': continue fields = string.split (line, ';') if len(fields) < 5: log("Bad MonitorsDB entry\n: %s", line) continue man = string.strip(fields[0]) model = string.strip(fields[1]) eisa = string.lower(string.strip(fields[2])) horiz = string.strip(fields[3]) vert = string.strip(fields[4]) if self.monlist.has_key(man): self.monlist[man].append((model, eisa, vert, horiz)) else: self.monlist[man] = [(model, eisa, vert, horiz)] self.monids[eisa] = (man, model, eisa, vert, horiz) return self.monlist
def monitorsDB(self): if not self.monlist: self.readMonitorsDB()
return self.monlist
def monitorsEISADB(self): if not self.monlist: self.readMonitorsDB()
return self.monids
def lookupMonitorByID(self, monID): if not self.monlist: self.readMonitorsDB()
for man in self.monlist.keys(): for model in self.monlist[man]: idlower = string.lower(monID) idupper = string.upper(monID) if idlower == model[1] or idupper == model[1]: return model
return 0
def lookupMonitorByName(self, monName): if not self.monlist: self.readMonitorsDB()
for man in self.monlist.keys(): for model in self.monlist[man]: if monName == model[0]: return model
return None
def __str__ (self): return "monName: %s\nmonID: %s\nmonHoriz: %s\nmonVert: %s\nphysicalWidth: %s\nphysicalHeight: %s\n" % ( self.monName, self.monID, self.monHoriz, self.monVert, self.monPhysicalWidth, self.monPhysicalHeight)
def setSpecs(self, horiz, vert, id=None, name = None, physicalWidth=0, physicalHeight=0): self.monPhysicalWidth = physicalWidth self.monPhysicalHeight = physicalHeight self.monHoriz = horiz self.monVert = vert if id: self.monID = id if name: self.monName = name
def getMonitorPhysicalWidth(self, useProbed=0): if useProbed: return self.orig_monPhysicalWidth else: return self.monPhysicalWidth
def getMonitorPhysicalHeight(self, useProbed=0): if useProbed: return self.orig_monPhysicalHeight else: return self.monPhysicalHeight
def getMonitorHorizSync(self, useProbed=0): if useProbed: return self.orig_monHoriz else: return self.monHoriz
def getMonitorVertSync(self, useProbed=0): if useProbed: return self.orig_monVert else: return self.monVert
def getMonitorID(self, useProbed = 0): if not useProbed: return self.monID else: if self.orig_use_probed: return self.probedMonitor[0] else: return self.monID
def getMonitorName(self): return self.monName
def shortDescription(self): if self.monName and self.monName != "" and self.monName != "Unprobed Monitor": return self.monName else: return _("Unable to probe")
def supportsMode(self, modename): return monitor_supports_mode (self.monHoriz, self.monVert, modename)
def runDDCProbeStub(self): monEisa = None monName = None monHoriz = None monVert = None physWidth = None physHeight = None probe = string.split (execWithCapture("/usr/sbin/ddcprobe", ['ddcprobe', '--raw', '--monitor']), '\n') for line in probe: l = string.strip(line) if len(l)<1: continue rc = string.split(l, "=") try: key = rc[0] val = rc[1] if key == "id": monEisa = val elif key == "name": #Remove any potential '"' chars in name. See bug #87588. val = string.replace(val, '"', '') monName = val elif key == "horiz": monHoriz = val elif key == "vert": monVert = val elif key == "width": physWidth = int(val) elif key == "height": physHeight = int(val) else: log("Unknown key/val in monitor::runDDCProbeStuv = %s %s", key, val) except: log("Ignoring bad ddcprobe output line |%s|", line) pass
if monName is None and monEisa is not None: monName = monEisa
return (monEisa, monName, monHoriz, monVert, physWidth, physHeight)
def getDDCProbeResults(self): if self.orig_use_probed: return self.probedMonitor else: return None
def reset(self): self.monName = self.orig_monName self.monID = self.orig_monID self.monHoriz = self.orig_monHoriz self.monVert = self.orig_monVert self.monPhysicalWidth = self.orig_monPhysicalWidth self.monPhysicalHeight = self.orig_monPhysicalHeight
def __init__ (self, skipDDCProbe = 0, fbDevice = None):
self.monName = None self.monID = "Unprobed Monitor"
self.monHoriz = None self.monVert = None
self.monlist = {} self.monids = {}
self.monPhysicalWidth = 0 self.monPhysicalHeight = 0 # store probed values for future reference self.probedMonitor = []
# flag if the original monitor was probed or not self.orig_use_probed = 0 # VESA probe for monitor/videoram, etc. if not skipDDCProbe: try: (monEisa, monName, monHoriz, monVert, physWidth, physHeight) = self.runDDCProbeStub()
ddcsane = 0
# if we can't probe horiz/vert, try to look it up if (monVert, monHoriz) == (None, None) and monEisa is not None: if self.monitorsEISADB().has_key(monEisa.lower()): dbmon = self.monitorsEISADB()[monEisa.lower()] monVert = dbmon[3] monHoriz = dbmon[4] if monName is None: monName = dbmon[1] if monVert != None and monHoriz != None and monName != None: if isValidSyncRange(monVert) and isValidSyncRange(monHoriz): self.probedMonitor = (monEisa, monName, monHoriz, monVert) self.setSpecs(monHoriz, monVert, id="DDCPROBED", name=monName, physicalWidth=physWidth, physicalHeight=physHeight) self.orig_use_probed = 1 ddcsane = 1
except: log("ddcprobe failed") pass
# XXX - default to something sane # really bad because this same code exists in xhwstate # but it another example of different data structures # representing the same entity. # Will have to fix these issues next round. if self.monHoriz == None: self.monHoriz = "31.5-37.9" if self.monVert == None: self.monVert = "50-70" if self.monName == None: self.monName = "Unknown monitor"
# save for reset() method self.orig_monName = self.monName self.orig_monID = self.monID
self.orig_monHoriz = self.monHoriz self.orig_monVert = self.monVert
self.orig_monPhysicalWidth = self.monPhysicalWidth self.orig_monPhysicalHeight = self.monPhysicalHeight
SYNC_TOLERANCE = 0.01 # 1 percent
class ModeLine: def __init__(self, elements): self.clock = string.atof(elements[2]) self.hdisp = string.atof(elements[3]) self.hsyncstart = string.atof(elements[4]) self.hsyncend = string.atof(elements[5]) self.htotal = string.atof(elements[6]) self.vdisp = string.atof(elements[7]) self.vsyncstart = string.atof(elements[8]) self.vsyncend = string.atof(elements[9]) self.vtotal = string.atof(elements[10])
self.flags = [] for i in range(11, len(elements)): self.flags.append(string.upper(elements[i]))
# Bascically copied from xf86CheckModeForMonitor def supports(self, monitor_hsync, monitor_vsync): hsync = self.clock * 1000 / self.htotal hsync_ok = 0 for i in range(len(monitor_hsync)): if hsync > monitor_hsync[i][0] * (1.0 - SYNC_TOLERANCE) and hsync < monitor_hsync[i][1] * (1.0 + SYNC_TOLERANCE): hsync_ok = 1 break; if not hsync_ok: return 0
vrefresh = self.clock * 1000000.0 / (self.htotal * self.vtotal) if "INTERLACE" in self.flags: vrefresh = vrefresh * 2.0; if "DBLSCAN" in self.flags: vrefresh = vrefresh / 2.0;
vsync_ok = 0 for i in range(len(monitor_vsync)): if vrefresh > monitor_vsync[i][0] * (1.0 - SYNC_TOLERANCE) and vrefresh < monitor_vsync[i][1] * (1.0 + SYNC_TOLERANCE): vsync_ok = 1 break; return vsync_ok
def monitor_supports_mode (monitor_hsync, monitor_vsync, modename): def list_from_string(str): l = [] pieces = string.split(str, ",") for piece in pieces: tmp = string.split(piece, "-") if len(tmp) == 1: l.append( (string.atof(tmp[0]), string.atof(tmp[0])) ) else: l.append( (string.atof(tmp[0]), string.atof(tmp[1])) ) return l
if not modelines.has_key(modename): return -1 hsync_list = list_from_string (monitor_hsync) vsync_list = list_from_string (monitor_vsync)
modes = modelines[modename] for modeline in modes: if modeline.supports(hsync_list, vsync_list): return 1 return 0
modelines = {}
def read_modes(filename): fd = open("/usr/share/rhpl/" + filename, 'r')
lines = fd.readlines() fd.close()
for line in lines: if line[0] != "#" and line[0] != '/': line = string.strip(line) elements = string.split(line)
if line == "": continue if len(elements) < 11 or string.lower(elements[0]) != "modeline": raise exceptions.StandardError("Invalid modeline in file: %s"%(line))
name = elements[1][1:-1] if modelines.has_key(name): modelines[name].append(ModeLine(elements)) else: modelines[name] = [ModeLine(elements)]
read_modes("vesamodes") read_modes("extramodes")
|