phillipberndt / autorandr

Auto-detect the connected display hardware and load the appropriate X11 setup using xrandr
2.51k stars 123 forks source link

Feature request: Wildcards for output names? #140

Open eater opened 5 years ago

eater commented 5 years ago

I have a pair of external monitors that I use with my laptop via a dock. Whenever I connect the laptop to the dock, the monitors get assigned different output names: DP1-1 and DP1-2, DP1-1 and DP2-1, DP-1-1 and DP-2-2, etc. Sometimes I connect one of them without the dock, and I get DP1-1 and HDMI1-1. And the internal laptop display is sometimes eDP1 and sometimes eDP-1.

I always want the configuration to be the same when I have these monitors connected. Is it possible for autorandr to recognize the monitors by their EDIDs rather than by these changing names?

phillipberndt commented 5 years ago

There's a feature for wildcarding EDID's per output, but the inverse doesn't exist yet.

The simplest way to add this, I guess, would be to extend XrandrOutput.from_config_file to support finding the output name using an EDID. This might work:

diff --git a/autorandr.py b/autorandr.py
index c108c26..dc59765 100755
--- a/autorandr.py
+++ b/autorandr.py
@@ -381,6 +381,12 @@ class XrandrOutput(object):

         edid = None

+        if options["output"].startswith("x-autorandr-edid:"):
+            # Determine output name from edid
+            inverse_edid_map = dict(((v, k) for k, v in edid_map.items()))
+            find_edid = options["output"][len("x-autorandr-edid:"):]
+            options["output"] = inverse_edid_map.get(find_edid, options["output"])
+
         if options["output"] in edid_map:
             edid = edid_map[options["output"]]
         else:
@@ -514,7 +520,8 @@ def load_profiles(profile_path):
         buffer = []
         for line in chain(open(config_name).readlines(), ["output"]):
             if line[:6] == "output" and buffer:
-                config[buffer[0].strip().split()[-1]] = XrandrOutput.from_config_file(edids, "".join(buffer))
+                output = XrandrOutput.from_config_file(edids, "".join(buffer))
+                config[output.output] = output
                 buffer = [line]
             else:
                 buffer.append(line)

Idea would be to edit your config and setup files and replace DP1-1 with x-autorandr-edid:YOUR_EDID_HERE in both files. This code should dynamically, upon loading, replace that string with the output that currently has a monitor with this EDID attached.

Let me know if this works and if you have an idea for making this more convenient to use.

eater commented 5 years ago

Thanks. I patched autorandr.py and created the config and setup files, but when I try to change to the new profile, I get

"Failed to apply profile 'test' (line 718): 'x-autorandr-edid:00ffffffffffff0006af3d3100000000001a0104a51f1178028d15a156529d280a505400000001010101010101010101010101010101143780b87038244010103e0035ae100000180000000f0000000000000000000000000020000000fe0041554f0a202020202020202020000000fe004231343048414e30332e31200a003b' This appears to be a bug.

phillipberndt commented 5 years ago

Try adding

print(find_edid)
print(options["output"])
print(inverse_edid_map)

below the first chunk of changes and paste the output, please.

eater commented 5 years ago

I now don't have a multimonitor setup so I haven't been able to test this.