{"id":18676050,"url":"https://github.com/nscde/monitor-plug","last_synced_at":"2025-08-30T23:32:09.909Z","repository":{"id":115206321,"uuid":"304107596","full_name":"NsCDE/monitor-plug","owner":"NsCDE","description":"Simple scripted udev driven mechanism for auto configuring monitors with xrandr based on detected connected monitors. Linux only.","archived":false,"fork":false,"pushed_at":"2020-10-14T19:23:36.000Z","size":14,"stargazers_count":5,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2024-11-07T09:37:14.778Z","etag":null,"topics":["automation","linux","monitor","randr","udev-rules","x11"],"latest_commit_sha":null,"homepage":"","language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/NsCDE.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-10-14T18:53:07.000Z","updated_at":"2023-06-23T03:57:50.000Z","dependencies_parsed_at":null,"dependency_job_id":"d4aad850-c272-4362-bc04-0c3091d75c3c","html_url":"https://github.com/NsCDE/monitor-plug","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NsCDE%2Fmonitor-plug","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NsCDE%2Fmonitor-plug/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NsCDE%2Fmonitor-plug/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NsCDE%2Fmonitor-plug/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/NsCDE","download_url":"https://codeload.github.com/NsCDE/monitor-plug/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":231539711,"owners_count":18392333,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["automation","linux","monitor","randr","udev-rules","x11"],"created_at":"2024-11-07T09:27:29.526Z","updated_at":"2024-12-27T20:42:14.452Z","avatar_url":"https://github.com/NsCDE.png","language":"Shell","funding_links":[],"categories":[],"sub_categories":[],"readme":"**Monitor Plug**\n\nThis is Linux only (not portable) udev(7) triggered script for configuring\nmultiple or single monitor setup for X11 based on recognized monitor\nnames, EDID and resolution modes data from /sys/class/drm/cardX entries\non the Linux sysfs filesystem which is mounted on /sys.\n\n\nHow it works\n\nThis script has two modes of operation:\n - collection mode (-s \u003cname\u003e)\n - configuration mode (-c \u003ccard\u003e)\n\nIn the collection mode it will find all connected monitors on the system,\ntake their EDID data SHA-256 hash, or resolution mode hash if EDID\ninformation is empty or otherwise not readable. It will join this binary\ndata, and calculate SHA-256 hash of this concentrated data. Then, it will\ntry to find device names (in C locale order) in the configuration text\ndatabase /etc/opt/monitor-plug/monitordb.txt which itself has this format\n\n- configuration name\n- comma separated list of monitors as seen by the Linux kernel, not xrandr\n- SHA-256 hash\n- flag\n\nFor every monitor combination values above are concentrated in one line,\nseparated by a space. Configuration name is also the name of the script\nwhich runs xrandr and/or whatever is put in it. This script exists as\n/etc/opt/monitor-plug/scripts/\u003cconfiguration-name\u003e.sh. List of monitors\nis a list of all connected monitors on the system which are expected.\nTheir names are similar, but a bit different from the names which\nxrandr(1) presents on the output.\n\nWhen monitor-plug.sh is run by the udev rule (see example udev rule file\n96-monitor-hotplug.rules.example), it will collect data about monitor\nnames hashes of their EDID or resolution modes data, and compare this\nwith configuration lines in the /etc/opt/monitor-plug/monitordb.txt.\nIf there is a match, script named by configuration name will be run\nfrom the scripts/ subdirectory of the /etc/opt/monitor-plug. In this\nscripts, xrandr command line, created manually or with arandr(1) will\nbe run to configure monitors in the way user desires for this setup.\nThis scripts can do any other things, but be careful not to overbloat\nthem with unnecessary or inappropriate actions.\n\nPresently, there are two types of flags: Builtin and External. For\nline with Builting flag, less internal checks and rules will be\napplied. This line should have configuration name \"Default\" usually\nand hash of the single (notebook builtin) monitor. All other monitor\ncombinations (cloned, builtin disconnected, external connected, all\nconnected ...) should have a flag External.\n\n\nWho needs this\n\nPeople who have multiple monitor and projector devices at home, on job,\netc ... and are tired to configure manually or with a place based script\nevery time they connect some DisplayPort, HDMI, VGA, DVI or other cable\nin their laptop.\nIt is probably not needed for static stable configurations where nothing\ngets often reconnected and definitely not for single monitor machines.\n\n\nHow to populate monitordb.txt\n\nConnect all monitors you want and turn on and off to get desirable state.\nRun \"monitor-plug.sh -s \u003cname\u003e\" to generate configuration line which\ncontains C locale ordered and comma separated Linux monitor names and\nEDID or modes hashed data. Put this line into monitordb.txt.\n\nExample:\n\n\\# monitor-plug.sh -s HomeOffice\\\nLOG: local0.info monitor-plug.sh: Monitor /sys/class/drm/card0/card0-HDMI-A-1 is connected, taking it into calculation.\nLOG: local0.info monitor-plug.sh: Monitor /sys/class/drm/card0/card0-eDP-1 is connected, taking it into calculation.\n\nConfiguration line for current layout to be written in /etc/opt/monitor-plug/monitordb.txt:\n\nOffice HDMI-A-1,eDP-1 88bfce976725d8f22d60a460091ef3c022f592cfddcfde5b39fef560df179c3a External\n\n\nHow to install and start\n\n- Put monitor-plug.sh someware in your PATH and make it executable\n- Inspect 96-monitor-hotplug.rules.example and put it in\n  /etc/udev/rules.d omitting \".example\" from the end of file name.\n- Optional: uncomment atd(8) based rule if you are not using systemd(1)\n  and comment out systemd based rule. Make sure you have atd service\n  installed and running\n- Copy monitor-plug.service into /etc/systemd/system and edit to suit\n  if using systemd instead of atd\n- mkdir -p /etc/opt/monitor-plug/scripts\n- Unplug all apart from built in or primary monitor\n- monitor-plug.sh -s Default \u003e /etc/opt/monitor-plug/monitordb.txt\n- Do \"systemctl daemon-reload\" if using systemd instead of atd\n- If you are using atd instead of systemd, make sure atd is enabled\n  and running on your system \n- udevadm trigger\n- Write xrandr(1) scripts and put them as executables in directory\n  /etc/opt/monitor-plug/scripts name them Default.sh and whatever\n  other configurations you generated with \"-s \u003cname\u003e\".\n- Play with cables and see if it works\n\n\nMisc facts\n\n- Script monitor-plug.sh logs into local0 syslog facility if it was not\n  run from the terminal. Otherwise, log lines are visible on stderr. In\n  collection mode (which is interactive) it will always log on stderr of\n  the attached tty device.\n\n- This script depends on the Linux sysfs, EDID data of the monitor or\n  resolition modes, combined with device names. If kernel for some\n  reason is not providing either EDID or modes in the\n  /sys/class/drm/cardX/cardX-DEVNAME-X/{edid,modes}, this will not\n  work unfortunately. Luckily, even KVM virtualized displays are\n  providing at least modes information.\n\n- All pain with the systemd(1) or atd(8) is due to the fact that\n  udev(7) will kill all long running programs run with the RUN argument\n  even if backgrounded and disowned - udev will find them and kill\n\n- DISPLAY and XAUTHORITY variables are essential for configuration\n  based scripts to work if they are calling X11 based programs.\n  Program xrandr(1) is one of them. DISPLAY is assumed to be :0,\n  while w(1) is used to inspect who is logged on the DISPLAY :0 and\n  to find it's home directory with getent, and then .Xauthority file.\n  If this fails, X11 based programs will not work if called from\n  configuration based scripts in the /etc/opt/monitor-plug/scripts.\n  Both DISPLAY and XAUTHORITY can be set or overriden in the udev rule\n  file. For example:\n\n  ENV{DISPLAY}=\":0\", ENV{XAUTHORITY}=\"/home/user2/.Xauthority\"\n\n  See udev(7) documentation if you want to customize udev rules example\n  provided with monitor-plug.\n\n  If called from atd or systemd, DISPLAY and XAUTHORITY must be set in\n  the monitor-plug.service unit file, overlayed with \"systemctl edit\",\n  or provided to atd(8) by other means.\n\n- Because kernel can trigger DRM event twice sometimes, or cable can\n  quickly go in and out, script implements internal locking mechanism\n  to avoid running multiple instances in the same time.\n\n- This operates on the system level and is run under the root privileges,\n  so be careful with configuration based scripts.\n\n- What about information about resolution, serial number etc from EDID?\n  Unreliable. As EDID existance itself. Hashing that data is opportunistic\n  way to get some semi-unique identifiers of user setup states and to act\n  upon them.\n\n- Log example while unplugging HDMI cable to the notebook:\n\n`Oct 12 21:12:04 testbox11 monitor-plug.sh[318407]: DISPLAY set to :0, XAUTHORITY set to /home/h3d/.Xauthority`\n\\\n`Oct 12 21:12:04 testbox11 monitor-plug.sh[318408]: Collecting runtime information ...`\n\\\n`Oct 12 21:12:06 testbox11 monitor-plug.sh[318412]: Monitor /sys/class/drm/card0/card0-eDP-1 is connected, taking it into calculation.`\n\\\n`Oct 12 21:12:06 testbox11 monitor-plug.sh[318421]: Executing Default.sh (Configuration: Builtin).`\n\\\n- Log example while plugging HDMI cable to the notebook:\n\n`Oct 12 21:12:16 testbox11 monitor-plug.sh[318440]: DISPLAY set to :0, XAUTHORITY set to /home/h3d/.Xauthority`\n\\\n`Oct 12 21:12:17 testbox11 monitor-plug.sh[318441]: Collecting runtime information ...`\n\\\n`Oct 12 21:12:19 testbox11 monitor-plug.sh[318448]: Monitor /sys/class/drm/card0/card0-HDMI-A-1 is connected, taking it into calculation.`\n\\\n`Oct 12 21:12:19 testbox11 monitor-plug.sh[318452]: Monitor /sys/class/drm/card0/card0-eDP-1 is connected, taking it into calculation.`\n\\\n`Oct 12 21:12:19 testbox11 monitor-plug.sh[318461]: Executing HomeOffice.sh (Configuration: External).`\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnscde%2Fmonitor-plug","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnscde%2Fmonitor-plug","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnscde%2Fmonitor-plug/lists"}