X-Git-Url: https://git.ralfj.de/lilass.git/blobdiff_plain/9dcdd8e65683504437a6a2f93e20edbdfd50c9c0..HEAD:/screen.py diff --git a/screen.py b/screen.py index 160efec..f0de7e9 100644 --- a/screen.py +++ b/screen.py @@ -32,6 +32,14 @@ def processOutputGen(*args): def processOutputIt(*args): return list(processOutputGen(*args)) # list() iterates over the generator +# for auto-config: common names of internal connectors +def commonInternalConnectorNames(): + commonInternalConnectorPrefixes = ['LVDS', 'eDP'] + commonInternalConnectorSuffices = ['', '0', '1', '-0', '-1'] + for prefix in commonInternalConnectorPrefixes: + for suffix in commonInternalConnectorSuffices: + yield prefix+suffix + ## the classes class RelativeScreenPosition(Enum): @@ -153,7 +161,7 @@ class ScreenSetup: class Connector: def __init__(self, name=None): self.name = name # connector name, e.g. "HDMI1" - self.edid = None # EDID string for the connector, or None if disconnected + self.edid = None # EDID string for the connector, or None if disconnected / unavailable self._resolutions = set() # set of Resolution objects, empty if disconnected self._preferredResolution = None self.previousResolution = None @@ -166,8 +174,8 @@ class Connector: return """""" % (str(self.name), str(self.edid), ", ".join(str(r) for r in self.getResolutionList())) def isConnected(self): - assert (self.edid is None) == (len(self._resolutions)==0), "Resolution-EDID mismatch; #resolutions: {}".format(len(self._resolutions)) - return self.edid is not None + # It is very possible not to have an EDID even for a connected connector + return len(self._resolutions) > 0 def addResolution(self, resolution): assert isinstance(resolution, Resolution) @@ -192,17 +200,18 @@ class Connector: return sorted(self._resolutions, key=lambda r: -r.pixelCount()) class ScreenSituation: - connectors = [] # contains all the Connector objects + connectors = None # contains all the Connector objects internalConnector = None # the internal Connector object (will be an enabled one) externalConnector = None # the used external Connector object (an enabled one), or None previousSetup = None # None or the ScreenSetup used the last time this external screen was connected '''Represents the "screen situation" a machine can be in: Which connectors exist, which resolutions do they have, what are the names for the internal and external screen''' - def __init__(self, internalConnectorNames, externalConnectorNames = None): + def __init__(self, internalConnectorNames, externalConnectorNames = None, xrandrSource = None): '''Both arguments are lists of connector names. The first one which exists and has a screen attached is chosen for that class. can be None to just choose any remaining connector.''' # which connectors are there? - self._getXrandrInformation() + self.connectors = [] + self._getXrandrInformation(xrandrSource) # figure out which is the internal connector self.internalConnector = self._findAvailableConnector(internalConnectorNames) if self.internalConnector is None: @@ -218,10 +227,12 @@ class ScreenSituation: print("Detected external connector:",self.externalConnector) # Run xrandr and fill the dict of connector names mapped to lists of available resolutions. - def _getXrandrInformation(self): + def _getXrandrInformation(self, xrandrSource = None): connector = None # current connector readingEdid = False - for line in processOutputGen("xrandr", "-q", "--verbose"): + if xrandrSource is None: + xrandrSource = processOutputGen("xrandr", "-q", "--verbose") + for line in xrandrSource: if readingEdid: m = re.match(r'^\s*([0-9a-f]+)\s*$', line) if m is not None: @@ -239,7 +250,7 @@ class ScreenSituation: m = re.search(r'^([\w\-]+) (dis)?connected ', line) if m is not None: connector = Connector(m.group(1)) - assert not any(c.name == connector.name for c in self.connectors) + assert not any(c.name == connector.name for c in self.connectors), "Duplicate connector {}".format(connector.name) if not connector.name.startswith("VIRTUAL"): # skip "VIRTUAL" connectors self.connectors.append(connector)