From 65e2ac1e5f2c5d714a5080120decab18e4452b1a Mon Sep 17 00:00:00 2001 From: Alexander Grothe Date: Mon, 4 Feb 2019 17:57:34 +0100 Subject: [PATCH] Disable screen blanking by default via xorg configuration snippet Further changes: - add ppa:yavdr/experimental-kodi for KODI 18 - add set-kodi-display script to allow switching DISPLAY in dual screen configuration (inkompatible with KODI 17) --- Manual.org | 122 +++++++++++++++++- group_vars/all | 2 +- roles/kodi/tasks/configure-kodi.yml | 7 +- roles/kodi/templates/kodi.service.j2 | 2 +- roles/kodi/templates/set-kodi-display.j2 | 96 ++++++++++++++ roles/samba-config/templates/smb.conf.j2 | 3 +- roles/yavdr-xorg/tasks/detect-xorg.yml | 5 + .../templates/10-serverflags.conf.j2 | 8 ++ 8 files changed, 238 insertions(+), 7 deletions(-) create mode 100644 roles/kodi/templates/set-kodi-display.j2 create mode 100644 roles/yavdr-xorg/templates/10-serverflags.conf.j2 diff --git a/Manual.org b/Manual.org index 941f7c1..1527d2b 100644 --- a/Manual.org +++ b/Manual.org @@ -343,8 +343,8 @@ ppa_owner: 'ppa:yavdr' repositories: - '{{ ppa_owner }}/{{branch}}-main' - '{{ ppa_owner }}/{{branch}}-vdr' + - '{{ ppa_owner }}/{{branch}}-kodi' #- '{{ ppa_owner }}/{{branch}}-yavdr' - #- '{{ ppa_owner }}/{{branch}}-kodi' #+END_SRC ** VDR user, directories, special configuration and plugins :PROPERTIES: @@ -1829,7 +1829,7 @@ ctl.!default { :PROPERTIES: :ID: 3f614f9c-c24b-4450-82ff-5c3fe103e695 :END: -The X-Server is started by using the two systemd units ~xlogin@.service~ and ~x@.service~ provided by the package *xlogin*. The former is enabled (and started) for the vdr user - which results (using the default settings for the user *vdr* with the uid *666*) in the activation of ~xlogin@vdr.service~ when reaching the graphical.target. To simplify starting and stopping the X-server and the desktop session a ~yavdr-xorg.service~ is provided by the package ~yavdr-xorg~, which depends on the two units mentioned before. +The X-Server is started by using the two systemd units ~xlogin@.service~ and ~x@.service~ provided by the package *xlogin*. The former is enabled (and started) for the vdr user - which results (using the default settings for the user *vdr* with the uid *666*) in the activation of ~xlogin@vdr.service~ when reaching the graphical.target. To simplify starting and stopping the X-server and the desktop session a ~yavdr-xorg.service~ is provided by the package ~yavdr-xorg~, which depends on the two units mentioned before. ~x@vt7.service~ is started automatically as a dependency of ~xlogin@vdr.service~ and starts the X-server. ~xlogin@vdr.service~ also starts a systemd user session using ~user@666.service~. In order to use the keyboard layout configured during installation for the X-Server the script ~write-x11-keyboard-config~ reads the keyboard configuration from ~/etc/default/keyboard~ when starting ~x@.service~ and writes the file ~/etc/X11/xorg.conf.d/00-keyboard.conf~ (because systemd for Ubuntu (and Debian) has been patched not to create ~/etc/X11/xorg.conf.d/00-keyboard.conf~ according to the ~localectl~ settings). @@ -2578,6 +2578,10 @@ preferred_refreshrates: when: - intel_detected +- name: server flags config snippet to disable screen blanking + template: + src: templates/10-serverflags.conf.j2 + dest: /etc/X11/xorg.conf.d/10-serverflags.conf #+END_SRC **** intel.yml :PROPERTIES: @@ -3071,6 +3075,17 @@ Section "Screen" EndSection {% endif %} #+END_SRC +***** snippet to disable screen blanking +#+BEGIN_SRC conf :tangle roles/yavdr-xorg/templates/10-serverflags.conf.j2 +{{ ansible_managed | comment }} +Section "ServerFlags" + Option "NoPM" "true" + Option "blank time" "0" + Option "standby time" "0" + Option "suspend time" "0" + Option "off time" "0" +EndSection +#+END_SRC **** vdr :PROPERTIES: :ID: 748ef799-1673-4028-b52e-234328dc793b @@ -5325,7 +5340,8 @@ end # This option controls how unsuccessful authentication attempts are mapped # to anonymous connections - map to guest = bad user + map to guest = bad password + guest account = nobody {% if samba.windows_compatible %} # disable unix extensions and enable following symlinks @@ -6010,6 +6026,106 @@ install serial_ir setserial /dev/{{serial_ir_device}} uart none; /sbin/modprobe :END: This systemd unit for the user session starts (and stops) kodi. #+INCLUDE: "roles/kodi/templates/kodi.service.j2" src conf +**** set-kodi-diplay +This is a version-dependent script to force KODI to use the display set by the environment variable ~DISPLAY~. The following Version is intended for KODI 18. +#+BEGIN_SRC jinja2 :tangle roles/kodi/templates/set-kodi-display.j2 :padline no +#!/usr/bin/env python3 +""" +{{ ansible_managed }} + +This Script changes the monitor in KODI's guisettings.xml to the wanted output +according to the DISPLAY environment variable. It works with KODI 18 (not KODI 17!). +""" + +import os +import sys +import subprocess +import xml.etree.ElementTree as ET + + +GUISETTINGS = '/var/lib/vdr/.kodi/userdata/guisettings.xml' +CACHE_DIR = '/var/lib/vdr/.kodi/.display_cache' +VIDEOSCREEN_TEMPLATE = """ + {} +""" + + +def get_output_names(): + """ + get display name from xrandr output for given DISPLAY environment variable + """ + xrandr_output = [ + l for l in subprocess.check_output( + ["xrandr"], + env={"DISPLAY": os.environ["DISPLAY"]} + ).decode("utf-8").splitlines() + ] + return [l.split()[0] for l in xrandr_output if " connected " in l] + + +def parse_template(template_path, template, output=""): + """read videoscreen settings from backup or create a stub file""" + try: + xml_tree = ET.parse(template_path) + except FileNotFoundError: + print("{} not found, creating stub file".format(template_path)) + xml_template = ET.fromstring(template.format(output)) + xml_tree = ET.ElementTree(xml_template) + finally: + xml_tree.write(template_path) + return xml_tree + + +def backup_videoscreen(): + """parse guisettings.xml for display name an backup videoscreen data""" + tree = parse_template(GUISETTINGS, VIDEOSCREEN_TEMPLATE, "Default") + root = tree.getroot() + videoscreen = root.find("./setting[@id='videoscreen.monitor']") + output = videoscreen.text + xml_path = os.path.join(CACHE_DIR, '{}-videodevice.xml'.format(output)) + base_tree = ET.fromstring('') + xml_tree = ET.ElementTree(base_tree) + backup_root = xml_tree.getroot() + backup_root.insert(0, videoscreen) + xml_tree.write(xml_path) + print("written backup for {} to {}".format(output, xml_path)) + + +def change_videoscreen(output, new_videoscreen): + """change videoscreen node to content of backup file""" + tree = parse_template(GUISETTINGS, VIDEOSCREEN_TEMPLATE, output) + root = tree.getroot() + + videoscreen = root.find('./setting[@id="videoscreen.monitor"]') + if videoscreen is not None: + videoscreen.text = new_videoscreen.text + else: + videoscreen = root.find("./settings") + root.insert(0, new_videoscreen) + tree.write(GUISETTINGS) + return tree + +if __name__ == '__main__': + output = get_output_names()[0] + if not output: + sys.exit("Error: no screen name found") + try: + os.makedirs(CACHE_DIR, exist_ok=True) + except PermissionError: + sys.exit("Error: insufficient permissions to create cachedir {}".format( + CACHE_DIR)) + try: + backup_videoscreen() + except FileNotFoundError: + print("{} does not exist".format(GUISETTINGS)) + except Exception as e: + print("Could not backup videoscreen.monitor:", str(e)) + xml_path = os.path.join(CACHE_DIR, '{}-videodevice.xml'.format(output)) + videodir_xml = parse_template(xml_path, VIDEOSCREEN_TEMPLATE, output) + videodir_root = videodir_xml.getroot() + new_videoscreen = videodir_root.find("./setting[@id='videoscreen.monitor']") + guisettings_xml = change_videoscreen(output, new_videoscreen) +#+END_SRC *** files :PROPERTIES: :ID: 58c5c693-bd24-420a-bfed-79771e8e0d47 diff --git a/group_vars/all b/group_vars/all index a7f48b3..11645e2 100644 --- a/group_vars/all +++ b/group_vars/all @@ -7,8 +7,8 @@ ppa_owner: 'ppa:yavdr' repositories: - '{{ ppa_owner }}/{{branch}}-main' - '{{ ppa_owner }}/{{branch}}-vdr' + - '{{ ppa_owner }}/{{branch}}-kodi' #- '{{ ppa_owner }}/{{branch}}-yavdr' - #- '{{ ppa_owner }}/{{branch}}-kodi' # properties of the user vdr and vdr-related options # NOTE: user name, uid and confdir must match the values set by the vdr package vdr: diff --git a/roles/kodi/tasks/configure-kodi.yml b/roles/kodi/tasks/configure-kodi.yml index e6d09d3..4f1a37c 100644 --- a/roles/kodi/tasks/configure-kodi.yml +++ b/roles/kodi/tasks/configure-kodi.yml @@ -35,4 +35,9 @@ group: '{{ vdr.group }}' mode: "0664" force: no -# TODO: Add configuration files + +- name: expand template for set-kodi-display + template: + src: 'templates/set-kodi-display.j2' + dest: '/usr/bin/set-kodi-display' + mode: "0755" diff --git a/roles/kodi/templates/kodi.service.j2 b/roles/kodi/templates/kodi.service.j2 index d200cf0..f3d0851 100644 --- a/roles/kodi/templates/kodi.service.j2 +++ b/roles/kodi/templates/kodi.service.j2 @@ -9,4 +9,4 @@ ExecStart=/usr/bin/kodi -l /run/lirc/lircd ExecStop=/bin/bash -c "/usr/bin/kodi-send --action=QUIT; while ps -p $MAINPID -o comm=; do sleep .25; done" TimeoutStopSec=10 SuccessExitStatus=0 127 SIGKILL -Restart=on-failure +Restart=on-failure \ No newline at end of file diff --git a/roles/kodi/templates/set-kodi-display.j2 b/roles/kodi/templates/set-kodi-display.j2 new file mode 100644 index 0000000..dc8fbec --- /dev/null +++ b/roles/kodi/templates/set-kodi-display.j2 @@ -0,0 +1,96 @@ +#!/usr/bin/env python3 +""" +{{ ansible_managed }} + +This Script changes the monitor in KODI's guisettings.xml to the wanted output +according to the DISPLAY environment variable. It works with KODI 18 (not KODI 17!). +""" + +import os +import sys +import subprocess +import xml.etree.ElementTree as ET + + +GUISETTINGS = '/var/lib/vdr/.kodi/userdata/guisettings.xml' +CACHE_DIR = '/var/lib/vdr/.kodi/.display_cache' +VIDEOSCREEN_TEMPLATE = """ + {} +""" + + +def get_output_names(): + """ + get display name from xrandr output for given DISPLAY environment variable + """ + xrandr_output = [ + l for l in subprocess.check_output( + ["xrandr"], + env={"DISPLAY": os.environ["DISPLAY"]} + ).decode("utf-8").splitlines() + ] + return [l.split()[0] for l in xrandr_output if " connected " in l] + + +def parse_template(template_path, template, output=""): + """read videoscreen settings from backup or create a stub file""" + try: + xml_tree = ET.parse(template_path) + except FileNotFoundError: + print("{} not found, creating stub file".format(template_path)) + xml_template = ET.fromstring(template.format(output)) + xml_tree = ET.ElementTree(xml_template) + finally: + xml_tree.write(template_path) + return xml_tree + + +def backup_videoscreen(): + """parse guisettings.xml for display name an backup videoscreen data""" + tree = parse_template(GUISETTINGS, VIDEOSCREEN_TEMPLATE, "Default") + root = tree.getroot() + videoscreen = root.find("./setting[@id='videoscreen.monitor']") + output = videoscreen.text + xml_path = os.path.join(CACHE_DIR, '{}-videodevice.xml'.format(output)) + base_tree = ET.fromstring('') + xml_tree = ET.ElementTree(base_tree) + backup_root = xml_tree.getroot() + backup_root.insert(0, videoscreen) + xml_tree.write(xml_path) + print("written backup for {} to {}".format(output, xml_path)) + + +def change_videoscreen(output, new_videoscreen): + """change videoscreen node to content of backup file""" + tree = parse_template(GUISETTINGS, VIDEOSCREEN_TEMPLATE, output) + root = tree.getroot() + + videoscreen = root.find('./setting[@id="videoscreen.monitor"]') + if videoscreen is not None: + videoscreen.text = new_videoscreen.text + else: + videoscreen = root.find("./settings") + root.insert(0, new_videoscreen) + tree.write(GUISETTINGS) + return tree + +if __name__ == '__main__': + output = get_output_names()[0] + if not output: + sys.exit("Error: no screen name found") + try: + os.makedirs(CACHE_DIR, exist_ok=True) + except PermissionError: + sys.exit("Error: insufficient permissions to create cachedir {}".format( + CACHE_DIR)) + try: + backup_videoscreen() + except FileNotFoundError: + print("{} does not exist".format(GUISETTINGS)) + except Exception as e: + print("Could not backup videoscreen.monitor:", str(e)) + xml_path = os.path.join(CACHE_DIR, '{}-videodevice.xml'.format(output)) + videodir_xml = parse_template(xml_path, VIDEOSCREEN_TEMPLATE, output) + videodir_root = videodir_xml.getroot() + new_videoscreen = videodir_root.find("./setting[@id='videoscreen.monitor']") + guisettings_xml = change_videoscreen(output, new_videoscreen) diff --git a/roles/samba-config/templates/smb.conf.j2 b/roles/samba-config/templates/smb.conf.j2 index e744160..63dab45 100644 --- a/roles/samba-config/templates/smb.conf.j2 +++ b/roles/samba-config/templates/smb.conf.j2 @@ -69,7 +69,8 @@ # This option controls how unsuccessful authentication attempts are mapped # to anonymous connections - map to guest = bad user + map to guest = bad password + guest account = nobody {% if samba.windows_compatible %} # disable unix extensions and enable following symlinks diff --git a/roles/yavdr-xorg/tasks/detect-xorg.yml b/roles/yavdr-xorg/tasks/detect-xorg.yml index 68fe2be..f5c6e79 100644 --- a/roles/yavdr-xorg/tasks/detect-xorg.yml +++ b/roles/yavdr-xorg/tasks/detect-xorg.yml @@ -174,3 +174,8 @@ dest: /etc/X11/xorg.conf.d/20-intel.conf when: - intel_detected + +- name: server flags config snippet to disable screen blanking + template: + src: templates/10-serverflags.conf.j2 + dest: /etc/X11/xorg.conf.d/10-serverflags.conf diff --git a/roles/yavdr-xorg/templates/10-serverflags.conf.j2 b/roles/yavdr-xorg/templates/10-serverflags.conf.j2 new file mode 100644 index 0000000..8d802e2 --- /dev/null +++ b/roles/yavdr-xorg/templates/10-serverflags.conf.j2 @@ -0,0 +1,8 @@ +{{ ansible_managed | comment }} +Section "ServerFlags" + Option "NoPM" "true" + Option "blank time" "0" + Option "standby time" "0" + Option "suspend time" "0" + Option "off time" "0" +EndSection