X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=autorandr.py;h=aadb7d4f608e3e179fefe87d7b8f563cc8042d58;hb=e5ae9d8c97fe6251c2b587de0cb4fbd605196075;hp=ee559359100a6a47e4b235725dba0a3e5dda6d15;hpb=586dce7ec54977b8a7cd1c38df7734fbd9a659c9;p=deb_pkgs%2Fautorandr.git diff --git a/autorandr.py b/autorandr.py index ee55935..aadb7d4 100755 --- a/autorandr.py +++ b/autorandr.py @@ -145,12 +145,12 @@ class XrandrOutput(object): @property def option_vector(self): "Return the command line parameters for XRandR for this instance" - return sum([["--%s" % option[0], option[1]] if option[1] else ["--%s" % option[0]] for option in chain((("output", self.output),), self.options_with_defaults.items())], []) + return sum([["--%s" % option[0], option[1]] if option[1] else ["--%s" % option[0]] for option in chain((("output", self.output),), sorted(self.options_with_defaults.items()))], []) @property def option_string(self): "Return the command line parameters in the configuration file format" - return "\n".join([ " ".join(option) if option[1] else option[0] for option in chain((("output", self.output),), self.options.items())]) + return "\n".join([ " ".join(option) if option[1] else option[0] for option in chain((("output", self.output),), sorted(self.options.items()))]) @property def sort_key(self): @@ -328,6 +328,8 @@ def parse_xrandr_output(): # Split at output boundaries and instanciate an XrandrOutput per output split_xrandr_output = re.split("(?m)^([^ ]+ (?:(?:dis)?connected|unknown connection).*)$", xrandr_output) + if len(split_xrandr_output) < 2: + raise RuntimeError("No output boundaries found") outputs = OrderedDict() modes = OrderedDict() for i in range(1, len(split_xrandr_output), 2): @@ -364,24 +366,27 @@ def load_profiles(profile_path): if config[output_name].edid is None: del config[output_name] - profiles[profile] = config + profiles[profile] = { "config": config, "path": os.path.join(profile_path, profile), "config-mtime": os.stat(config_name).st_mtime } return profiles -def find_profile(current_config, profiles): - "Find a profile matching the currently connected outputs" +def find_profiles(current_config, profiles): + "Find profiles matching the currently connected outputs" + detected_profiles = [] for profile_name, profile in profiles.items(): + config = profile["config"] matches = True - for name, output in profile.items(): + for name, output in config.items(): if not output.edid: continue if name not in current_config or not output.edid_equals(current_config[name]): matches = False break - if not matches or any(( name not in profile.keys() for name in current_config.keys() if current_config[name].edid )): + if not matches or any(( name not in config.keys() for name in current_config.keys() if current_config[name].edid )): continue if matches: - return profile_name + detected_profiles.append(profile_name) + return detected_profiles def profile_blocked(profile_path): "Check if a profile is blocked" @@ -412,6 +417,14 @@ def save_configuration(profile_path, configuration): with open(os.path.join(profile_path, "setup"), "w") as setup: output_setup(configuration, setup) +def update_mtime(filename): + "Update a file's mtime" + try: + os.utime(filename, None) + return True + except: + return False + def apply_configuration(configuration, dry_run=False): "Apply a configuration" outputs = sorted(configuration.keys(), key=lambda x: configuration[x].sort_key) @@ -523,6 +536,8 @@ def main(argv): profile_path = os.path.join(os.environ.get("XDG_CONFIG_HOME", os.path.expanduser("~/.config")), "autorandr") if os.path.isdir(profile_path): profiles.update(load_profiles(profile_path)) + # Sort by descending mtime + profiles = OrderedDict(sorted(profiles.items(), key=lambda x: -x[1]["config-mtime"])) except Exception as e: print("Failed to load profiles:\n%s" % str(e), file=sys.stderr) sys.exit(1) @@ -558,7 +573,7 @@ def main(argv): if "-h" in options or "--help" in options: exit_help() - detected_profile = find_profile(config, profiles) + detected_profiles = find_profiles(config, profiles) load_profile = False if "-l" in options: @@ -570,10 +585,10 @@ def main(argv): if profile_blocked(os.path.join(profile_path, profile_name)): print("%s (blocked)" % profile_name, file=sys.stderr) continue - if detected_profile == profile_name: + if profile_name in detected_profiles: print("%s (detected)" % profile_name, file=sys.stderr) - if "-c" in options or "--change" in options: - load_profile = detected_profile + if ("-c" in options or "--change" in options) and not load_profile: + load_profile = profile_name else: print(profile_name, file=sys.stderr) @@ -584,25 +599,30 @@ def main(argv): if load_profile: if load_profile in ( x[0] for x in virtual_profiles ): - profile = generate_virtual_profile(config, modes, load_profile) + load_config = generate_virtual_profile(config, modes, load_profile) + scripts_path = os.path.join(profile_path, load_profile) else: try: profile = profiles[load_profile] + load_config = profile["config"] + scripts_path = profile["path"] except KeyError: print("Failed to load profile '%s':\nProfile not found" % load_profile, file=sys.stderr) sys.exit(1) - add_unused_outputs(config, profile) - if profile == dict(config) and not "-f" in options and not "--force" in options: + if load_profile in detected_profiles and detected_profiles[0] != load_profile: + update_mtime(os.path.join(scripts_path, "config")) + add_unused_outputs(config, load_config) + if load_config == dict(config) and not "-f" in options and not "--force" in options: print("Config already loaded", file=sys.stderr) sys.exit(0) try: if "--dry-run" in options: - apply_configuration(profile, True) + apply_configuration(load_config, True) else: - exec_scripts(os.path.join(profile_path, load_profile), "preswitch") - apply_configuration(profile, False) - exec_scripts(os.path.join(profile_path, load_profile), "postswitch") + exec_scripts(scripts_path, "preswitch") + apply_configuration(load_config, False) + exec_scripts(scripts_path, "postswitch") except Exception as e: print("Failed to apply profile '%s':\n%s" % (load_profile, str(e)), file=sys.stderr) sys.exit(1)