aboutsummaryrefslogtreecommitdiffstats
path: root/xorg-xrandr/setres/get.py
diff options
context:
space:
mode:
Diffstat (limited to 'xorg-xrandr/setres/get.py')
-rw-r--r--xorg-xrandr/setres/get.py248
1 files changed, 248 insertions, 0 deletions
diff --git a/xorg-xrandr/setres/get.py b/xorg-xrandr/setres/get.py
new file mode 100644
index 0000000..47a6428
--- /dev/null
+++ b/xorg-xrandr/setres/get.py
@@ -0,0 +1,248 @@
+class XScreen:
+ def __init__(self, line):
+ self.number = int(line.split(':')[0].split(' ')[1])
+ self.minimum = None
+ self.current = None
+ self.maximum = None
+ self.connectors = []
+ for part in line.split(':')[1][1:].split(', '):
+ words = part.split(' ')
+ if words[0] == 'minimum':
+ self.minimum = (int(words[1]), int(words[3]))
+ elif words[0] == 'current':
+ self.minimum = (int(words[1]), int(words[3]))
+ elif words[0] == 'maximum':
+ self.minimum = (int(words[1]), int(words[3]))
+
+ def __getitem__(self, value):
+ if isinstance(value, str):
+ for connector in self.connectors:
+ if connector.name == value:
+ return connector
+ elif value is True:
+ for connector in self.connectors:
+ if connector.primary:
+ return connector
+ else:
+ return self.connectors[value]
+ return None
+
+
+class XConnector:
+ def __init__(self, line):
+ line = line.split(' ')
+ self.name = line[0]
+ self.connected = line[1] == 'connected'
+ self.primary = False
+ self.size = None
+ self.position = None
+ self.mode = None
+ self.rr = None
+ self.physsize = None
+ self.modes = []
+ self.identifier = None
+ self.timestamp = None
+ self.subpixel = None
+ self.gamma = None
+ self.brightness = None
+ self.clones = None
+ self.crtc = None
+ self.crtcs = None
+ self.transform = None
+ self.filter = None # TODO
+ self.edid = None
+ # TODO BACKLIGHT
+ # TODO Backlight
+ # TODO scaling mode
+ # TODO Broadcast RGB
+ # TODO audio
+
+ if not self.connected:
+ return
+ i = 2
+
+ if i == len(line):
+ return
+ if line[i] == 'primary':
+ self.primary = True
+ i += 1
+
+ if i == len(line):
+ return
+ word = line[i].replace('-', '+-').replace('+--', '+-')
+ if len(word.replace('+', '')) + 2 == len(word) and len(word.replace('x', '')) + 1 == len(word):
+ if word.replace('+', '').replace('x', '').isdigit():
+ i += 1
+ words = word.split('+')
+ self.position = (int(words[1]), int(words[2]))
+ words = words[0].split('x')
+ self.size = (int(words[0]), int(words[1]))
+
+ if i == len(line):
+ return
+ if line[i].startswith('(0x') and line[i].endswith(')'):
+ self.mode = int(line[i][3 : -1], 16)
+ i += 1
+
+ while not line[i].startswith('('):
+ if self.rr is None:
+ self.rr = line[i]
+ else:
+ self.rr += ' ' + line[i]
+ i += 1
+ while not line[i].endswith(')'):
+ i += 1
+ i += 1
+
+ line = [word[:-2] for word in line[i:] if word.endswith('mm')]
+ if len(line) == 2:
+ self.physsize = (int(line[0]), int(line[1]))
+
+ def __getitem__(self, name):
+ for mode in self.modes:
+ if mode.name == name:
+ return mode
+ return None
+
+ def best_rate(self, mode):
+ best = None
+ if isinstance(mode, str):
+ mode = tuple(int(x) for x in mode.split('x'))
+ for m in self.modes:
+ if m.size == mode:
+ cand = m.vclock
+ if cand is None:
+ continue
+ if best is None or float(cand) > float(best):
+ best = cand
+ return best
+
+
+class XMode:
+ def __init__(self, line):
+ line = line.split(' ')
+ [w, h] = line[0].split('x')
+ self.size = (int(w), int(h))
+ self.name = int(line[1][3 : -1], 16)
+ self.tclock = line[2][:-3] # MHz
+ self.hsync = None
+ self.vsync = None
+ self.current = False
+ self.preferred = False
+ for word in line[3]:
+ if word.endswith('HSync'):
+ self.hsync = word[0]
+ elif word.endswith('VSync'):
+ self.vsync = word[0]
+ elif word == '*current':
+ self.current = True
+ elif word == '+preferred':
+ self.preferred = True
+
+ def set_h(self, line):
+ line = line.split(' ')
+ self.width = int(line[2])
+ self.hstart = int(line[4])
+ self.hend = int(line[6])
+ self.htotal = int(line[8])
+ self.hskew = int(line[10])
+ self.hclock = line[12][:-3] # KHz
+
+ def set_v(self, line):
+ line = line.split(' ')
+ self.height = int(line[2])
+ self.vstart = int(line[4])
+ self.vend = int(line[6])
+ self.vtotal = int(line[8])
+ self.vclock = line[10][:-2] # Hz
+
+
+def get_setup():
+ from subprocess import Popen, PIPE
+
+ def is_screen_line(line):
+ if ':' not in line:
+ return False
+ line = line.split(':')[0].split(' ')
+ if len(line) != 2:
+ return False
+ return line[0] == 'Screen' and line[1].isdigit()
+
+ def is_connector_line(line):
+ return ' ' in line and line.split(' ')[1] in ('connected', 'disconnected')
+
+ def is_mode_line(line):
+ words = line.split(' ')
+ if len(words) < 2:
+ return False
+ if len(words[0]) - 1 != len(words[0].replace('x', '')):
+ return False
+ if not words[0].replace('x', '').isdigit():
+ return False
+ if words[0][0] == 'x' or words[0][-1] == 'x':
+ return False
+ if not words[1].startswith('(0x'):
+ return False
+ return words[1].endswith(')')
+
+ screens = []
+ screen = None
+ connector = None
+ mode = None
+ transx = None
+ on_edid = False
+
+ xrandr_output = Popen('env LANG=C xrandr --verbose'.split(' '), stdout = PIPE)
+ xrandr_output = xrandr_output.communicate()[0].decode('utf-8', 'strict').split('\n')
+
+ for line in xrandr_output:
+ if on_edid and line.startswith('\t\t') and ':' not in line:
+ connector.edid += line.replace(' ', '')
+ on_edid = None
+ elif transx is not None:
+ transx.append(line.strip())
+ if len(transx) == 3:
+ connector.transform = tuple(tuple(float(x) for x in r.split(' ')) for r in transx)
+ transx = None
+ elif is_screen_line(line):
+ screen = XScreen(line)
+ screens.append(screen)
+ elif is_connector_line(line):
+ connector = XConnector(line)
+ screen.connectors.append(connector)
+ else:
+ line = line.replace('\t', ' ').strip()
+ while ' ' in line:
+ line = line.replace(' ', ' ')
+ words = line.split(' ')
+ if is_mode_line(line):
+ mode = XMode(line)
+ connector.modes.append(mode)
+ elif line.startswith('h: '):
+ mode.set_h(line)
+ elif line.startswith('v: '):
+ mode.set_v(line)
+ elif line.startswith('Identifier:'):
+ connector.identifier = int(words[1][2:], 16)
+ elif line.startswith('Timestamp:'):
+ connector.timestamp = int(words[1])
+ elif line.startswith('Subpixel:'):
+ connector.subpixel = ' '.join(words[1:])
+ elif line.startswith('Gamma:'):
+ connector.gamma = tuple(float(x) for x in words[1].split(':'))
+ elif line.startswith('Brightness:'):
+ connector.brightness = float(words[1])
+ elif line.startswith('Clones:'):
+ connector.clones = words[1:]
+ elif line.startswith('CRTCs:'):
+ connector.crtc = int(words[1])
+ elif line.startswith('CRTCs:'):
+ connector.crtcs = tuple(int(x) for x in words[1:])
+ elif line.startswith('Transform:'):
+ transx = [' '.join(words[1:])]
+ elif line.startswith('EDID:'):
+ connector.edid = ''.join(words[1:])
+ on_edid = None
+ on_edid = on_edid is None
+
+ return screens