Ansible Playbooks for yaVDR 0.7
Inhaltsverzeichnis
- 1. User Stories
- 2. Notes
- 3. Introduction
- 4. Installing and configuring yaVDR with Ansible
- 5. Playbooks
- 6. Hosts
- 7. Group Variables
- 8. Roles
- 8.1. install-dependencies
- 8.2. nvidia-381 drivers
- 8.3. yavdr-common
- 8.4. vdr
- 8.5. STARTED yavdr-network
- 8.6. nfs-server
- 8.7. TODO yavdr-remote
- 8.8. pulseaudio
- 8.9. yavdr-xorg
- 8.10. samba-install
- 8.11. samba-config
- 8.12. STARTED autoinstall-drivers
- 8.13. autoinstall-ubuntu-drivers
- 8.14. autoinstall-satip
- 8.15. autoinstall-targavfd
- 8.16. autoinstall-imonlcd
- 8.17. autoinstall-libcecdaemon
- 8.18. autoinstall-pvr350
- 8.19. TODO autoinstall-dvbhddevice
- 8.20. autoinstall-dvbsddevice
- 8.21. kodi
- 8.22. dvd
- 8.23. template-test
- 8.24. grub-config
- 9. Modules
- 10. Handlers
1 User Stories
1.1 yavdr-full
A User wants to install yaVDR without customization and relies on full automation.
After installing a supported Ubuntu Server version and (if needed) setting up the network connection, the install script is downloaded and started.
The install script adds the ansible PPA, installs ansible and other basic dependencies and runs the automated installation process.
Several roles are used to tie everything together:
- yavdr-common
- installs the basic set of packages needed and preconfigures the system (package sources, package manager settings, entires for network ports, directory structure etc.). Also collects information about the system
- autoinstall-ubuntu-drivers
- uses Ubuntu’s automatic detection for additional drivers (e.g. proprietary nvidia driver, microcode updates, VirtualBox guest additions)
- vdr
- install the vdr package and required plugins
- pulseaudio
- install and preconfigure pulseaudio
- yavdr-network
- configure WOL, add nfs client capabilites, install avahi-linker
- samba-server
- install and preconfigure a samba server
- nfs-server
- install nfs-kernelserver and preconfigure nfs exports (and avahi-announcements)
- autoinstall-satip
- install vdr-plugin-satip if a Sat>IP server has been found
- autoinstall-targavfd
- install vdr-plugin-targavfd if display is connected
- autoinstall-imonlcd
- install vdr-plugin-imonlcd if a matchind display is connected
- yavdr-xorg
- install and configure a systemd user session with a running X-server. A frontend script will manage VDR’s frontend and other applications like KODI. Also choose the best possible output plugin.
- grub-config
- update grub configuration based on executed roles
1.1.1 Using vdr, pulseaudio and xorg together
2 Notes
:export nil
2.1 TODO optimize and document data structure for xorg parsing script
2.2 TODO xorg.conf templates for intel, nvidia, noveau and radeon drivers
2.2.1 STARTED BusID für (nvidia) Grafikkarten aus lspci auslesen
Format: „%d:%d:%d“ (lspci liefert es als „%04x:%02x:%02x.%x“, domain, bus, device, function)
- Wie mit mehreren GPUs umgehen? Priorität bzw. Reihenfolge?
- Was ist mit NVidia Optimus/Bumblebee (AFAIK keine VDPAU-Funktionalität)?
- Wie BusID der xrandr-Ausgabe zuordnen?
2.2.2 NVIDIA-Dokumentation zur BusID:
- What is the format of a PCI Bus ID?
Different tools have different formats for the PCI Bus ID of a PCI device.
The X server’s „BusID“ X configuration file option interprets the BusID string in the format „bus@domain:device:function“ (the „@domain“ portion is only needed if the PCI domain is non-zero), in decimal. More specifically,
„%d@%d:%d:%d“, bus, domain, device, function in printf(3) syntax. NVIDIA X driver logging, nvidia-xconfig, and nvidia-settings match the X configuration file BusID convention.
The lspci(8) utility, in contrast, reports the PCI BusID of a PCI device in the format „domain:bus:device.function“, printing the values in hexadecimal. More specifically,
„%04x:%02x:%02x.%x“, domain, bus, device, function in printf(3) syntax. The „Bus Location“ reported in the /proc/driver/nvidia/gpus/0..N/information files matches the lspci format.
- Parsen der /proc/driver/nvidia/gpus/*/information Dateien
# read the BusID for nvidia cards and the model name # from the /proc/driver/nvidia/gpus/*/information file(s) from __future__ import print_function import glob import re BusID_RE = re.compile(( '(?P<domain>[0-9a-fA-F]+)' ':' '(?P<bus>[0-9a-fA-F]+)' ':' '(?P<device>[0-9a-fA-F]+)' '\.' '(?P<function>[0-9a-fA-F]+)' )) Model_RE = re.compile('Model:\s+(.*)') def get_BusIDs(): for gpu_info in glob.glob('/proc/driver/nvidia/gpus/*/information'): with open(gpu_info) as f: data = f.read() match = BusID_RE.search(data) if match: BusID = "{:d}@{:d}:{:d}:{:d}".format(*(int(n, 16) for n in match.groups())) yield BusID, Model_RE.match(data).groups()[0] if __name__ == '__main__': BusIDs = [BusID for BusID in get_BusIDs()] print(BusIDs)
2.3 TODO plan for customization of xorg settings by the user
either directly or using a configuration wizard or a web frontend
2.4 SOMEDAY select best frontend based on GPU
- intel
- softhddevice-vpp
- amd
- softhddevice-vpp
- nvidia
- softhddevice-openglosd (if no HEVC channels are needed)
3 Introduction
One of the major problems we faced with customized Ubuntu ISO files as installation media for prior yaVDR versions has been the limited hardware support and the time consuming process to create and update them. An interesting alternative to this approach is to enable the user to choose the installation medium himself so point releases, kernel versions and additional drivers can be chosen deliberately. After the basic setup is complete (and a working internet connection is available), a fully customizable install script completes the yaVDR installation.
4 Installing and configuring yaVDR with Ansible
This is an experimental feature which allows to set up a yaVDR installation based on a normal Ubuntu Server 16.04.x installation using Ansible.
This Manual is written in org-mode for Emacs and can rewrite the complete ansible configuration if you call org-babel-tangle
from within emacs.
To use this playbook on a Ubuntu Server Installation you need to run the following commands:
sudo apt-get install git
git clone https://github.com/yavdr/yavdr-ansible.git
cd yavdr-ansible
sudo ./install-yavdr.sh
4.1 Install script for local usage
if (( $EUID != 0 )); then echo "This script must be run using sudo or as root" exit fi apt-get -y install software-properties-common # Add repository for ansible add-apt-repository -y ppa:ansible/ansible # update packages apt-get update # install required packages apt-get -y install ansible # TODO: run ansible on local host ansible-playbook yavdr07.yml -b -i 'localhost_inventory' --connection=local
5 Playbooks
5.1 yavdr07.yml
The yavdr07.yml
playbook sets up a fully-featured yaVDR installation:
--- # file: yavdr07.yml # this playbook sets up a complete yaVDR 0.7 installation - name: set up yaVDR hosts: all become: true roles: - yavdr-common # install and configure the basic system - autoinstall-ubuntu-drivers # use ubuntu-drivers to install proprietary dirvers # (e.g. nvidia, virtualbox) - vdr # install vdr and related packages - yavdr-network # enable network client capabilities - samba-install # install samba server - samba-config # configure samba server - nfs-server # install nfs server - pulseaudio # install pulseaudio - yavdr-xorg # graphical session - yavdr-remote # remote configuration files, services and scripts - autoinstall-satip # install vdr-plugin-satip if a Sat>IP server has been found - autoinstall-targavfd # install vdr-plugin-targavfd if display is connected - autoinstall-imonlcd # install vdr-plugin-imonlcd if a matchind display is connected - autoinstall-pvr350 # install vdr-plugin-pvr350 if a matching card is detected - autoinstall-dvbsddevice # install vdr-plugin-dvbsddevice if a matching card is detected - kodi - dvd # set up packages and a udev rule to allow kodi and other players # to play and eject optical media - grub-config # configure grub handlers: - include: handlers/main.yml
5.2 yavdr07-headless.yml
For a headless server installation yavdr07-headless.yml
is a good choice
--- # file: yavdr07-headless.yml # this playbook set up a headless yaVDR 0.7 installation - name: set up a headless yaVDR server hosts: all become: true roles: - yavdr-common - vdr - yavdr-network - samba-server - samba-config - nfs-server - grub-config - autoinstall-satip handlers: - include: handlers/main.yml
6 Hosts
This playbook can either be used to run the installation on the localhost or any other PC in the network that can be accessed via ssh. Simply add the host names or IP addresses to the hosts file in the respective section:
[localhost] localhost connection=local
7 Group Variables
7.1 default text for templates used by ansible
--- # file: group_vars/all # this is the standard text to put in templates ansible_managed_file: "*** YAVDR: ANSIBLE MANAGED FILE ***"
7.2 PPAs
branch: unstable ppa_owner: 'ppa:yavdr' # a list of all package repositories to be added to the installation repositories: - '{{ ppa_owner }}/main' - '{{ ppa_owner }}/unstable-main' - '{{ ppa_owner }}/{{branch}}-vdr' - '{{ ppa_owner }}/{{branch}}-yavdr' - '{{ ppa_owner }}/{{branch}}-kodi'
7.3 VDR user, directories, special configuration and plugins
# properties of the user vdr and vdr-related options vdr: user: vdr group: vdr uid: 666 gid: 666 home: /var/lib/vdr confdir: /var/lib/vdr recdir: /srv/vdr/video hide_first_recording_level: false safe_dirnames: true # escape characters (useful for windows clients and FAT/NTFS file systems) override_vdr_charset: false # add the vdr plugins you want to install vdr_plugins: - vdr-plugin-devstatus - vdr-plugin-markad - vdr-plugin-restfulapi - vdr-plugin-softhddevice
7.4 Media directories
# dictionary of directories for (shared) files. Automatically exported via NFS and Samba if those roles are enabled media_dirs: audio: /srv/audio video: /srv/audio pictures: /srv/picture files: /srv/files backups: /srv/backups recordings: '{{ vdr.recdir }}'
7.5 NFS
nfs: insecure: false # set to true for OS X clients or if you plan to use libnfs as unprivileged user (e.g. KODI)
7.6 Samba
samba: workgroup: YAVDR windows_compatible: '{{ vdr.safe_dirnames }}' # set to true to disable unix extensions, enable follow symlinks and wide links
7.7 Additional packages
# additional packages you want to install extra_packages: - vim - tree - w-scan - bpython - bpython3
7.8 System pre-configuration
#system: # shutdown: poweroff grub: timeout: 0 boot_options: quiet nosplash
8 Roles
8.1 install-dependencies
8.2 nvidia-381 drivers
install nvidia-381 from ppa:graphics-drivers/ppa
8.2.1 tasks
8.3 yavdr-common
This role is used to set up a basic yaVDR installation. It creates the directories, installs the vdr and other useful packages.
8.3.1 default variables
This section is for reference only, please use the files in global_vars
for customizations.
--- # file: roles/yavdr-common/defaults/main.yml
- Repositories
You can set a list of package repositories which provide the necessary packages. Feel free to use own PPAs if you need special customization to the VDR and it’s plugins.
branch: unstable repositories: - 'ppa:yavdr/main' - 'ppa:yavdr/unstable-main' - 'ppa:yavdr/{{branch}}-vdr' - 'ppa:yavdr/{{branch}}-kodi' - 'ppa:yavdr/{{branch}}-yavdr'
- Drivers
Automatically installed drivers can be very useful, but if you know you need a certain driver, you can simply set it’s value to true. If you don’t want a driver to be installed, set it’s value to false.
drivers: sundtek: auto ddvb-dkms: auto
- Additional Packages
Add additional packages you would like to have on your installation to this list
extra_packages: - vim - tree - w-scan
- VDR
This section allows you to set the recording directory, the user and group that runs the vdr and it’s home directory.
- user
- the vdr user name
- group
- the main group for the user vdr
- uid
- the user id for the user vdr
- gid
- the group id for the group vdr
- home
- the home directory for the user vdr
- recdir
- the recording directory used by VDR
- hide_first_recording_level
- let vdr hide the first directory level of it’s recording directory so the content of multiple directories is shown merged together
- safe_dirnames
- replace special characters which are not compatible with Windows file systems and Samba shares
- override_vdr_charset
- workaround for channels with weird EPG encodings, e.g. Sky
vdr: user: vdr group: vdr uid: 666 gid: 666 home: /var/lib/vdr recdir: /srv/vdr/video hide_first_recording_level: false safe_dirnames: true override_vdr_charset: false
8.3.2 tasks
yavdr-common executes the following tasks:
- main.yml
- Disable default installation of recommended packages
This task prevents apt to automatically install all recommended dependencies for packages:
--- - name: apt | prevent automatic installation of recommended packages template: src: templates/90-norecommends.j2 dest: /etc/apt/apt.conf.d/90norecommends
- Use bash instead of dash
- name: use bash instead of dash shell: | echo "set dash/sh false" | debconf-communicate dpkg-reconfigure -f noninteractive dash
- create user vdr
- Disable release-upgrade notifications
- name: disable release-upgrade notifications lineinfile: dest: /etc/update-manager/release-upgrades backrefs: yes state: present regexp: '^(Prompt=).*$' line: '\1never'
- Set up package repositories
- name: add yaVDR PPAs apt_repository: repo: '{{ item }}' state: present update_cache: yes with_items: '{{ repositories }}' - name: upgrade existing packages apt: upgrade: dist update_cache: yes
- Install essential packages
- name: apt | install basic packages apt: name: '{{ item }}' state: present install_recommends: no with_items: - anacron - at - bash-completion #- biosdevname # caution: may change device names after a minimal installation! - debconf-utils - linux-firmware - psmisc - python-kmodpy - python-usb - python3-usb - software-properties-common - ssh - wget - wpasupplicant - usbutils - xfsprogs
- Install additional packages (user defined)
- name: apt | install extra packages apt: name: '{{ item }}' state: present install_recommends: no with_items: '{{ extra_packages }}'
- Gather facts with custom modules
- name: get information about usb and pci hardware and loaded kernel modules hardware_facts: usb: True pci: True modules: True gpus: True - debug: var: usb verbosity: 1 - debug: var: pci verbosity: 1 - debug: var: modules verbosity: 1 - debug: var: gpus verbosity: 1
- create media directories
- Disable default installation of recommended packages
8.3.3 templates
{{ ansible_managed_file | comment('c') }} // Recommends are as of now still abused in many packages APT::Install-Recommends "0"; APT::Install-Suggests "0";
8.4 vdr
8.4.1 tasks
- install the basic vdr packages
--- # file: roles/vdr/tasks/main.yml - name: apt | install basic vdr packages apt: name: '{{ item }}' state: present install_recommends: no with_items: - vdr - vdrctl - vdr-plugin-dbus2vdr
- Add svdrp/svdrp-disc to /etc/services
- name: add svdrp and svdrp-disc to /etc/services lineinfile: dest: /etc/services state: present line: "{{ item }}" with_items: - "svdrp 6419/tcp" - "svdrp-disc 6419/udp"
- Set up the recording directory for the vdr user
- name: create vdr recdir file: state: directory owner: '{{ vdr.user }}' group: '{{ vdr.group }}' mode: 0775 dest: '{{ vdr.recdir }}' - name: set option to use hide-first-recording-level patch blockinfile: dest: /etc/vdr/conf.d/04-vdr-hide-first-recordinglevel.conf create: true block: | [vdr] --hide-first-recording-level when: vdr.hide_first_recording_level - name: create local dir in recdir file: state: directory owner: '{{ vdr.user }}' group: '{{ vdr.group }}' mode: '0775' dest: '{{ vdr.recdir }}/local' when: vdr.hide_first_recording_level # TODO: set recdir, user etc. in /etc/vdr/conf.d/
- Install additional vdr plugins
The additional plugins to install can be set in the variable
{{vdr_plugins}}
in the group variables- name: apt | install additional vdr plugins apt: name: '{{ item }}' state: present install_recommends: no with_items: '{{ vdr_plugins | default({}) }}' notify: [ 'Restart VDR' ]
- copy vdr configuration files (if they don’t exist yet)
- name: ensure vdr is stopped systemd: name: vdr.service state: stopped notify: [ 'Start VDR' ] - name: "vdr configuration | copy remote.conf if it doesn't exist yet" copy: src: files/remote.conf dest: '{{ vdr.confdir }}/remote.conf' owner: '{{ vdr.user }}' group: '{{ vdr.group }}' mode: 0644 force: no - name: "vdr configuration | copy keymacros.conf if it doesn't exist yet" copy: src: files/keymacros.conf dest: '{{ vdr.confdir }}/keymacros.conf' owner: '{{ vdr.user }}' group: '{{ vdr.group }}' mode: 0644 force: no
8.4.2 templates
8.4.3 files
- remote.conf
LIRC.Up KEY_UP LIRC.Down KEY_DOWN LIRC.Menu KEY_MENU LIRC.Ok KEY_OK LIRC.Back KEY_ESC LIRC.Left KEY_LEFT LIRC.Right KEY_RIGHT LIRC.Red KEY_RED LIRC.Green KEY_GREEN LIRC.Yellow KEY_YELLOW LIRC.Blue KEY_BLUE LIRC.0 KEY_0 LIRC.1 KEY_1 LIRC.2 KEY_2 LIRC.3 KEY_3 LIRC.4 KEY_4 LIRC.5 KEY_5 LIRC.6 KEY_6 LIRC.7 KEY_7 LIRC.8 KEY_8 LIRC.9 KEY_9 LIRC.Info KEY_INFO LIRC.Play KEY_PLAY LIRC.Pause KEY_PAUSE LIRC.Play/Pause KEY_PLAYPAUSE LIRC.Stop KEY_STOP LIRC.Record KEY_RECORD LIRC.FastFwd KEY_FASTFORWARD LIRC.FastRew KEY_REWIND LIRC.Next KEY_NEXT LIRC.Prev KEY_BACK LIRC.Power KEY_POWER2 LIRC.Channel+ KEY_CHANNELUP LIRC.Channel- KEY_CHANNELDOWN LIRC.PrevChannel KEY_PREVIOUS LIRC.Volume+ KEY_VOLUMEUP LIRC.Volume- KEY_VOLUMEDOWN LIRC.Mute KEY_MUTE LIRC.Subtitles KEY_SUBTITLE LIRC.Schedule KEY_EPG LIRC.Channels KEY_CHANNEL LIRC.Commands KEY_FAVORITES LIRC.Audio KEY_MODE LIRC.Timers KEY_TIME LIRC.Recordings KEY_PVR LIRC.Setup KEY_SETUP LIRC.User0 KEY_TEXT LIRC.User1 KEY_PROG1 LIRC.User2 KEY_PROG2 LIRC.User3 KEY_PROG3 LIRC.User4 KEY_PROG4 LIRC.User5 KEY_AUDIO LIRC.User6 KEY_VIDEO LIRC.User7 KEY_IMAGES LIRC.User8 KEY_FN LIRC.User9 KEY_SCREEN XKeySym.Up Up XKeySym.Down Down XKeySym.Menu Home XKeySym.Menu Tab XKeySym.Menu KP_Home XKeySym.Ok Return XKeySym.Ok KP_Enter XKeySym.Back BackSpace XKeySym.Back KP_Separator XKeySym.Left Left XKeySym.Right Right XKeySym.Up KP_Up XKeySym.Down KP_Down XKeySym.Left KP_Left XKeySym.Right KP_Right XKeySym.Red F1 XKeySym.Green F2 XKeySym.Yellow F3 XKeySym.Blue F4 XKeySym.0 0 XKeySym.1 1 XKeySym.2 2 XKeySym.3 3 XKeySym.4 4 XKeySym.5 5 XKeySym.6 6 XKeySym.7 7 XKeySym.8 8 XKeySym.9 9 XKeySym.0 KP_0 XKeySym.1 KP_1 XKeySym.2 KP_2 XKeySym.3 KP_3 XKeySym.4 KP_4 XKeySym.5 KP_5 XKeySym.6 KP_6 XKeySym.7 KP_7 XKeySym.8 KP_8 XKeySym.9 KP_9 XKeySym.Info End XKeySym.Info KP_End XKeySym.Pause F9 XKeySym.FastFwd F6 XKeySym.FastRew F5 XKeySym.Power Pause XKeySym.Volume+ F12 XKeySym.Volume- F11 XKeySym.Volume+ KP_Add XKeySym.Volume- KP_Subtract XKeySym.Mute F10 XKeySym.User1 F5 XKeySym.User2 F6 XKeySym.User3 F7 XKeySym.User4 F8 XKeySym.User5 Print XKeySym.User6 Scroll_Lock XKeySym.User7 Insert XKeySym.User8 KP_Divide XKeySym.User9 KP_Multiply XKeySym.Audio Menu XKeySym.Channel+ Prior XKeySym.Channel- Next XKeySym.Channel+ KP_Prior XKeySym.Channel- KP_Next XKeySym.Volume+ XF86AudioRaiseVolume XKeySym.Volume- XF86AudioLowerVolume XKeySym.Mute XF86AudioMute XKeySym.Stop XF86AudioStop XKeySym.Play/Pause XF86AudioPlay XKeySym.Prev XF86AudioPrev XKeySym.Next XF86AudioNext
- keymacros.conf
# Remote control key macros for VDR # # Format: # # macrokey key1 key2 key3... # macrokey @plugin key1 key2 key3... # # See man vdr(5) Red Recordings Green Schedule Yellow Info Blue Timers User0 @osdteletext
8.5 STARTED yavdr-network
8.5.1 default variables
install_avahi: true
8.5.2 tasks
--- # this playbook sets up network services for a yaVDR installation - name: apt |install packages for network services apt: name: '{{ item }}' state: present install_recommends: no with_items: - avahi-daemon - avahi-utils - biosdevname - ethtool - nfs-common - vdr-addon-avahi-linker - wakeonlan # Does this really work? We need a way to check if an interface supports WOL - Python Skript? # - name: check WOL capabilities of network interfaces # shell: 'ethtool {{ item }} | grep -Po "(?<=Supports\sWake-on:\s).*$"' # register: wol # with_items: '{% for interface in ansible_interfaces if interface != 'lo' and interface != 'bond0' %}' - name: restart autofs if running systemd: name: autofs state: restarted enabled: yes masked: no - name: ensure autofs is running systemd: name: autofs state: started enabled: yes masked: no - name: restart avahi-linker if running systemd: name: avahi-linker state: restarted enabled: yes masked: no - name: start avahi-linker systemd: name: avahi-linker state: started enabled: yes masked: no
8.6 nfs-server
8.6.1 TODO avahi-services für NFS beim Stoppen des nfs-kernel-servers depublizieren, beim Start wieder announcen
8.6.2 tasks
--- - name: install nfs server packages apt: name: '{{ item }}' state: present install_recommends: no with_items: - nfs-kernel-server - nfs-common - name: create /etc/exports template: src: templates/nfs-exports.j2 dest: /etc/exports notify: [ 'Restart NFS Kernel Server' ] - name: populate /etc/avahi/services template: src: templates/avahi/service.j2 dest: '/etc/avahi/services/yavdr-{{ item.key }}.service' with_dict: '{{ media_dirs }}'
8.6.3 templates
- /etc/exports
/srv *(rw,fsid=0,sync,no_subtree_check,all_squash,anongid={{ vdr.gid }},anonuid={{ vdr.uid }}) {% for name, path in media_dirs.iteritems() %} {{ path }} *(rw,fsid={{ loop.index }},sync,no_subtree_check,all_squash,anongid={{ vdr.gid }},anonuid={{ vdr.uid }}{{ ',insecure' if nfs.insecure else '' }}) {% endfor %}
- avahi services
<?xml version="1.0" standalone='no'?> <!DOCTYPE service-group SYSTEM "avahi-service.dtd"> <service-group> <name replace-wildcards="yes">{{ item.key|capitalize }} on %h</name> ## Name <service> <type>_nfs._tcp</type> <port>2049</port> <txt-record>path={{ item.value }}</txt-record> ## path to shared Folder <txt-record>subtype={{ 'vdr' if item.key == 'recordings' else item.key }}</txt-record> ## subtype </service> </service-group>
8.7 TODO yavdr-remote
8.7.1 default variables
8.7.2 tasks
--- # This role is used to set up the yaVDR remote control configuration. - name: apt | install yavdr-remote apt: name: yavdr-remote state: present - name: apt | install eventlircd apt: name: eventlircd state: present when: install_eventlircd is defined and install_eventlircd - name: apt | install lirc apt: name: lircd state: present when: - install_lircd is defined and install_lircd - name: stop, mask and disable lircd.socket and lircd.service # (the default lirc configuration conflicts with eventlircd) systemd: name: '{{ item }}' enabled: no state: stopped masked: yes with_items: - lircd.service - lircd.socket ignore_errors: yes # TODO: upload lircd2uinput package to PPA #- name: install lircd2uinput # tag: install # apt: # name: lircd2uinput # state: present # when: # install_eventlircd is defined and install_eventlircd
8.7.3 templates
8.7.4 files
8.8 pulseaudio
8.8.1 tasks
--- - name: apt | install pulseaudio and pavucontrol apt: name: '{{ item }}' state: present install_recommends: no with_items: - pulseaudio - pavucontrol - name: create /etc/asound.conf with pulseaudio as default device template: src: templates/alsa/asound.conf.j2 dest: /etc/asound.conf
8.8.2 templates
# Use PulseAudio by default pcm.!default { type pulse fallback "sysdefault" hint { show on description "Default ALSA Output (currently PulseAudio Sound Server)" } } ctl.!default { type pulse fallback "sysdefault" }
8.9 yavdr-xorg
8.9.1 TODO automatic X-server configuration
[X]
detect connected display[X]
read EDID from displays[ ]
create a xorg.conf for nvidia/intel/amd gpus
- HOLD Nvidia-GPUs:read EDID:
$ nvidia-xconfig --extract-edids-from-file=/var/log/Xorg.0.log --extract-edids-output-file=/tmp/edid.bin.0 Found 2 EDIDs in "/var/log/Xorg.0.log". Wrote EDID for "DELL 2407WFP (CRT-1)" to "/tmp/edid.bin.0.0" (128 bytes). Wrote EDID for "ADI A715 (DFP-1)" to "/tmp/edid.bin.0.1" (128 bytes). $ xrandr -q Screen 0: minimum 8 x 8, current 3200 x 1200, maximum 8192 x 8192 DVI-I-0 disconnected primary (normal left inverted right x axis y axis) VGA-0 connected 1920x1200+1280+0 (normal left inverted right x axis y axis) 519mm x 324mm 1920x1200 59.95*+ 1680x1050 59.95 1280x1024 75.02 60.02 1152x864 75.00 1024x768 75.03 60.00 800x600 75.00 60.32 640x480 75.00 59.94 DVI-I-1 disconnected (normal left inverted right x axis y axis) HDMI-0 connected 1280x1024+0+0 (normal left inverted right x axis y axis) 338mm x 270mm 1280x1024 60.02*+ 1024x768 60.00 800x600 60.32 640x480 59.95 59.94 $ parse-edid < /tmp/edid.bin.0.1 Checksum Correct Section "Monitor" Identifier "ADI A715" ModelName "ADI A715" VendorName "ADI" # Monitor Manufactured week 15 of 2003 # EDID version 1.3 # Digital Display DisplaySize 330 270 Gamma 2.20 Option "DPMS" "true" #Not giving standard mode: 640x480, 60Hz #Not giving standard mode: 800x600, 60Hz #Not giving standard mode: 1024x768, 60Hz #Not giving standard mode: 1280x1024, 60Hz Modeline "Mode 0" 108.00 1280 1328 1440 1688 1024 1025 1028 1066 +hsync +vsync Modeline "Mode 1" 40.00 800 840 968 1056 600 601 605 628 +hsync +vsync EndSection $ parse-edid < /tmp/edid.bin.0.0 Checksum Correct Section "Monitor" Identifier "DELL 2407WFP" ModelName "DELL 2407WFP" VendorName "DEL" # Monitor Manufactured week 24 of 2007 # EDID version 1.3 # Analog Display Option "SyncOnGreen" "true" DisplaySize 520 330 Gamma 2.20 Option "DPMS" "true" Horizsync 30-83 VertRefresh 56-76 # Maximum pixel clock is 170MHz #Not giving standard mode: 1280x1024, 60Hz #Not giving standard mode: 1600x1200, 60Hz #Not giving standard mode: 1152x864, 75Hz #Not giving standard mode: 1680x1050, 60Hz Modeline "Mode 0" 154.00 1920 1968 2000 2080 1200 1203 1209 1235 +hsync -vsync EndSection
- DONE Start X-server with debug-output
# /etc/systemd/system/x-debug@.service [Unit] Description=X with verbose logging on %I Wants=graphical.target Before=graphical.target Conflicts=xlogin@vdr.service x@vt7.service [Service] Type=forking ExecStart=/usr/bin/x-daemon -logverbose 6 -noreset %I -config xdiscover.conf
# /etc/X11/xdiscover.conf Section "Device" Identifier "nvidia" Driver "nvidia" Option "NoLogo" "true" Option "DynamicTwinView" "true" Option "NoFlip" "false" # Option "FlatPanelProperties" "Scaling = Native" # Option "ModeValidation" "NoVesaModes, NoXServerModes" # Option "ModeDebug" "true" # Option "HWCursor" "false" EndSection Section "Screen" Identifier "screen" Device "nvidia" EndSection Section "Extensions" Option "Composite" "false" EndSection
- DONE python-script for parsing xrandr –verbose output
- Example output
$ xrandr --verbose Screen 0: minimum 8 x 8, current 1280 x 720, maximum 8192 x 8192 VGA-0 disconnected primary (normal left inverted right x axis y axis) Identifier: 0x1c4 Timestamp: 18571 Subpixel: unknown Clones: CRTCs: 0 1 Transform: 1.000000 0.000000 0.000000 0.000000 1.000000 0.000000 0.000000 0.000000 1.000000 filter: BorderDimensions: 4 supported: 4 Border: 0 0 0 0 range: (0, 65535) SignalFormat: VGA supported: VGA ConnectorType: VGA ConnectorNumber: 0 _ConnectorLocation: 1 HDMI-0 connected 1280x720+0+0 (0x1cb) normal (normal left inverted right x axis y axis) 885mm x 498mm Identifier: 0x1c5 Timestamp: 18571 Subpixel: unknown Gamma: 1.0:1.0:1.0 Brightness: 1.0 Clones: CRTC: 0 CRTCs: 0 1fg Transform: 1.000000 0.000000 0.000000 0.000000 1.000000 0.000000 0.000000 0.000000 1.000000 filter: EDID: 00ffffffffffff004c2d800100000000 2c0e01038059328c0ae2bda15b4a9824 15474a20000001010101010101010101 010101010101011d007251d01e206e28 550075f23100001e011d00bc52d01e20 b828554075f23100001e000000fd0032 3d0f2e08000a202020202020000000fc 0053414d53554e470a20202020200181 02031971468413051403122309070783 01000065030c001000011d8018711c16 20582c250075f23100009e011d80d072 1c1620102c258075f23100009e8c0ad0 8a20e02d10103e960075f2310000188c 0ad090204031200c40550075f2310000 18000000000000000000000000000000 000000000000000000000000000000ca BorderDimensions: 4 supported: 4 Border: 39 24 41 21 range: (0, 65535) SignalFormat: TMDS supported: TMDS ConnectorType: HDMI ConnectorNumber: 1 _ConnectorLocation: 2 1280x720 (0x1c6) 74.2MHz +HSync +VSync +preferred h: width 1280 start 1390 end 1430 total 1650 skew 0 clock 45.0KHz v: height 720 start 725 end 730 total 750 clock 60.0Hz 1920x1080 (0x1c7) 74.2MHz +HSync +VSync Interlace h: width 1920 start 2008 e#nd 2052 total 2200 skew 0 clock 33.8KHz v: height 1080 start 1084 end 1094 total 1124 clock 60.1Hz 1920x1080 (0x1c8) 74.2MHz +HSync +VSync Interlace h: width 1920 start 2008 end 2052 total 2200 skew 0 clock 33.7KHz v: height 1080 start 1084 end 1094 total 1124 clock 60.0Hz 1920x1080 (0x1c9) 74.2MHz +HSync +VSync Interlace h: width 1920 start 2448 end 2492 total 2640 skew 0 clock 28.1KHz v: height 1080 start 1084 end 1094 total 1124 clock 50.0Hz 1280x720 (0x1ca) 74.2MHz +HSync +VSync h: width 1280 start 1390 end 1430 total 1650 skew 0 clock 45.0KHz v: height 720 start 725 end 730 total 750 clock 59.9Hz 1280x720 (0x1cb) 74.2MHz +HSync +VSync *current h: width 1280 start 1720 end 1760 total 1980 skew 0 clock 37.5KHz v: height 720 start 725 end 730 total 750 clock 50.0Hz 800x600 (0x1cc) 40.0MHz +HSync +VSync h: width 800 start 840 end 968 total 1056 skew 0 clock 37.9KHz v: height 600 start 601 end 605 total 628 clock 60.3Hz 800x600 (0x1cd) 36.0MHz +HSync +VSync h: width 800 start 824 end 896 total 1024 skew 0 clock 35.2KHz v: height 600 start 601 end 603 total 625 clock 56.2Hz 720x576 (0x1ce) 27.0MHz -HSync -VSync h: width 720 start 732 end 796 total 864 skew 0 clock 31.2KHz v: height 576 start 581 end 586 total 625 clock 50.0Hz 720x480 (0x1cf) 27.0MHz -HSync -VSync h: width 720 start 736 end 798 total 858 skew 0 clock 31.5KHz v: height 480 start 489 end 495 total 525 clock 59.9Hz 640x480 (0x1d0) 25.2MHz -HSync -VSync h: width 640 start 656 end 752 total 800 skew 0 clock 31.5KHz v: height 480 start 490 end 492 total 525 clock 59.9Hz 320x240 (0x1d1) 12.6MHz -HSync -VSync DoubleScan h: width 320 start 328 end 376 total 400 skew 0 clock 31.5KHz v: height 240 start 245 end 246 total 262 clock 60.1Hz
$ xrandr --verbose Screen 0: minimum 8 x 8, current 3200 x 1200, maximum 8192 x 8192 DVI-I-0 disconnected primary (normal left inverted right x axis y axis) Identifier: 0x1c4 Timestamp: 641679 Subpixel: unknown Clones: CRTCs: 0 1 Transform: 1.000000 0.000000 0.000000 0.000000 1.000000 0.000000 0.000000 0.000000 1.000000 filter: BorderDimensions: 4 supported: 4 Border: 0 0 0 0 range: (0, 65535) SignalFormat: VGA supported: VGA ConnectorType: DVI-I ConnectorNumber: 0 _ConnectorLocation: 0 VGA-0 connected 1920x1200+1280+0 (0x1c6) normal (normal left inverted right x axis y axis) 519mm x 324mm Identifier: 0x1c5 Timestamp: 641679 Subpixel: unknown Gamma: 1.0:1.0:1.0 Brightness: 1.0 Clones: CRTC: 1 CRTCs: 0 1 Transform: 1.000000 0.000000 0.000000 0.000000 1.000000 0.000000 0.000000 0.000000 1.000000 filter: EDID: 00ffffffffffff0010ac16a0534b4431 181101030e342178eeee91a3544c9926 0f5054a54b008180a940714fb3000101 010101010101283c80a070b023403020 360007442100001a000000ff00555935 343537364531444b5320000000fc0044 454c4c20323430375746500a000000fd 00384c1e5311000a20202020202000f1 BorderDimensions: 4 supported: 4 Border: 0 0 0 0 range: (0, 65535) SignalFormat: VGA supported: VGA ConnectorType: VGA ConnectorNumber: 2 _ConnectorLocation: 2 1920x1200 (0x1c6) 154.000MHz +HSync -VSync *current +preferred h: width 1920 start 1968 end 2000 total 2080 skew 0 clock 74.04KHz v: height 1200 start 1203 end 1209 total 1235 clock 59.95Hz 1680x1050 (0x1c7) 146.250MHz -HSync +VSync h: width 1680 start 1784 end 1960 total 2240 skew 0 clock 65.29KHz v: height 1050 start 1053 end 1059 total 1089 clock 59.95Hz 1280x1024 (0x1c8) 135.000MHz +HSync +VSync h: width 1280 start 1296 end 1440 total 1688 skew 0 clock 79.98KHz v: height 1024 start 1025 end 1028 total 1066 clock 75.02Hz 1280x1024 (0x1c9) 108.000MHz +HSync +VSync h: width 1280 start 1328 end 1440 total 1688 skew 0 clock 63.98KHz v: height 1024 start 1025 end 1028 total 1066 clock 60.02Hz 1152x864 (0x1ca) 108.000MHz +HSync +VSync h: width 1152 start 1216 end 1344 total 1600 skew 0 clock 67.50KHz v: height 864 start 865 end 868 total 900 clock 75.00Hz 1024x768 (0x1cb) 78.750MHz +HSync +VSync h: width 1024 start 1040 end 1136 total 1312 skew 0 clock 60.02KHz v: height 768 start 769 end 772 total 800 clock 75.03Hz 1024x768 (0x1cc) 65.000MHz -HSync -VSync h: width 1024 start 1048 end 1184 total 1344 skew 0 clock 48.36KHz v: height 768 start 771 end 777 total 806 clock 60.00Hz 800x600 (0x1cd) 49.500MHz +HSync +VSync h: width 800 start 816 end 896 total 1056 skew 0 clock 46.88KHz v: height 600 start 601 end 604 total 625 clock 75.00Hz 800x600 (0x1ce) 40.000MHz +HSync +VSync h: width 800 start 840 end 968 total 1056 skew 0 clock 37.88KHz v: height 600 start 601 end 605 total 628 clock 60.32Hz 640x480 (0x1cf) 31.500MHz -HSync -VSync h: width 640 start 656 end 720 total 840 skew 0 clock 37.50KHz v: height 480 start 481 end 484 total 500 clock 75.00Hz 640x480 (0x1d0) 25.175MHz -HSync -VSync h: width 640 start 656 end 752 total 800 skew 0 clock 31.47KHz v: height 480 start 490 end 492 total 525 clock 59.94Hz DVI-I-1 disconnected (normal left inverted right x axis y axis) Identifier: 0x1d1 Timestamp: 641679 Subpixel: unknown Clones: CRTCs: 0 1 Transform: 1.000000 0.000000 0.000000 0.000000 1.000000 0.000000 0.000000 0.000000 1.000000 filter: BorderDimensions: 4 supported: 4 Border: 0 0 0 0 range: (0, 65535) SignalFormat: TMDS supported: TMDS ConnectorType: DVI-I ConnectorNumber: 0 _ConnectorLocation: 0 HDMI-0 connected 1280x1024+0+0 (0x1c9) normal (normal left inverted right x axis y axis) 338mm x 270mm Identifier: 0x1d2 Timestamp: 641679 Subpixel: unknown Gamma: 1.0:1.0:1.0 Brightness: 1.0 Clones: CRTC: 0 CRTCs: 0 1 Transform: 1.000000 0.000000 0.000000 0.000000 1.000000 0.000000 0.000000 0.000000 1.000000 filter: EDID: 00ffffffffffff0004895d2320090000 0f0d0103e0211b782ac5c6a3574a9c23 124f5421080031404540614081800101 010101010101302a009851002a403070 1300520e1100001ea00f200031581c20 28801400520e1100001e000000ff0033 31355430324530323333360a000000fc 0041444920413731350a20202020002b BorderDimensions: 4 supported: 4 Border: 0 0 0 0 range: (0, 65535) SignalFormat: TMDS supported: TMDS ConnectorType: HDMI ConnectorNumber: 1 _ConnectorLocation: 1 1280x1024 (0x1c9) 108.000MHz +HSync +VSync *current +preferred h: width 1280 start 1328 end 1440 total 1688 skew 0 clock 63.98KHz v: height 1024 start 1025 end 1028 total 1066 clock 60.02Hz 1024x768 (0x1cc) 65.000MHz -HSync -VSync h: width 1024 start 1048 end 1184 total 1344 skew 0 clock 48.36KHz v: height 768 start 771 end 777 total 806 clock 60.00Hz 800x600 (0x1ce) 40.000MHz +HSync +VSync h: width 800 start 840 end 968 total 1056 skew 0 clock 37.88KHz v: height 600 start 601 end 605 total 628 clock 60.32Hz 640x480 (0x1d3) 25.180MHz -HSync -VSync h: width 640 start 648 end 744 total 800 skew 0 clock 31.48KHz v: height 480 start 482 end 484 total 525 clock 59.95Hz 640x480 (0x1d0) 25.175MHz -HSync -VSync h: width 640 start 656 end 752 total 800 skew 0 clock 31.47KHz v: height 480 start 490 end 492 total 525 clock 59.94Hz
- parse hex-strings
>>> import binascii >>> s = "deadbeef" >>> binascii.a2b_hex(s) b'\xde\xad\xbe\xef'
- Example output
8.9.2 default variables
8.9.3 tasks
--- # file: roles/yavdr-xorg/tasks/main.yml # TODO: use hooks or requirements instead - name: Stop VDR systemd: name: vdr.service state: stopped enabled: yes notify: ['Start VDR'] - name: create directory /etc/systemd/system/vdr.service.d/ file: dest: /etc/systemd/system/vdr.service.d/ state: directory - name: add environment file for vdr.service template: src: templates/systemd/vdr-environ.j2 dest: /etc/systemd/system/vdr.service.d/load-environ.conf - name: Stop xlogin systemd: name: xlogin@vdr.service state: stopped enabled: yes - name: Stop x systemd: name: x@vt7.service state: stopped - name: install packages for xorg apt: name: '{{ item }}' state: present with_items: - xorg - xserver-xorg-video-all - xserver-xorg-input-all - xlogin - xterm - openbox - tmux - kiosk-browser - read-edid #- yavdr-xorg - name: "stop x@vt7.service" systemd: name: "x@vt7.service" state: stopped - name: "expand template for x-verbose@.service" template: src: "templates/systemd/system/x-verbose@.service.j2" dest: "/etc/systemd/system/x-verbose@.service" - name: "expand template for xorg-verbose.conf" template: src: "templates/xorg-verbose.conf.j2" dest: "/etc/X11/xorg-verbose.conf" - name: "start x-verbose@.service" systemd: name: "x-verbose@vt7.service" state: started enabled: false masked: false daemon_reload: true - name: "wait a little bit, so X has some time to start up (needed?)" wait_for: timeout: 3 - name: "detect xorg configuration" action: xrandr_facts - debug: var: xorg.primary - debug: var: xorg.secondary when: xorg.secondary is defined - name: "stop x-verbose@vt7.service" systemd: name: "x-verbose@vt7.service" state: stopped enabled: false masked: true # TODO: expand template for xorg.conf (or snippets) # with respect for the available graphics card driver # nvidia, noveau, intel, radeon - name: create xorg.conf (for nvidia driver) template: src: templates/xorg.conf.j2 dest: /etc/X11/xorg.conf backup: yes - name: create folders for user session file: state: directory dest: '{{ item }}' mode: '0775' owner: '{{ vdr.user }}' group: '{{ vdr.group }}' with_items: - '{{ vdr.home }}/.config/systemd/user' - '{{ vdr.home }}/.config/openbox/' - name: create folder for customizations of vdr.service file: state: directory dest: /etc/systemd/system/vdr.service.d mode: '0775' - name: add dependency to X-server for vdr.service using a drop-in template: src: templates/vdr-xorg.conf dest: /etc/systemd/system/vdr.service.d/ - name: create folders for user configuration files file: state: directory dest: '{{ item }}' mode: '0775' owner: '{{ vdr.user }}' group: '{{ vdr.group }}' with_items: - '{{ vdr.home }}/.config/systemd/user' - '{{ vdr.home }}/.config/openbox' - '{{ vdr.home }}/.config/pulse' - name: expand template for .xinitrc for vdr user template: src: 'templates/.xinitrc.j2' dest: '{{ vdr.home }}/.xinitrc' mode: 0755 owner: '{{ vdr.user }}' group: '{{ vdr.group }}' - name: expand template for openbox autostart template: src: 'templates/openbox/autostart.j2' dest: '{{ vdr.home }}/.config/openbox/autostart' mode: 0755 owner: '{{ vdr.user }}' group: '{{ vdr.group }}' - name: expand rc.xml for openbox template: src: 'templates/openbox/rc.xml.j2' dest: '{{ vdr.home }}/.config/openbox/rc.xml' mode: 0755 owner: '{{ vdr.user }}' group: '{{ vdr.group }}' - name: create yavdr-desktop.target for the user session template: src: 'templates/systemd/user/yavdr-desktop.target.j2' dest: '{{ vdr.home }}/.config/systemd/user/yavdr-desktop.target' mode: 0755 owner: '{{ vdr.user }}' group: '{{ vdr.group }}' - name: disable pulseaudio autospawning lineinfile: path: '{{ vdr.home }}/.config/pulse/client.conf' line: 'autospawn = no' create: yes state: present owner: '{{ vdr.user }}' group: '{{ vdr.group }}' - name: set a login shell for the user vdr user: name: '{{ vdr.user }}' shell: '/bin/bash' state: present uid: '{{ vdr.uid }}' groups: '{{ vdr.group }}' append: yes - name: create tmux.service for the session template: src: roles/yavdr-xorg/templates/systemd/user/tmux.service.j2 dest: '{{ vdr.home }}/.config/systemd/user/tmux.service' - name: enable and start xlogin for the user vdr systemd: daemon_reload: yes name: 'xlogin@{{ vdr.user }}' enabled: yes state: started
8.9.4 templates
- xorg
- x-verbose@.service
[Unit] Description=X with verbose logging on %I Wants=graphical.target Before=graphical.target [Service] Type=forking ExecStart=/usr/bin/x-daemon -logverbose 6 -noreset %I -config /etc/X11/xorg-debug.conf
- Drop-in snippet for vdr.service
# file: roles/yavdr-xorg/templates/vdr-xorg.conf # {{ ansible_managed_file }} [Unit] After=x@vt7.service Wants=x@vt7.service #BindsTo=x@vt7.service
#!/bin/bash # {{ ansible_managed_file }} exec openbox-session
- xorg.conf
Section "Device" Identifier "nvidia" Driver "nvidia" Option "NoLogo" "true" Option "DynamicTwinView" "true" Option "NoFlip" "false" # Option "FlatPanelProperties" "Scaling = Native" # Option "ModeValidation" "NoVesaModes, NoXServerModes" # Option "ModeDebug" "true" # Option "HWCursor" "false" EndSection Section "Screen" Identifier "screen" Device "nvidia" EndSection Section "Extensions" Option "Composite" "false" EndSection
{{ ansible_managed_file | comment }} Section "ServerLayout" Identifier "Layout0" Screen 0 "Screen0" {% if xorg.secondary is defined %} Screen 1 "Screen1" RightOf "Screen0" {% endif %} #InputDevice "Keyboard0" "CoreKeyboard" #InputDevice "Mouse0" "CorePointer" EndSection Section "InputClass" Identifier "exclude eventlircd devices" MatchTag "eventlircd" Option "Ignore" "True" EndSection Section "Monitor" Identifier "Monitor0" VendorName "{{ xorg.primary.vendor }}" ModelName "{{ xorg.primary.model }}" Option "DPMS" Option "ExactModeTimingsDVI" "True" EndSection Section "Device" Identifier "Device0" Driver "nvidia" VendorName "NVIDIA Corporation" Option "NoLogo" "true" {% if xorg.primary.bus_id is defined %} BoardName "{{ xorg.primary.gpu_name }}" BusID "{{ xorg.primary.bus_id }}" {% else %} BoardName "Unknown" {% endif %} Screen 0 EndSection Section "Screen" Identifier "Screen0" Device "Device0" Monitor "Monitor0" DefaultDepth 24 Option "nvidiaXineramaInfoOrder" "{{ xorg.primary.connector }}" Option "ConnectedMonitor" "{{ xorg.primary.connector }}" Option "UseDisplayDevice" "{{ xorg.primary.connector }}" Option "CustomEDID" "{{ xorg.primary.connector }}:/etc/X11/edid.{{ xorg.primary.connector }}.bin" Option "metamodes" "{{ xorg.primary.connector }}: {{ xorg.primary.mode }} +0+0" Option "SLI" "Off" Option "MultiGPU" "Off" Option "BaseMosaic" "off" SubSection "Display" Depth 24 EndSubSection EndSection {% if xorg.secondary is defined %} Section "Device" Identifier "Device1" Driver "nvidia" VendorName "NVIDIA Corporation" Option "NoLogo" "true" {% if xorg.secondary.bus_id is defined %} BoardName "{{ xorg.primary.gpu_name }}" BusID "{{ xorg.primary.bus_id }}" {% else %} BoardName "Unknown" {% endif %} Screen 1 EndSection Section "Monitor" Identifier "Monitor1" VendorName "{{ xorg.secondary.vendor }}" ModelName "{{ xorg.secondary.model }}" EndSection Section "Screen" Identifier "Screen1" Device "Device1" Monitor "Monitor1" DefaultDepth 24 Option "nvidiaXineramaInfoOrder" "{{ xorg.secondary.connector }}" Option "ConnectedMonitor" "{{ xorg.secondary.connector }}" Option "UseDisplayDevice" "{{ xorg.secondary.connector }}" Option "CustomEDID" "{{ xorg.secondary.connector }}:/etc/X11/edid.{{ xorg.secondary.connector }}.bin" Option "metamodes" "{{ xorg.secondary.connector }}: {{ xorg.secondary.mode }} +0+0" Option "SLI" "Off" Option "MultiGPU" "Off" Option "BaseMosaic" "off" SubSection "Display" Depth 24 EndSubSection EndSection {% endif %}
{{ ansible_managed_file | comment }} Section "ServerLayout" Identifier "Layout0" Screen 0 "Screen0" {% if xorg.best_tv_mode.secondary is defined %} Screen 1 "Screen1" RightOf "Screen0" {% endif %} InputDevice "Keyboard0" "CoreKeyboard" InputDevice "Mouse0" "CorePointer" EndSection Section "InputDevice" # generated from default Identifier "Mouse0" Driver "mouse" Option "Protocol" "auto" Option "Device" "/dev/psaux" Option "Emulate3Buttons" "no" Option "ZAxisMapping" "4 5" EndSection # ignore devices with eventlircd tag # ENV{ID_INPUT.tags}+="eventlircd" # must be set by an udev rule Section "InputClass" Identifier "ignore eventlircd devices" MatchTag "eventlircd" Option "Ignore" "True" EndSection Section "InputDevice" # generated from default Identifier "Keyboard0" Driver "kbd" EndSection Section "Monitor" Identifier "Monitor0" VendorName "Unknown" ModelName "Unknown" {# TODO: VGA2SCART support (if needed) {% if system.x11.display.0.default == "VGA2Scart_4_3" or system.x11.display.0.default == "VGA2Scart_16_9" %} HorizSync 14-17 VertRefresh 49-61 {% if system.x11.display.0.default == "VGA2Scart_4_3" %} Modeline "VGA2Scart_4_3" 13.875 720 744 808 888 576 580 585 625 -HSync -Vsync interlace {% elif system.x11.display.0.default == "VGA2Scart_16_9" %} Modeline "VGA2Scart_16_9" 19 1024 1032 1120 1216 576 581 586 625 -Hsync -Vsync interlace {% endif %} {% endif %} #} Option "DPMS" Option "ExactModeTimingsDVI" "True" EndSection {% if xrandr.best_tv_mode.secondary is defined %} Section "Monitor" Identifier "Monitor1" VendorName "Unknown" ModelName "Unknown" {# {% if system.x11.display.1.default in ("VGA2Scart_4_3", "VGA2Scart_16_9") %} HorizSync 14-17 VertRefresh 49-61 {% if system.x11.display.1.default == "VGA2Scart_4_3" %} Modeline "VGA2Scart_4_3" 13.875 720 744 808 888 576 580 585 625 -HSync -Vsync interlace {% elif system.x11.display.1.default == "VGA2Scart_16_9" %} Modeline "VGA2Scart_16_9" 19 1024 1032 1120 1216 576 581 586 625 -Hsync -Vsync interlace {% endif %} Option "DPMS" Option "ExactModeTimingsDVI" "True" {% endif %} #} EndSection {% endif %} Section "Device" Identifier "Device0" {% if system.hardware.nvidia.detected %} Driver "nvidia" VendorName "NVIDIA Corporation" {% endif %} Screen 0 Option "DPI" "100x100" {% if system.hardware.nvidia.busid is defined and system.hardware.busid %} BusID "PCI: {{ system.hardware.nvidia.busid }}" {% endif %} Option "NoLogo" "True" Option "UseEvents" "True" Option "TripleBuffer" "False" Option "AddARGBGLXVisuals" "True" Option "TwinView" "0" Option "DynamicTwinView" "0" Option "OnDemandVBlankinterrupts" "on" Option "FlatPanelProperties" "Scaling = Native" EndSection {% if xrandr.best_tv_mode.secondary is defined %} Section "Device" Identifier "Device1" {% if system.hardware.nvidia.detected %} Driver "nvidia" VendorName "NVIDIA Corporation" {% endif %} Screen 1 {% if system.hardware.nvidia.busid is defined and system.hardware.nvidia.busid %} BusID "PCI: {{ system.hardware.nvidia.busid }}" {% endif %} Option "NoLogo" "True" Option "UseEvents" "True" Option "TripleBuffer" "False" Option "AddARGBGLXVisuals" "True" Option "TwinView" "0" Option "DynamicTwinView" "0" EndSection {% endif %} Section "Screen" Identifier "Screen0" Device "Device0" Monitor "Monitor0" DefaultDepth 24 SubSection "Display" Depth 24 {% if xrandr.best_tv_mode.primary is defined %} Modes "{{ xrandr.best_tv_mode.primary.mode }}"{#{% for mode in xrandr %}{% if mode != system.x11.display.0.default %} "{{ mode }}"{% endif %}{% endfor %}#} nvidia-auto-select {% elif system.hardware.nvidia.detected == 1 %} Modes "nvidia-auto-select" {% endif %} EndSubSection {% if system.x11.display.0.default or system.x11.default %} {% if system.x11.display.0.device is definded and system.x11.display.0.device %} Option "ConnectedMonitor" {{ system.x11.display.0.device }} {% else %} Option "ConnectedMonitor" {{ system.x11.default }} {% endif %} # Option "ConnectedMonitor" "<?cs if:(?system.x11.display.0.device) ?><?cs call:fix_display_name(system.x11.display.0.device) ?><?cs else ?><?cs var:system.x11.default ?><?cs /if ?><?cs if:(?system.x11.dualhead.enabled && system.x11.dualhead.enabled == 1) ?>, <?cs call:fix_display_name(system.x11.display.1.device) ?><?cs /if ?>" #Option "ConnectedMonitor" "<?cs if:(?system.x11.display.0.device) ?> <?cs call:fix_display_name(system.x11.display.0.device) ?> <?cs else ?> <?cs var:system.x11.default ?> <?cs /if ?> <?cs if:(?system.x11.dualhead.enabled && system.x11.dualhead.enabled == 1) ?>, <?cs call:fix_display_name(system.x11.display.1.device) ?><?cs /if ?>" # Option "UseDisplayDevice" "<?cs if:(?system.x11.display.0.device) ?><?cs call:fix_display_name(system.x11.display.0.device) ?><?cs else ?><?cs var:system.x11.default ?><?cs /if ?>" # <?cs /if ?> # <?cs if:(?system.hardware.nvidia.0.edid && system.hardware.nvidia.0.edid == "1") ?> # Option "CustomEDID" "<?cs call:fix_display_name(system.x11.display.0.device) ?>:/etc/X11/edid.0.yavdr" # <?cs /if ?> # <?cs if:(system.hardware.nvidia.detected == 1 && ?system.x11.display.0.device) ?> # Option "MetaModes" "<?cs call:fix_display_name(system.x11.display.0.device) ?>: <?cs var:system.x11.display.0.default ?> { ViewPortIn=<?cs var:system.x11.display.0.viewport.in.x ?>x<?cs var:system.x11.display.0.viewport.in.y ?>, ViewPortOut=<?cs var:system.x11.display.0.viewport.out.x ?>x<?cs var:system.x11.display.0.viewport.out.y ?>+<?cs var:system.x11.display.0.viewport.out.plusx ?>+<?cs var:system.x11.display.0.viewport.out.plusy ?> }" # <?cs each:mode = system.x11.display.0.mode ?><?cs if:(mode != system.x11.display.0.default) ?> # Option "MetaModes" "<?cs call:fix_display_name(system.x11.display.0.device) ?>: <?cs var:mode ?> { ViewPortIn=<?cs var:system.x11.display.0.viewport.in.x ?>x<?cs var:system.x11.display.0.viewport.in.y ?>, ViewPortOut=<?cs var:system.x11.display.0.viewport.out.x ?>x<?cs var:system.x11.display.0.viewport.out.y ?>+<?cs var:system.x11.display.0.viewport.out.plusx ?>+<?cs var:system.x11.display.0.viewport.out.plusy ?> }"<?cs /if ?><?cs /each ?> {% endif %} EndSection {% if system.x11.dualhead.enabled == "1" %} Section "Screen" Identifier "Screen1" Device "Device1" Monitor "Monitor1" DefaultDepth 24 SubSection "Display" Depth 24 {% if system.x11.display.0.default is defined and system.x11.display.0.default %} Modes "{{ system.x11.display.1.default }}"{% for mode in system.x11.display.1.mode %}{% if mode != system.x11.display.1.default %} "{{ mode }}"{% endif %}{% endfor %} {% elif system.hardware.nvidia.detected == "1" %} Modes "nvidia-auto-select" {% endif %} EndSubSection # <?cs if:(?system.x11.display.1.default && system.x11.display.1.default != "" && system.x11.display.1.default != "disabled") ?> # Option "UseDisplayDevice" "<?cs call:fix_display_name(system.x11.display.1.device) ?>" # <?cs /if ?> # <?cs if:(?system.hardware.nvidia.1.edid && system.hardware.nvidia.1.edid == "1") ?> # Option "CustomEDID" "<?cs call:fix_display_name(system.x11.display.1.device) ?>:/etc/X11/edid.1.yavdr" # <?cs /if ?> # <?cs if:(system.hardware.nvidia.detected == 1 && ?system.x11.display.1.device) ?> # Option "MetaModes" "<?cs call:fix_display_name(system.x11.display.1.device) ?>: <?cs var:system.x11.display.1.default ?> { ViewPortIn=<?cs var:system.x11.display.1.viewport.in.x ?>x<?cs var:system.x11.display.1.viewport.in.y ?>, ViewPortOut=<?cs var:system.x11.display.1.viewport.out.x ?>x<?cs var:system.x11.display.1.viewport.out.y ?>+<?cs var:system.x11.display.1.viewport.out.plusx ?>+<?cs var:system.x11.display.1.viewport.out.plusy ?> }" # <?cs each:mode = system.x11.display.1.mode ?><?cs if:(mode != system.x11.display.1.default) ?> # Option "MetaModes" "<?cs call:fix_display_name(system.x11.display.1.device) ?>: <?cs var:mode ?> { ViewPortIn=<?cs var:system.x11.display.1.viewport.in.x ?>x<?cs var:system.x11.display.1.viewport.in.y ?>, ViewPortOut=<?cs var:system.x11.display.1.viewport.out.x ?>x<?cs var:system.x11.display.1.viewport.out.y ?>+<?cs var:system.x11.display.1.viewport.out.plusx ?>+<?cs var:system.x11.display.1.viewport.out.plusy ?> }"<?cs /if ?><?cs /each ?> # <?cs /if ?> EndSection {% endif %}
- x-verbose@.service
- vdr
[Service] EnvironmentFile=-/var/lib/vdr/.session-env
- Systemd User Session
- yavdr-desktop.target
[Unit] Description=yaVDR Desktop Requires=default.target After=default.target pulseaudio.service Wants=dbus.service pulseaudio.service AllowIsolate=yes
- detect-second-display
[Unit] Description=Detect second DISPLAY using xrandr [Service] Type=oneshot ExecStart=/bin/bash -c 'export DISPLAY=$DISPLAY.1; xrandr -q | grep "connected" && echo "DISPLAY=$DISPLAY" > ~/.second_display || rm -f ~/.second_display' [Install] WantedBy=yavdr-desktop.target
- openbox-second.service
[Unit] Description=Start openbox on the second DISPLAY if it exists After=detect-second-display.service Wants=detect-second-display.service Before=yavdr-frontend.service ConditionFileNotEmpty=%h/.second_display [Service] PassEnvironment=XDG_RUNTIME_DIR DBUS_SESSION_BUS_ADDRESS EnvironmentFile=%h/.second_display ExecStart=/usr/bin/openbox --config-file %h/.config/openbox/rc.xml [Install] WantedBy=yavdr-desktop.target
- osd2web.service
[Unit] Description=Start a kiosk browser on the second DISPLAY if it exists After=detect-second-display.service openbox-second.service Wants=detect-second-display.service openbox-second.service ConditionFileNotEmpty=%h/.second_display [Service] EnvironmentFile=%h/.second_display PassEnvironment=XDG_RUNTIME_DIR DBUS_SESSION_BUS_ADDRESS ExecStart=/usr/bin/on_vdr -o -c 'kiosk-browser "http://localhost:4444/skins/horchiTft/index.html?theme=blue&onlyView=1"' [Install] WantedBy=yavdr-desktop.target
- tmux.service
[Unit] Description=Start tmux in detached session [Service] EnvironmentFile=-%h/.session-env Type=forking ExecStart=/usr/bin/tmux new-session -s use-session -d ExecStop=/usr/bin/tmux kill-session -t %u Restart=always [Install] WantedBy=default.target
- yavdr-desktop.target
- openbox
- autostart
# forward environment variables to an environment file and the systemd user session env | grep "DISPLAY\|DBUS_SESSION_BUS_ADDRESS\|XDG_RUNTIME_DIR" > ~/.session-env systemctl --user import-environment DISPLAY XAUTHORITY XDG_RUNTIME_DIR DBUS_SESSION_BUS_ADDRESS enabled_services=("tmux.service" "detect-second-display.service" "openbox-second.service" "osd2web.service") disabled_services=() # enable configured services for the user session for service in "${enabled_services[@]}"; do systemctl --user enable "$service" done # disable unwanted services for the user session for service in "${disabled_services[@]}"; do systemctl --user disable "$service" done if which dbus-update-activation-environment >/dev/null 2>&1; then dbus-update-activation-environment DISPLAY XAUTHORITY XDG_RUNTIME_DIR fi # start systemd units for the yavdr user session systemctl --user isolate yavdr-desktop.target
- rc.xml
<?xml version="1.0" encoding="UTF-8"?> <openbox_config xmlns="http://openbox.org/3.4/rc" xmlns:xi="http://www.w3.org/2001/XInclude"> <!-- Do not edit this file, it will be overwritten on install. Copy the file to $HOME/.config/openbox/ instead. --> <resistance> <strength>10</strength> <screen_edge_strength>20</screen_edge_strength> </resistance> <focus> <focusNew>yes</focusNew> <!-- always try to focus new windows when they appear. other rules do apply --> <followMouse>no</followMouse> <!-- move focus to a window when you move the mouse into it --> <focusLast>yes</focusLast> <!-- focus the last used window when changing desktops, instead of the one under the mouse pointer. when followMouse is enabled --> <underMouse>no</underMouse> <!-- move focus under the mouse, even when the mouse is not moving --> <focusDelay>200</focusDelay> <!-- when followMouse is enabled, the mouse must be inside the window for this many milliseconds (1000 = 1 sec) before moving focus to it --> <raiseOnFocus>no</raiseOnFocus> <!-- when followMouse is enabled, and a window is given focus by moving the mouse into it, also raise the window --> </focus> <placement> <policy>Smart</policy> <!-- 'Smart' or 'UnderMouse' --> <center>yes</center> <!-- whether to place windows in the center of the free area found or the top left corner --> <monitor>Active</monitor> <!-- with Smart placement on a multi-monitor system, try to place new windows on: 'Any' - any monitor, 'Mouse' - where the mouse is, 'Active' - where the active window is, 'Primary' - only on the primary monitor --> <primaryMonitor>Active</primaryMonitor> <!-- The monitor where Openbox should place popup dialogs such as the focus cycling popup, or the desktop switch popup. It can be an index from 1, specifying a particular monitor. Or it can be one of the following: 'Mouse' - where the mouse is, or 'Active' - where the active window is --> </placement> <theme> <name>Onyx</name> <titleLayout>NLIMC</titleLayout> <!-- available characters are NDSLIMC, each can occur at most once. N: window icon L: window label (AKA title). I: iconify M: maximize C: close S: shade (roll up/down) D: omnipresent (on all desktops). --> <keepBorder>yes</keepBorder> <animateIconify>yes</animateIconify> <font place="ActiveWindow"> <name>sans</name> <size>8</size> <!-- font size in points --> <weight>bold</weight> <!-- 'bold' or 'normal' --> <slant>normal</slant> <!-- 'italic' or 'normal' --> </font> <font place="InactiveWindow"> <name>sans</name> <size>8</size> <!-- font size in points --> <weight>bold</weight> <!-- 'bold' or 'normal' --> <slant>normal</slant> <!-- 'italic' or 'normal' --> </font> <font place="MenuHeader"> <name>sans</name> <size>9</size> <!-- font size in points --> <weight>normal</weight> <!-- 'bold' or 'normal' --> <slant>normal</slant> <!-- 'italic' or 'normal' --> </font> <font place="MenuItem"> <name>sans</name> <size>9</size> <!-- font size in points --> <weight>normal</weight> <!-- 'bold' or 'normal' --> <slant>normal</slant> <!-- 'italic' or 'normal' --> </font> <font place="ActiveOnScreenDisplay"> <name>sans</name> <size>9</size> <!-- font size in points --> <weight>bold</weight> <!-- 'bold' or 'normal' --> <slant>normal</slant> <!-- 'italic' or 'normal' --> </font> <font place="InactiveOnScreenDisplay"> <name>sans</name> <size>9</size> <!-- font size in points --> <weight>bold</weight> <!-- 'bold' or 'normal' --> <slant>normal</slant> <!-- 'italic' or 'normal' --> </font> </theme> <desktops> <!-- this stuff is only used at startup, pagers allow you to change them during a session these are default values to use when other ones are not already set by other applications, or saved in your session use obconf if you want to change these without having to log out and back in --> <number>2</number> <firstdesk>1</firstdesk> <names> <!-- set names up here if you want to, like this: <name>desktop 1</name> <name>desktop 2</name> --> </names> <popupTime>875</popupTime> <!-- The number of milliseconds to show the popup for when switching desktops. Set this to 0 to disable the popup. --> </desktops> <resize> <drawContents>yes</drawContents> <popupShow>Nonpixel</popupShow> <!-- 'Always', 'Never', or 'Nonpixel' (xterms and such) --> <popupPosition>Center</popupPosition> <!-- 'Center', 'Top', or 'Fixed' --> <popupFixedPosition> <!-- these are used if popupPosition is set to 'Fixed' --> <x>10</x> <!-- positive number for distance from left edge, negative number for distance from right edge, or 'Center' --> <y>10</y> <!-- positive number for distance from top edge, negative number for distance from bottom edge, or 'Center' --> </popupFixedPosition> </resize> <!-- You can reserve a portion of your screen where windows will not cover when they are maximized, or when they are initially placed. Many programs reserve space automatically, but you can use this in other cases. --> <margins> <top>0</top> <bottom>0</bottom> <left>0</left> <right>0</right> </margins> <dock> <position>TopLeft</position> <!-- (Top|Bottom)(Left|Right|)|Top|Bottom|Left|Right|Floating --> <floatingX>0</floatingX> <floatingY>0</floatingY> <noStrut>no</noStrut> <stacking>Above</stacking> <!-- 'Above', 'Normal', or 'Below' --> <direction>Vertical</direction> <!-- 'Vertical' or 'Horizontal' --> <autoHide>no</autoHide> <hideDelay>300</hideDelay> <!-- in milliseconds (1000 = 1 second) --> <showDelay>300</showDelay> <!-- in milliseconds (1000 = 1 second) --> <moveButton>Middle</moveButton> <!-- 'Left', 'Middle', 'Right' --> </dock> <keyboard> <chainQuitKey>C-g</chainQuitKey> <!-- Keybindings for desktop switching --> <keybind key="C-A-Left"> <action name="GoToDesktop"> <to>left</to> <wrap>no</wrap> </action> </keybind> <keybind key="C-A-Right"> <action name="GoToDesktop"> <to>right</to> <wrap>no</wrap> </action> </keybind> <keybind key="C-A-Up"> <action name="GoToDesktop"> <to>up</to> <wrap>no</wrap> </action> </keybind> <keybind key="C-A-Down"> <action name="GoToDesktop"> <to>down</to> <wrap>no</wrap> </action> </keybind> <keybind key="S-A-Left"> <action name="SendToDesktop"> <to>left</to> <wrap>no</wrap> </action> </keybind> <keybind key="S-A-Right"> <action name="SendToDesktop"> <to>right</to> <wrap>no</wrap> </action> </keybind> <keybind key="S-A-Up"> <action name="SendToDesktop"> <to>up</to> <wrap>no</wrap> </action> </keybind> <keybind key="S-A-Down"> <action name="SendToDesktop"> <to>down</to> <wrap>no</wrap> </action> </keybind> <keybind key="W-F1"> <action name="GoToDesktop"> <to>1</to> </action> </keybind> <keybind key="W-F2"> <action name="GoToDesktop"> <to>2</to> </action> </keybind> <keybind key="W-F3"> <action name="GoToDesktop"> <to>3</to> </action> </keybind> <keybind key="W-F4"> <action name="GoToDesktop"> <to>4</to> </action> </keybind> <keybind key="W-d"> <action name="ToggleShowDesktop"/> </keybind> <!-- Keybindings for windows --> <keybind key="A-F4"> <action name="Close"/> </keybind> <keybind key="A-Escape"> <action name="Lower"/> <action name="FocusToBottom"/> <action name="Unfocus"/> </keybind> <keybind key="A-space"> <action name="ShowMenu"> <menu>client-menu</menu> </action> </keybind> <!-- Take a screenshot of the current window with scrot when Alt+Print are pressed --> <keybind key="A-Print"> <action name="Execute"> <command>scrot -s</command> </action> </keybind> <!-- Keybindings for window switching --> <keybind key="A-Tab"> <action name="NextWindow"> <finalactions> <action name="Focus"/> <action name="Raise"/> <action name="Unshade"/> </finalactions> </action> </keybind> <keybind key="A-S-Tab"> <action name="PreviousWindow"> <finalactions> <action name="Focus"/> <action name="Raise"/> <action name="Unshade"/> </finalactions> </action> </keybind> <keybind key="C-A-Tab"> <action name="NextWindow"> <panels>yes</panels> <desktop>yes</desktop> <finalactions> <action name="Focus"/> <action name="Raise"/> <action name="Unshade"/> </finalactions> </action> </keybind> <!-- Keybindings for window switching with the arrow keys --> <keybind key="W-S-Right"> <action name="DirectionalCycleWindows"> <direction>right</direction> </action> </keybind> <keybind key="W-S-Left"> <action name="DirectionalCycleWindows"> <direction>left</direction> </action> </keybind> <keybind key="W-S-Up"> <action name="DirectionalCycleWindows"> <direction>up</direction> </action> </keybind> <keybind key="W-S-Down"> <action name="DirectionalCycleWindows"> <direction>down</direction> </action> </keybind> <!-- Keybindings for running applications --> <keybind key="W-e"> <action name="Execute"> <startupnotify> <enabled>true</enabled> <name>Konqueror</name> </startupnotify> <command>kfmclient openProfile filemanagement</command> </action> </keybind> <!-- Launch scrot when Print is pressed --> <keybind key="Print"> <action name="Execute"> <command>scrot</command> </action> </keybind> </keyboard> <mouse> <dragThreshold>1</dragThreshold> <!-- number of pixels the mouse must move before a drag begins --> <doubleClickTime>500</doubleClickTime> <!-- in milliseconds (1000 = 1 second) --> <screenEdgeWarpTime>400</screenEdgeWarpTime> <!-- Time before changing desktops when the pointer touches the edge of the screen while moving a window, in milliseconds (1000 = 1 second). Set this to 0 to disable warping --> <screenEdgeWarpMouse>false</screenEdgeWarpMouse> <!-- Set this to TRUE to move the mouse pointer across the desktop when switching due to hitting the edge of the screen --> <context name="Frame"> <mousebind button="A-Left" action="Press"> <action name="Focus"/> <action name="Raise"/> </mousebind> <mousebind button="A-Left" action="Click"> <action name="Unshade"/> </mousebind> <mousebind button="A-Left" action="Drag"> <action name="Move"/> </mousebind> <mousebind button="A-Right" action="Press"> <action name="Focus"/> <action name="Raise"/> <action name="Unshade"/> </mousebind> <mousebind button="A-Right" action="Drag"> <action name="Resize"/> </mousebind> <mousebind button="A-Middle" action="Press"> <action name="Lower"/> <action name="FocusToBottom"/> <action name="Unfocus"/> </mousebind> <mousebind button="A-Up" action="Click"> <action name="GoToDesktop"> <to>previous</to> </action> </mousebind> <mousebind button="A-Down" action="Click"> <action name="GoToDesktop"> <to>next</to> </action> </mousebind> <mousebind button="C-A-Up" action="Click"> <action name="GoToDesktop"> <to>previous</to> </action> </mousebind> <mousebind button="C-A-Down" action="Click"> <action name="GoToDesktop"> <to>next</to> </action> </mousebind> <mousebind button="A-S-Up" action="Click"> <action name="SendToDesktop"> <to>previous</to> </action> </mousebind> <mousebind button="A-S-Down" action="Click"> <action name="SendToDesktop"> <to>next</to> </action> </mousebind> </context> <context name="Titlebar"> <mousebind button="Left" action="Drag"> <action name="Move"/> </mousebind> <mousebind button="Left" action="DoubleClick"> <action name="ToggleMaximize"/> </mousebind> <mousebind button="Up" action="Click"> <action name="if"> <shaded>no</shaded> <then> <action name="Shade"/> <action name="FocusToBottom"/> <action name="Unfocus"/> <action name="Lower"/> </then> </action> </mousebind> <mousebind button="Down" action="Click"> <action name="if"> <shaded>yes</shaded> <then> <action name="Unshade"/> <action name="Raise"/> </then> </action> </mousebind> </context> <context name="Titlebar Top Right Bottom Left TLCorner TRCorner BRCorner BLCorner"> <mousebind button="Left" action="Press"> <action name="Focus"/> <action name="Raise"/> <action name="Unshade"/> </mousebind> <mousebind button="Middle" action="Press"> <action name="Lower"/> <action name="FocusToBottom"/> <action name="Unfocus"/> </mousebind> <mousebind button="Right" action="Press"> <action name="Focus"/> <action name="Raise"/> <action name="ShowMenu"> <menu>client-menu</menu> </action> </mousebind> </context> <context name="Top"> <mousebind button="Left" action="Drag"> <action name="Resize"> <edge>top</edge> </action> </mousebind> </context> <context name="Left"> <mousebind button="Left" action="Drag"> <action name="Resize"> <edge>left</edge> </action> </mousebind> </context> <context name="Right"> <mousebind button="Left" action="Drag"> <action name="Resize"> <edge>right</edge> </action> </mousebind> </context> <context name="Bottom"> <mousebind button="Left" action="Drag"> <action name="Resize"> <edge>bottom</edge> </action> </mousebind> <mousebind button="Right" action="Press"> <action name="Focus"/> <action name="Raise"/> <action name="ShowMenu"> <menu>client-menu</menu> </action> </mousebind> </context> <context name="TRCorner BRCorner TLCorner BLCorner"> <mousebind button="Left" action="Press"> <action name="Focus"/> <action name="Raise"/> <action name="Unshade"/> </mousebind> <mousebind button="Left" action="Drag"> <action name="Resize"/> </mousebind> </context> <context name="Client"> <mousebind button="Left" action="Press"> <action name="Focus"/> <action name="Raise"/> </mousebind> <mousebind button="Middle" action="Press"> <action name="Focus"/> <action name="Raise"/> </mousebind> <mousebind button="Right" action="Press"> <action name="Focus"/> <action name="Raise"/> </mousebind> </context> <context name="Icon"> <mousebind button="Left" action="Press"> <action name="Focus"/> <action name="Raise"/> <action name="Unshade"/> <action name="ShowMenu"> <menu>client-menu</menu> </action> </mousebind> <mousebind button="Right" action="Press"> <action name="Focus"/> <action name="Raise"/> <action name="ShowMenu"> <menu>client-menu</menu> </action> </mousebind> </context> <context name="AllDesktops"> <mousebind button="Left" action="Press"> <action name="Focus"/> <action name="Raise"/> <action name="Unshade"/> </mousebind> <mousebind button="Left" action="Click"> <action name="ToggleOmnipresent"/> </mousebind> </context> <context name="Shade"> <mousebind button="Left" action="Press"> <action name="Focus"/> <action name="Raise"/> </mousebind> <mousebind button="Left" action="Click"> <action name="ToggleShade"/> </mousebind> </context> <context name="Iconify"> <mousebind button="Left" action="Press"> <action name="Focus"/> <action name="Raise"/> </mousebind> <mousebind button="Left" action="Click"> <action name="Iconify"/> </mousebind> </context> <context name="Maximize"> <mousebind button="Left" action="Press"> <action name="Focus"/> <action name="Raise"/> <action name="Unshade"/> </mousebind> <mousebind button="Middle" action="Press"> <action name="Focus"/> <action name="Raise"/> <action name="Unshade"/> </mousebind> <mousebind button="Right" action="Press"> <action name="Focus"/> <action name="Raise"/> <action name="Unshade"/> </mousebind> <mousebind button="Left" action="Click"> <action name="ToggleMaximize"/> </mousebind> <mousebind button="Middle" action="Click"> <action name="ToggleMaximize"> <direction>vertical</direction> </action> </mousebind> <mousebind button="Right" action="Click"> <action name="ToggleMaximize"> <direction>horizontal</direction> </action> </mousebind> </context> <context name="Close"> <mousebind button="Left" action="Press"> <action name="Focus"/> <action name="Raise"/> <action name="Unshade"/> </mousebind> <mousebind button="Left" action="Click"> <action name="Close"/> </mousebind> </context> <context name="Desktop"> <mousebind button="Up" action="Click"> <action name="GoToDesktop"> <to>previous</to> </action> </mousebind> <mousebind button="Down" action="Click"> <action name="GoToDesktop"> <to>next</to> </action> </mousebind> <mousebind button="A-Up" action="Click"> <action name="GoToDesktop"> <to>previous</to> </action> </mousebind> <mousebind button="A-Down" action="Click"> <action name="GoToDesktop"> <to>next</to> </action> </mousebind> <mousebind button="C-A-Up" action="Click"> <action name="GoToDesktop"> <to>previous</to> </action> </mousebind> <mousebind button="C-A-Down" action="Click"> <action name="GoToDesktop"> <to>next</to> </action> </mousebind> <mousebind button="Left" action="Press"> <action name="Focus"/> <action name="Raise"/> </mousebind> <mousebind button="Right" action="Press"> <action name="Focus"/> <action name="Raise"/> </mousebind> </context> <context name="Root"> <!-- Menus --> <mousebind button="Middle" action="Press"> <action name="ShowMenu"> <menu>client-list-combined-menu</menu> </action> </mousebind> <mousebind button="Right" action="Press"> <action name="ShowMenu"> <menu>root-menu</menu> </action> </mousebind> </context> <context name="MoveResize"> <mousebind button="Up" action="Click"> <action name="GoToDesktop"> <to>previous</to> </action> </mousebind> <mousebind button="Down" action="Click"> <action name="GoToDesktop"> <to>next</to> </action> </mousebind> <mousebind button="A-Up" action="Click"> <action name="GoToDesktop"> <to>previous</to> </action> </mousebind> <mousebind button="A-Down" action="Click"> <action name="GoToDesktop"> <to>next</to> </action> </mousebind> </context> </mouse> <menu> <!-- You can specify more than one menu file in here and they are all loaded, just don't make menu ids clash or, well, it'll be kind of pointless --> <!-- default menu file (or custom one in $HOME/.config/openbox/) --> <!-- system menu files on Debian systems --> <file>/var/lib/openbox/debian-menu.xml</file> <file>menu.xml</file> <hideDelay>200</hideDelay> <!-- if a press-release lasts longer than this setting (in milliseconds), the menu is hidden again --> <middle>no</middle> <!-- center submenus vertically about the parent entry --> <submenuShowDelay>100</submenuShowDelay> <!-- time to delay before showing a submenu after hovering over the parent entry. if this is a negative value, then the delay is infinite and the submenu will not be shown until it is clicked on --> <submenuHideDelay>400</submenuHideDelay> <!-- time to delay before hiding a submenu when selecting another entry in parent menu if this is a negative value, then the delay is infinite and the submenu will not be hidden until a different submenu is opened --> <showIcons>yes</showIcons> <!-- controls if icons appear in the client-list-(combined-)menu --> <manageDesktops>yes</manageDesktops> <!-- show the manage desktops section in the client-list-(combined-)menu --> </menu> <!-- # this is an example with comments through out. use these to make your # own rules, but without the comments of course. # you may use one or more of the name/class/role/title/type rules to specify # windows to match <application name="the window's _OB_APP_NAME property (see obxprop)" class="the window's _OB_APP_CLASS property (see obxprop)" groupname="the window's _OB_APP_GROUP_NAME property (see obxprop)" groupclass="the window's _OB_APP_GROUP_CLASS property (see obxprop)" role="the window's _OB_APP_ROLE property (see obxprop)" title="the window's _OB_APP_TITLE property (see obxprop)" type="the window's _OB_APP_TYPE property (see obxprob).. (if unspecified, then it is 'dialog' for child windows)"> # you may set only one of name/class/role/title/type, or you may use more # than one together to restrict your matches. # the name, class, role, and title use simple wildcard matching such as those # used by a shell. you can use * to match any characters and ? to match # any single character. # the type is one of: normal, dialog, splash, utility, menu, toolbar, dock, # or desktop # when multiple rules match a window, they will all be applied, in the # order that they appear in this list # each rule element can be left out or set to 'default' to specify to not # change that attribute of the window <decor>yes</decor> # enable or disable window decorations <shade>no</shade> # make the window shaded when it appears, or not <position force="no"> # the position is only used if both an x and y coordinate are provided # (and not set to 'default') # when force is "yes", then the window will be placed here even if it # says you want it placed elsewhere. this is to override buggy # applications who refuse to behave <x>center</x> # a number like 50, or 'center' to center on screen. use a negative number # to start from the right (or bottom for <y>), ie -50 is 50 pixels from # the right edge (or bottom). use 'default' to specify using value # provided by the application, or chosen by openbox, instead. <y>200</y> <monitor>1</monitor> # specifies the monitor in a xinerama setup. # 1 is the first head, or 'mouse' for wherever the mouse is </position> <size> # the size to make the window. <width>20</width> # a number like 20, or 'default' to use the size given by the application. # you can use fractions such as 1/2 or percentages such as 75% in which # case the value is relative to the size of the monitor that the window # appears on. <height>30%</height> </size> <focus>yes</focus> # if the window should try be given focus when it appears. if this is set # to yes it doesn't guarantee the window will be given focus. some # restrictions may apply, but Openbox will try to <desktop>1</desktop> # 1 is the first desktop, 'all' for all desktops <layer>normal</layer> # 'above', 'normal', or 'below' <iconic>no</iconic> # make the window iconified when it appears, or not <skip_pager>no</skip_pager> # asks to not be shown in pagers <skip_taskbar>no</skip_taskbar> # asks to not be shown in taskbars. window cycling actions will also # skip past such windows <fullscreen>yes</fullscreen> # make the window in fullscreen mode when it appears <maximized>true</maximized> # 'Horizontal', 'Vertical' or boolean (yes/no) </application> # end of the example --> <applications> <application title="softhddevice"> <decor>no</decor> <maximized>true</maximized> <!--<skip_pager>yes</skip_pager>--> <skip_taskbar>no</skip_taskbar> </application> <application title="browser"> <decor>no</decor> <maximized>true</maximized> <!--<skip_pager>yes</skip_pager>--> <skip_taskbar>yes</skip_taskbar> </application> <application title="osd2Web"> <decor>no</decor> <maximized>true</maximized> <!--<skip_pager>yes</skip_pager>--> <skip_taskbar>yes</skip_taskbar> </application> </applications> </openbox_config>
- autostart
8.10 samba-install
8.10.1 tasks
--- # file: roles/samba-install/tasks/main.yml - name: install samba server apt: name: '{{ item }}' state: present install_recommends: no with_items: - samba - samba-common - samba-common-bin - tdb-tools
8.11 samba-config
8.11.1 tasks
--- # file: roles/samba-config/tasks/main.yml # TODO: # - name: divert original smbd.conf - name: touch smb.conf.custom file: state: touch dest: '/etc/samba/smb.conf.custom' notify: [ 'Restart Samba' ] - name: expand template for smb.conf template: src: 'templates/smb.conf.j2' dest: '/etc/samba/smb.conf' #validate: 'testparm -s %s' notify: [ 'Restart Samba' ]
8.11.2 templates
- smb.conf
- global settings
{{ ansible_managed_file | comment }} #======================= Global Settings ======================= [global] ## Browsing/Identification ### # Change this to the workgroup/NT-domain name your Samba server will part of workgroup = {{ samba.workgroup }} # server string is the equivalent of the NT Description field server string = %h server (Samba, Ubuntu) # This will prevent nmbd to search for NetBIOS names through DNS. dns proxy = no #### Debugging/Accounting #### # This tells Samba to use a separate log file for each machine # that connects log file = /var/log/samba/log.%m # Cap the size of the individual log files (in KiB). max log size = 1000 # We want Samba to log a minimum amount of information to syslog. Everything # should go to /var/log/samba/log.{smbd,nmbd} instead. If you want to log # through syslog you should set the following parameter to something higher. syslog = 0 # Do something sensible when Samba crashes: mail the admin a backtrace panic action = /usr/share/samba/panic-action %d ####### Authentication ####### # "security = user" is always a good idea. This will require a Unix account # in this server for every user accessing the server. See # /usr/share/doc/samba-doc/htmldocs/Samba3-HOWTO/ServerType.html # in the samba-doc package for details. # security = user # You may wish to use password encryption. See the section on # 'encrypt passwords' in the smb.conf(5) manpage before enabling. encrypt passwords = true # If you are using encrypted passwords, Samba will need to know what # password database type you are using. passdb backend = tdbsam obey pam restrictions = yes # This boolean parameter controls whether Samba attempts to sync the Unix # password with the SMB password when the encrypted SMB password in the # passdb is changed. unix password sync = yes # For Unix password sync to work on a Debian GNU/Linux system, the following # parameters must be set (thanks to Ian Kahan <<kahan@informatik.tu-muenchen.de> for # sending the correct chat script for the passwd program in Debian Sarge). passwd program = /usr/bin/passwd %u passwd chat = *Enter\snew\s*\spassword:* %n\n *Retype\snew\s*\spassword:* %n\n *password\supdated\ssuccessfully* . # This boolean controls whether PAM will be used for password changes # when requested by an SMB client instead of the program listed in # 'passwd program'. The default is 'no'. pam password change = yes # This option controls how unsuccessful authentication attempts are mapped # to anonymous connections map to guest = bad user {% if samba.windows_compatible %} # disable unix extensions and enable following symlinks unix extensions = no follow symlinks= yes wide links= yes {% endif %}
- media directories
{% for name, path in media_dirs.iteritems() %} [{{ name }}] path = {{ path }} comment = {{ name }} on %h guest ok = yes writeable = yes browseable = yes create mode = 0664 directory mode = 0775 force user = {{ vdr.user }} force group = {{ vdr.group }} follow symlinks = yes wide links = yes {% endfor %}
- include custom samba exports
include = /etc/samba/smb.conf.custom
- global settings
8.12 STARTED autoinstall-drivers
It would be nice to be able to detect if it is suitable to install those drivers:
8.12.1 TODO sundtek for Sundtek devices (local or network connection)
Vendor-IDs:
- eb1a:5[1b2] (alte Generation)
- 2659:* (neuere Sticks)
8.12.2 TODO dddvb-dkms if only newer DD cards are detected
8.12.3 TODO media-build-experimental (up to kernel 4.8) for „old“ cards like TT S2-6400 FF
8.12.4 TODO newly merged DD drivers
8.13 autoinstall-ubuntu-drivers
The tool ubuntu-drivers is used to install the matching driver version for nvidia graphics cards, virtualbox guest additions and Intel and AMD microcode updates.
8.13.1 tasks
--- # file roles/autoinstall-ubuntu-drivers/tasks/main.yml - name: apt | install ubuntu-drivers-common apt: name: ubuntu-drivers-common state: present - name: ensure /etc/yavdr exists file: path: /etc/yavdr state: directory mode: 0755 - name: let ubuntu-drivers automatically install additional drivers command: ubuntu-drivers --package-list /etc/yavdr/autoinstalled autoinstall
8.14 autoinstall-satip
If a Sat>IP Server responds to a discovery request, the package vdr-plugin-satip is installed.
8.14.1 tasks
--- # file roles/autoinstall-satip/tasks/main.yml - name: "detect SAT>IP Server(s) on the network" action: satip_facts - debug: var: satip_detected verbosity: 1 - name: apt | install vdr-plugin-satip if a Sat>IP server has been detected apt: name: vdr-plugin-satip when: satip_detected notify: [ 'Restart VDR' ]
8.15 autoinstall-targavfd
8.15.1 tasks
--- # file roles/autoinstall-targavfd/tasks/main.yml - name: apt | install vdr-plugin-targavfd if connected apt: name: vdr-plugin-targavfd when: - '"19c2:6a11" in usb' notify: [ 'Restart VDR' ]
8.16 autoinstall-imonlcd
8.16.1 tasks
--- # file roles/autoinstall-imonlcd/tasks/main.yml - name: apt | install vdr-plugin-imonlcd if connected apt: name: vdr-plugin-imonlcd when: - '"15c2:0038" in usb' - '"15c2:ffdc" in usb' notify: [ 'Restart VDR' ]
8.17 autoinstall-libcecdaemon
8.17.1 tasks
--- # file roles/autoinstall-libcec-daemon/tasks/main.yml - name: apt | install libcec-daemon if connected apt: name: libcec-daemon when: - '"2548:1002" in usb'
8.18 autoinstall-pvr350
8.18.1 tasks
--- # file roles/autoinstall-pvr350/tasks/main.yml - name: apt | install vdr-plugin-pvr350 if connected apt: name: vdr-plugin-pvr350 when: - '"0070:4000" in pci' notify: [ 'Restart VDR' ]
8.19 TODO autoinstall-dvbhddevice
Problem: woher kommt der Treiber (AFAIK noch nicht im Kernel)? Die Firmware sollte in yavdr-firmware stecken
8.19.1 tasks
--- # file roles/autoinstall-dvbhddevice/tasks/main.yml - name: apt | install vdr-plugin-dvbhddevice if connected apt: name: vdr-plugin-dvbhddevice when: - '"13c2:300a" in pci' - '"13c2:300b" in pci' notify: [ 'Restart VDR' ]
8.20 autoinstall-dvbsddevice
8.20.1 tasks
--- # file roles/autoinstall-dvbsddevice/tasks/main.yml - name: apt | install vdr-plugin-dvbsddevice if module is loaded apt: name: vdr-plugin-dvbsddevice when: - '"dvb_ttpci" in modules' notify: [ 'Restart VDR' ]
8.21 kodi
8.21.1 tasks
- Install KODI
--- - name: apt | install kodi packages apt: name: '{{ item }}' state: present install_recommends: no with_items: - kodi - kodi-pvr-vdr-vnsi - kodi-eventclients-xbmc-send - name: create kodi.service for the user session template: src: 'templates/kodi.service.j2' dest: '{{ vdr.home }}/.config/systemd/user/kodi.service' mode: 0755 owner: '{{ vdr.user }}' group: '{{ vdr.group }}' - name: create kodi user directory file: dest: '{{ vdr.home }}/{{ item }}' state: directory owner: '{{ vdr.user }}' group: '{{ vdr.group }}' mode: "0775" with_items: - .kodi - .kodi/userdata - .kodi/userdata/keymaps # TODO: Add configuration files
8.21.2 templates
- kodi.service
[Unit] Description=Start kodi in user session [Service] Type=simple PassEnvironment=DISPLAY XDG_RUNTIME_DIR DBUS_SESSION_BUS_ADDRESS ExecStartPre=-/usr/bin/set-kodi-display ExecStart=/usr/bin/kodi ExecStop=/bin/bash -c "/usr/bin/kodi-send --action=QUIT; while /usr/bin/pgrep kodi; do sleep 1; done; sleep 1" TimeoutStopSec=10 SuccessExitStatus=0 127 Restart=on-failure
8.21.3 files
- Lircmap.xml
<lircmap> <remote device="linux-input-layer"> <altname>cx23885_remote</altname> <altname>devinput</altname> <up>KEY_UP</up> <down>KEY_DOWN</down> <menu>KEY_MENU</menu> <select>KEY_OK</select> <back>KEY_ESC</back> <left>KEY_LEFT</left> <right>KEY_RIGHT</right> <red>KEY_RED</red> <green>KEY_GREEN</green> <yellow>KEY_YELLOW</yellow> <blue>KEY_BLUE</blue> <zero>KEY_0</zero> <one>KEY_1</one> <two>KEY_2</two> <three>KEY_3</three> <four>KEY_4</four> <five>KEY_5</five> <six>KEY_6</six> <seven>KEY_7</seven> <eight>KEY_8</eight> <nine>KEY_9</nine> <info>KEY_INFO</info> <play>KEY_PLAY</play> <play>KEY_PLAYPAUSE</play> <pause>KEY_PAUSE</pause> <stop>KEY_STOP</stop> <record>KEY_RECORD</record> <forward>KEY_FASTFORWARD</forward> <reverse>KEY_REWIND</reverse> <skipplus>KEY_NEXT</skipplus> <skipminus>KEY_BACK</skipminus> <power>KEY_POWER2</power> <channelplus>KEY_CHANNELUP</channelplus> <channelminus>KEY_CHANNELDOWN</channelminus> <title>KEY_PROG3</title> <volumeplus>KEY_VOLUMEUP</volumeplus> <volumeminus>KEY_VOLUMEDOWN</volumeminus> <teletext>KEY_TEXT</teletext> <mute>KEY_MUTE</mute> <start>KEY_SELECT</start> <subtitle>KEY_SUBTITLE</subtitle> <audio>KEY_MODE</audio> <mute>KEY_MUTE</mute> <myvideo>KEY_VIDEO</myvideo> <mymusic>KEY_AUDIO</mymusic> <mypictures>KEY_IMAGES</mypictures> <recordedtv>KEY_PVR</recordedtv> <guide>KEY_EPG</guide> <display>KEY_SCREEN</display> <enter>KEY_PROG4</enter> <playlist>KEY_ZOOM</playlist> <livetv>KEY_CHANNEL</livetv> <mytv>KEY_TV</mytv> <liveradio>KEY_FN</liveradio> </remote> </lircmap>
- keymaps
- remote.xml
<!-- This file contains the mapping of keys (gamepad, remote, and keyboard) to actions within XBMC --> <!-- The <global> section is a fall through - they will only be used if the button is not --> <!-- used in the current window's section. Note that there is only handling --> <!-- for a single action per button at this stage. --> <!-- For joystick/gamepad configuration under linux/win32, see below as it differs from xbox --> <!-- gamepads. --> <!-- The format is: --> <!-- <device> --> <!-- <button>action</button> --> <!-- </device> --> <!-- To map keys from other remotes using the RCA protocol, you may add <universalremote> blocks --> <!-- In this case, the tags used are <obc#> where # is the original button code (OBC) of the key --> <!-- You set it up by adding a <universalremote> block to the window or <global> section: --> <!-- <universalremote> --> <!-- <obc45>Stop</obc45> --> <!-- </universalremote> --> <!-- To find out the OBC's of your remote, try enabling the <displayremotecodes> tag in AdvancedSettings.xml --> <!-- Note that the action can be a built-in function. --> <!-- eg <B>XBMC.ActivateWindow(MyMusic)</B> --> <!-- would automatically go to My Music on the press of the B button. --> <!-- Joysticks / Gamepads: --> <!-- See the sample PS3 controller configuration below for the format. --> <!-- --> <!-- Joystick Name: --> <!-- Do 'cat /proc/bus/input/devices' or see your xbmc log file to find the names of --> <!-- detected joysticks. The name used in the configuration should match the detected name. --> <!-- --> <!-- Button Ids: --> <!-- 'id' is the button ID used by SDL. Joystick button ids of connected joysticks appear --> <!-- in xbmc.log when they are pressed. Use your log to map custom buttons to actions. --> <!-- --> <!-- Axis Ids / Analog Controls --> <!-- Coming soon. --> <keymap> <global> <universalremote> <obc150>XBMC.ejecttray()</obc150> <obc151>Playlist</obc151> </universalremote> <remote> <play>PlayPause</play> <pause>Pause</pause> <stop>Stop</stop> <forward>FastForward</forward> <reverse>Rewind</reverse> <left>Left</left> <right>Right</right> <up>Up</up> <down>Down</down> <select>Select</select> <pageplus>PageUp</pageplus> <pageminus>PageDown</pageminus> <back>ParentDir</back> <menu>PreviousMenu</menu> <title>ContextMenu</title> <info>Info</info> <skipplus>SkipNext</skipplus> <skipminus>SkipPrevious</skipminus> <display>FullScreen</display> <start>PreviousMenu</start> <record>Screenshot</record> <volumeplus>VolumeUp</volumeplus> <volumeminus>VolumeDown</volumeminus> <mute>Mute</mute> <power>XBMC.Quit()</power> <myvideo>XBMC.ActivateWindow(MyVideos)</myvideo> <mymusic>XBMC.ActivateWindow(MyMusic)</mymusic> <mypictures>XBMC.ActivateWindow(MyPictures)</mypictures> <!--- <mytv>XBMC.ActivateWindow(Home)</mytv> --> <recordedtv>XBMC.ActivateWindowAndFocus(MyPVR, 34,0, 13,0)</recordedtv> <!-- PVR: EPG --> <guide>XBMC.ActivateWindowAndFocus(MyPVR, 31,0, 10,0)</guide> <!-- PVR: Channellist --> <livetv>XBMC.ActivateWindowAndFocus(MyPVR, 32,0, 11,0)</livetv> <!-- PVR: Radio --> <liveradio>XBMC.ActivateWindowAndFocus(MyPVR, 33,0, 12,0)</liveradio> <red>XBMC.ActivateWindow(Home)</red> <yellow>XBMC.ActivateWindow(MyVideos)</yellow> <green>XBMC.ActivateWindow(MyMusic)</green> <!-- <blue>XBMC.ActivateWindow(MyPictures)</blue> --> <zero>Number0</zero> <one>Number1</one> <two>JumpSMS2</two> <three>JumpSMS3</three> <four>JumpSMS4</four> <five>JumpSMS5</five> <six>JumpSMS6</six> <seven>JumpSMS7</seven> <eight>JumpSMS8</eight> <nine>JumpSMS9</nine> <audio>AudioNextLanguage</audio> <subtitle>ShowSubtitles</subtitle> <enter>FullScreen</enter> <blue>ContextMenu</blue> <playlist>XBMC.ActivateWindow(MyMusicPlaylist)</playlist> </remote> </global> <Home> <remote> <menu>XBMC.Skin.ToggleSetting(HomeViewToggle)</menu> <info>XBMC.ActivateWindow(SystemInfo)</info> <clear>XBMC.ActivateWindow(Weather)</clear> <blue>XBMC.ActivateWindow(Settings)</blue> <red>FullScreen</red> <back>FullScreen</back> </remote> </Home> <MyFiles> <remote> <clear>Delete</clear> </remote> </MyFiles> <MyMusicPlaylist> <remote> <back>Playlist</back> <!-- Close playlist --> <clear>Delete</clear> </remote> </MyMusicPlaylist> <MyMusicPlaylistEditor> <remote> <zero>Queue</zero> </remote> </MyMusicPlaylistEditor> <MyMusicFiles> <remote> <zero>Queue</zero> <star>Queue</star> <start>ContextMenu</start> </remote> </MyMusicFiles> <MyMusicLibrary> <remote> <zero>Queue</zero> <star>Queue</star> </remote> </MyMusicLibrary> <FullscreenVideo> <remote> <back>FullScreen</back> <zero>Number0</zero> <one>Number1</one> <two>Number2</two> <three>Number3</three> <four>Number4</four> <five>Number5</five> <six>Number6</six> <seven>Number7</seven> <eight>Number8</eight> <nine>Number9</nine> <left>Rewind</left> <right>FastForward</right> <up>Play</up> <down>Pause</down> <yellow>StepForward</yellow> <green>StepBack</green> <blue>CodecInfo</blue> <menu>OSD</menu> <start>OSD</start> <info>XBMC.ActivateWindow(PVROSDChannels)</info> <title>XBMC.ActivateWindow(PVROSDChannels)</title> <display>AspectRatio</display> <select>Info</select> <teletext>XBMC.ActivateWindow(Teletext)</teletext> <channelplus>SkipNext</channelplus> <channelminus>SkipPrevious</channelminus> <record>XBMC.PlayerControl(Record)</record> </remote> </FullscreenVideo> <FullscreenInfo> <remote> <back>FullScreen</back> <left>Rewind</left> <right>FastForward</right> <up>Play</up> <down>Pause</down> <yellow>StepForward</yellow> <green>StepBack</green> <display>AspectRatio</display> <info>CodecInfo</info> <select>Close</select> <menu>OSD</menu> </remote> </FullscreenInfo> <PlayerControls> <remote> <back>Close</back> <menu>Close</menu> </remote> </PlayerControls> <Visualisation> <universalremote> <obc151>XBMC.ActivateWindow(MyMusicPlaylist)</obc151> </universalremote> <remote> <red>FullScreen</red> <yellow>AnalogSeekForward</yellow> <green>AnalogSeekBack</green> <blue>CodecInfo</blue> <left>Rewind</left> <right>FastForward</right> <pageplus>SkipNext</pageplus> <pageminus>SkipPrevious</pageminus> <up>Play</up> <down>Pause</down> <info>XBMC.ActivateWindow(PVROSDChannels)</info> <back>XBMC.ActivateWindow(MyMusicPlaylist)</back> <select>Info</select> <menu>XBMC.ActivateWindow(MusicOSD)</menu> <start>XBMC.ActivateWindow(MusicOSD)</start> </remote> </Visualisation> <MusicOSD> <remote> <back>Close</back> <menu>Close</menu> <start>Close</start> <info>CodecInfo</info> </remote> </MusicOSD> <VisualisationSettings> <remote> <back>Close</back> <menu>Close</menu> </remote> </VisualisationSettings> <VisualisationPresetList> <remote> <back>Close</back> <menu>Close</menu> </remote> </VisualisationPresetList> <SlideShow> <remote> <zero>ZoomNormal</zero> <one>ZoomLevel1</one> <two>ZoomLevel2</two> <three>ZoomLevel3</three> <four>ZoomLevel4</four> <five>ZoomLevel5</five> <six>ZoomLevel6</six> <seven>ZoomLevel7</seven> <eight>ZoomLevel8</eight> <nine>ZoomLevel9</nine> <info>CodecInfo</info> <pageplus>ZoomIn</pageplus> <pageminus>ZoomOut</pageminus> <select>Rotate</select> <up>Pause</up> <down>Play</down> <back>PreviousMenu</back> </remote> </SlideShow> <ScreenCalibration> <remote> <select>NextCalibration</select> <enter>NextCalibration</enter> <zero>ResetCalibration</zero> <display>NextResolution</display> <xbox>NextResolution</xbox> </remote> </ScreenCalibration> <GUICalibration> <remote> <select>NextCalibration</select> <enter>NextCalibration</enter> <zero>ResetCalibration</zero> </remote> </GUICalibration> <SelectDialog> <remote> <back>Close</back> </remote> </SelectDialog> <VideoOSD> <remote> <back>PreviousMenu</back> <menu>Close</menu> <start>Close</start> </remote> </VideoOSD> <VideoMenu> <remote> <menu>OSD</menu> <back>PreviousMenu</back> <info>Info</info> <title>CodecInfo</title> <zero>Number0</zero> <one>Number1</one> <two>Number2</two> <three>Number3</three> <four>Number4</four> <five>Number5</five> <six>Number6</six> <seven>Number7</seven> <eight>Number8</eight> <nine>Number9</nine> </remote> </VideoMenu> <OSDVideoSettings> <remote> <back>Close</back> <menu>Close</menu> <start>Close</start> </remote> </OSDVideoSettings> <OSDAudioSettings> <remote> <back>Close</back> <menu>Close</menu> <start>Close</start> </remote> </OSDAudioSettings> <VideoBookmarks> <remote> <back>Close</back> <menu>Close</menu> <start>Close</start> <zero>Delete</zero> </remote> </VideoBookmarks> <MyVideoLibrary> <remote> <zero>Queue</zero> <clear>Delete</clear> <green>ToggleWatched</green> <yellow>Queue</yellow> </remote> </MyVideoLibrary> <MyVideoFiles> <remote> <zero>Queue</zero> <star>Queue</star> <blue>ContextMenu</blue> <green>ToggleWatched</green> <yellow>Queue</yellow> </remote> </MyVideoFiles> <MyPictures> <remote> <zero>Queue</zero> <star>Queue</star> <start>ContextMenu</start> </remote> </MyPictures> <MyVideoPlaylist> <remote> <back>Playlist</back> <!-- Close playlist --> <clear>Delete</clear> <zero>Delete</zero> </remote> </MyVideoPlaylist> <VirtualKeyboard> <remote> <back>BackSpace</back> <star>Shift</star> <hash>Symbols</hash> <zero>Number0</zero> <one>Number1</one> <two>Number2</two> <three>Number3</three> <four>Number4</four> <five>Number5</five> <six>Number6</six> <seven>Number7</seven> <eight>Number8</eight> <nine>Number9</nine> <pageminus>CursorLeft</pageminus> <pageplus>CursorRight</pageplus> </remote> </VirtualKeyboard> <ContextMenu> <remote> <blue>Close</blue> <back>Close</back> </remote> </ContextMenu> <FileStackingDialog> <remote> <back>Close</back> </remote> </FileStackingDialog> <Scripts> <remote> <info>XBMC.ActivateWindow(ScriptsDebugInfo)</info> </remote> </Scripts> <ScriptsDebugInfo> <remote> <info>Info</info> <!-- clears debug python info --> </remote> </ScriptsDebugInfo> <NumericInput> <remote> <zero>Number0</zero> <one>Number1</one> <two>Number2</two> <three>Number3</three> <four>Number4</four> <five>Number5</five> <six>Number6</six> <seven>Number7</seven> <eight>Number8</eight> <nine>Number9</nine> <back>BackSpace</back> </remote> </NumericInput> <Weather> <remote> <back>PreviousMenu</back> </remote> </Weather> <Settings> <remote> <back>PreviousMenu</back> </remote> </Settings> <MyPicturesSettings> <remote> <back>PreviousMenu</back> </remote> </MyPicturesSettings> <MyProgramsSettings> <remote> <back>PreviousMenu</back> </remote> </MyProgramsSettings> <MyWeatherSettings> <remote> <back>PreviousMenu</back> </remote> </MyWeatherSettings> <MyMusicSettings> <remote> <back>PreviousMenu</back> </remote> </MyMusicSettings> <SystemSettings> <remote> <back>PreviousMenu</back> </remote> </SystemSettings> <MyVideosSettings> <remote> <back>PreviousMenu</back> </remote> </MyVideosSettings> <NetworkSettings> <remote> <back>PreviousMenu</back> </remote> </NetworkSettings> <AppearanceSettings> <remote> <back>PreviousMenu</back> </remote> </AppearanceSettings> <Profiles> <remote> <back>PreviousMenu</back> </remote> </Profiles> <systeminfo> <remote> <back>PreviousMenu</back> </remote> </systeminfo> <shutdownmenu> <remote> <back>PreviousMenu</back> </remote> </shutdownmenu> <submenu> <remote> <back>PreviousMenu</back> </remote> </submenu> <MusicInformation> <remote> <back>Close</back> </remote> </MusicInformation> <MovieInformation> <remote> <back>Close</back> </remote> </MovieInformation> <LockSettings> <remote> <menu>Close</menu> <back>PreviousMenu</back> </remote> </LockSettings> <ProfileSettings> <remote> <menu>Close</menu> <back>PreviousMenu</back> </remote> </ProfileSettings> <PictureInfo> <remote> <skipplus>NextPicture</skipplus> <skipminus>PreviousPicture</skipminus> <info>Close</info> <back>Close</back> </remote> </PictureInfo> <Teletext> <remote> <zero>number0</zero> <one>number1</one> <two>number2</two> <three>number3</three> <four>number4</four> <five>number5</five> <six>number6</six> <seven>number7</seven> <eight>number8</eight> <nine>number9</nine> <red>Red</red> <green>Green</green> <yellow>Yellow</yellow> <blue>Blue</blue> <info>Info</info> <back>Close</back> <menu>Close</menu> <start>Close</start> <teletext>Close</teletext> </remote> </Teletext> <Favourites> <remote> <back>Close</back> </remote> </Favourites> </keymap>
- remote.xml
8.22 dvd
8.22.1 tasks
- install libdvd-pkg, allow programs to eject optical media
--- # file: roles/dvd/tasks/main.yml - name: preconfigure libdvd-pkg shell: | echo 'libdvd-pkg libdvd-pkg/post-invoke_hook-install boolean true' | debconf-set-selections echo 'libdvd-pkg libdvd-pkg/build boolean true' | debconf-set-selections - name: apt | install libdvd-pkg apt: name: '{{ item }}' state: present install_recommends: no with_items: - libdvd-pkg - name: change udev rule to allow KODI to eject optical disks shell: sed 's/--lock-media //' /lib/udev/rules.d/60-cdrom_id.rules > /etc/udev/rules.d/60-cdrom_id.rules args: creates: /etc/udev/rules.d/60-cdrom_id.rules
8.23 template-test
--- - name: show vars debug: var: '{{ system }}' - name: test templates template: src: templates/test.j2 dest: /tmp/test.txt
{{ ansible_managed_file | comment }} Section "ServerLayout" Identifier "Layout0" Screen 0 "Screen0" {% if system.x11.dualhead.enabled %} Screen 1 "Screen1" RightOf "Screen0" {% endif %} InputDevice "Keyboard0" "CoreKeyboard" InputDevice "Mouse0" "CorePointer" EndSection Section "InputDevice" # generated from default Identifier "Mouse0" Driver "mouse" Option "Protocol" "auto" Option "Device" "/dev/psaux" Option "Emulate3Buttons" "no" Option "ZAxisMapping" "4 5" EndSection # ignore devices with eventlircd tag # ENV{ID_INPUT.tags}+="eventlircd" # must be set by an udev rule Section "InputClass" Identifier "ignore eventlircd devices" MatchTag "eventlircd" Option "Ignore" "True" EndSection Section "InputDevice" # generated from default Identifier "Keyboard0" Driver "kbd" EndSection Section "Monitor" Identifier "Monitor0" VendorName "Unknown" ModelName "Unknown" {% if system.x11.display.0.default == "VGA2Scart_4_3" or system.x11.display.0.default == "VGA2Scart_16_9" %} HorizSync 14-17 VertRefresh 49-61 {% if system.x11.display.0.default == "VGA2Scart_4_3" %} Modeline "VGA2Scart_4_3" 13.875 720 744 808 888 576 580 585 625 -HSync -Vsync interlace {% elif system.x11.display.0.default == "VGA2Scart_16_9" %} Modeline "VGA2Scart_16_9" 19 1024 1032 1120 1216 576 581 586 625 -Hsync -Vsync interlace {% endif %} {% endif %} Option "DPMS" Option "ExactModeTimingsDVI" "True" EndSection {% if system.x11.dualhead.enabled == "1" %} Section "Monitor" Identifier "Monitor1" VendorName "Unknown" ModelName "Unknown" {% if system.x11.display.1.default in ("VGA2Scart_4_3", "VGA2Scart_16_9") %} HorizSync 14-17 VertRefresh 49-61 {% if system.x11.display.1.default == "VGA2Scart_4_3" %} Modeline "VGA2Scart_4_3" 13.875 720 744 808 888 576 580 585 625 -HSync -Vsync interlace {% elif system.x11.display.1.default == "VGA2Scart_16_9" %} Modeline "VGA2Scart_16_9" 19 1024 1032 1120 1216 576 581 586 625 -Hsync -Vsync interlace {% endif %} Option "DPMS" Option "ExactModeTimingsDVI" "True" {% endif %} EndSection {% endif %} Section "Device" Identifier "Device0" {% if system.hardware.nvidia.detected %} Driver "nvidia" VendorName "NVIDIA Corporation" {% endif %} Screen 0 Option "DPI" "100x100" {% if system.hardware.nvidia.busid %} BusID "PCI: {{ system.hardware.nvidia.busid }}" {% endif %} Option "NoLogo" "True" Option "UseEvents" "True" Option "TripleBuffer" "False" Option "AddARGBGLXVisuals" "True" Option "TwinView" "0" Option "DynamicTwinView" "0" Option "OnDemandVBlankinterrupts" "on" Option "FlatPanelProperties" "Scaling = Native" EndSection {% if system.x11.dualhead.enabled == "1" %} Section "Device" Identifier "Device1" {% if system.hardware.nvidia.detected %} Driver "nvidia" VendorName "NVIDIA Corporation" {% endif %} Screen 1 {% if system.hardware.nvidia.busid %} BusID "PCI: {{ system.hardware.nvidia.busid }}" {% endif %} Option "NoLogo" "True" Option "UseEvents" "True" Option "TripleBuffer" "False" Option "AddARGBGLXVisuals" "True" Option "TwinView" "0" Option "DynamicTwinView" "0" EndSection {% endif %} Section "Screen" Identifier "Screen0" Device "Device0" Monitor "Monitor0" DefaultDepth 24 SubSection "Display" Depth 24 {% if system.x11.display.0.default is defined and system.x11.display.0.default %} Modes "{{ system.x11.display.0.default }}"{% for mode in system.x11.display.0.mode %}{% if mode != system.x11.display.0.default %} "{{ mode }}"{% endif %}{% endfor %} {% elif system.hardware.nvidia.detected == 1 %} Modes "nvidia-auto-select" {% endif %} EndSubSection {% if system.x11.display.0.default or system.x11.default %} {% if system.x11.display.0.device is definded and system.x11.display.0.device %} Option "ConnectedMonitor" {{ system.x11.display.0.device }} {% else %} Option "ConnectedMonitor" {{ system.x11.default }} {% endif %} # Option "ConnectedMonitor" "<?cs if:(?system.x11.display.0.device) ?><?cs call:fix_display_name(system.x11.display.0.device) ?><?cs else ?><?cs var:system.x11.default ?><?cs /if ?><?cs if:(?system.x11.dualhead.enabled && system.x11.dualhead.enabled == 1) ?>, <?cs call:fix_display_name(system.x11.display.1.device) ?><?cs /if ?>" #Option "ConnectedMonitor" "<?cs if:(?system.x11.display.0.device) ?> <?cs call:fix_display_name(system.x11.display.0.device) ?> <?cs else ?> <?cs var:system.x11.default ?> <?cs /if ?> <?cs if:(?system.x11.dualhead.enabled && system.x11.dualhead.enabled == 1) ?>, <?cs call:fix_display_name(system.x11.display.1.device) ?><?cs /if ?>" # Option "UseDisplayDevice" "<?cs if:(?system.x11.display.0.device) ?><?cs call:fix_display_name(system.x11.display.0.device) ?><?cs else ?><?cs var:system.x11.default ?><?cs /if ?>" # <?cs /if ?> # <?cs if:(?system.hardware.nvidia.0.edid && system.hardware.nvidia.0.edid == "1") ?> # Option "CustomEDID" "<?cs call:fix_display_name(system.x11.display.0.device) ?>:/etc/X11/edid.0.yavdr" # <?cs /if ?> # <?cs if:(system.hardware.nvidia.detected == 1 && ?system.x11.display.0.device) ?> # Option "MetaModes" "<?cs call:fix_display_name(system.x11.display.0.device) ?>: <?cs var:system.x11.display.0.default ?> { ViewPortIn=<?cs var:system.x11.display.0.viewport.in.x ?>x<?cs var:system.x11.display.0.viewport.in.y ?>, ViewPortOut=<?cs var:system.x11.display.0.viewport.out.x ?>x<?cs var:system.x11.display.0.viewport.out.y ?>+<?cs var:system.x11.display.0.viewport.out.plusx ?>+<?cs var:system.x11.display.0.viewport.out.plusy ?> }" # <?cs each:mode = system.x11.display.0.mode ?><?cs if:(mode != system.x11.display.0.default) ?> # Option "MetaModes" "<?cs call:fix_display_name(system.x11.display.0.device) ?>: <?cs var:mode ?> { ViewPortIn=<?cs var:system.x11.display.0.viewport.in.x ?>x<?cs var:system.x11.display.0.viewport.in.y ?>, ViewPortOut=<?cs var:system.x11.display.0.viewport.out.x ?>x<?cs var:system.x11.display.0.viewport.out.y ?>+<?cs var:system.x11.display.0.viewport.out.plusx ?>+<?cs var:system.x11.display.0.viewport.out.plusy ?> }"<?cs /if ?><?cs /each ?> {% endif %} EndSection {% if system.x11.dualhead.enabled == "1" %} Section "Screen" Identifier "Screen1" Device "Device1" Monitor "Monitor1" DefaultDepth 24 SubSection "Display" Depth 24 {% if system.x11.display.0.default is defined and system.x11.display.0.default %} Modes "{{ system.x11.display.1.default }}"{% for mode in system.x11.display.1.mode %}{% if mode != system.x11.display.1.default %} "{{ mode }}"{% endif %}{% endfor %} {% elif system.hardware.nvidia.detected == "1" %} Modes "nvidia-auto-select" {% endif %} EndSubSection # <?cs if:(?system.x11.display.1.default && system.x11.display.1.default != "" && system.x11.display.1.default != "disabled") ?> # Option "UseDisplayDevice" "<?cs call:fix_display_name(system.x11.display.1.device) ?>" # <?cs /if ?> # <?cs if:(?system.hardware.nvidia.1.edid && system.hardware.nvidia.1.edid == "1") ?> # Option "CustomEDID" "<?cs call:fix_display_name(system.x11.display.1.device) ?>:/etc/X11/edid.1.yavdr" # <?cs /if ?> # <?cs if:(system.hardware.nvidia.detected == 1 && ?system.x11.display.1.device) ?> # Option "MetaModes" "<?cs call:fix_display_name(system.x11.display.1.device) ?>: <?cs var:system.x11.display.1.default ?> { ViewPortIn=<?cs var:system.x11.display.1.viewport.in.x ?>x<?cs var:system.x11.display.1.viewport.in.y ?>, ViewPortOut=<?cs var:system.x11.display.1.viewport.out.x ?>x<?cs var:system.x11.display.1.viewport.out.y ?>+<?cs var:system.x11.display.1.viewport.out.plusx ?>+<?cs var:system.x11.display.1.viewport.out.plusy ?> }" # <?cs each:mode = system.x11.display.1.mode ?><?cs if:(mode != system.x11.display.1.default) ?> # Option "MetaModes" "<?cs call:fix_display_name(system.x11.display.1.device) ?>: <?cs var:mode ?> { ViewPortIn=<?cs var:system.x11.display.1.viewport.in.x ?>x<?cs var:system.x11.display.1.viewport.in.y ?>, ViewPortOut=<?cs var:system.x11.display.1.viewport.out.x ?>x<?cs var:system.x11.display.1.viewport.out.y ?>+<?cs var:system.x11.display.1.viewport.out.plusx ?>+<?cs var:system.x11.display.1.viewport.out.plusy ?> }"<?cs /if ?><?cs /each ?> # <?cs /if ?> EndSection {% endif %} {% if not system.x11.use_compositing %} Section "Extensions" # if not open-gl OSD is needed (e.g. for vdr-sxfe): Option "Composite" "Disable" EndSection {% endif %}
foo: - bar - baz - spam system: hardware: nvidia: detected: "1" busid: "000:2304:234" x11: dualhead: enabled: "0" display: 0: mode: - "1920x1080_50" default: "nvidia-auto" 1: mode: - "1280x720_60"
8.24 grub-config
8.24.1 default variables
system: shutdown: poweroff grub: timeout: 0 boot_options: quiet nosplash
8.24.2 tasks
--- - name: custom grub configuration for timeout and reboot halt template: src: templates/50_custom.j2 dest: /etc/grub.d/50_custom mode: '0775' notify: [ 'Update GRUB' ] # TODO: add special case if plymouth is used - name: let the system boot quietly lineinfile: dest: /etc/default/grub state: present regexp: '^(GRUB_CMDLINE_LINUX_DEFAULT=")' line: '\1{{ grub.boot_options}}"' backrefs: yes notify: [ 'Update GRUB' ]
8.24.3 templates
#!/bin/sh exec tail -n +3 $0 # This file is configured by the ansible configuration for yaVDR {% if system.shutdown is defined and system.shutdown == 'reboot' %} menuentry "PowerOff" { halt } {% endif %} if [ "${recordfail}" = 1 ]; then set timeout={{ 3 if grub.timeout < 3 else grub.timeout }} else set timeout={{ grub.timeout if grub.timeout is defined else 0 }} fi
8.24.4 handlers
--- - name: Update GRUB command: update-grub failed_when: ('error' in grub_register_update.stderr) register: grub_register_update # TODO: Do we need to use grub-set-default? # https://github.com/yavdr/yavdr-utils/blob/master/events/actions/update-grub
9 Modules
This section contains custom modules for the yaVDR Playbooks. They are used to collect facts about the system and configure applications and daemons.
9.1 hardware_facts.py
# This Module collects the vendor- and device ids for USB- and PCI(e)-devices and currently loaded kernel modules. DOCUMENTATION = ''' --- module: hardware_facts short_description: collects facts for kernel modules, usb and pci devices description: - This Module collects the vendor- and device ids for USB- and PCI(e)-devices and currently loaded kernel modules. options: usb: required: False default: True description: - return a list of vendor- and device ids for usb devices in '04x:04x' notation pci: required: False default: True description: - return a list of vendor- and device ids for pci devices in '04x:04x' notation modules: required: False default: True description: - return a list of currently loaded kernel modules gpus: required: False default: True description: - return a list of devices of the pci gpu class (0x030000) notes: - requres python-pyusb and python-kmodpy requirements: [ ] author: "Alexander Grothe <seahawk1986@gmx.de>" ''' EXAMPLES = ''' - name: get information about usb and pci hardware and loaded kernel modules hardware_facts: usb: True pci: True modules: True - debug: var: usb - debug var: pci - debug var: modules - debug var: gpus ''' import glob import json import os import sys import usb.core from collections import namedtuple import kmodpy from ansible.module_utils.basic import * PCIDevice = namedtuple("PCIDevice", 'idVendor idProduct idClass pciPath') def get_pci_devices(): for device in glob.glob('/sys/devices/pci*/*:*:*/'): with open(os.path.join(device, 'device')) as d: product_id = int(d.read().strip(), 16) with open(os.path.join(device, 'vendor')) as d: vendor_id = int(d.read().strip(), 16) with open(os.path.join(device, 'class')) as d: class_id = int(d.read().strip(), 16) yield PCIDevice(idVendor=vendor_id, idProduct=product_id, idClass=class_id, pciPath=device) def format_device_list(iterator): return ["{:04x}:{:04x}".format(d.idVendor, d.idProduct) for d in iterator] def format_gpu_device_list(iterator): def get_entries(iterator): for d in iterator: if d.idClass == 0x030000: yield ("{:04x}:{:04x}".format(d.idVendor, d.idProduct)) return [entry for entry in get_entries(iterator)] arg_specs = { 'usb': dict(default=True, type='bool', required=False), 'pci': dict(default=True, type='bool', required=False), 'modules': dict(default=True, type='bool', required=False), 'gpus': dict(default=True, type='bool', required=False), } def main(): module = AnsibleModule(argument_spec=arg_specs, supports_check_mode=True,) collect_usb = module.params['usb'] collect_pci = module.params['pci'] collect_modules = module.params['modules'] collect_gpus = module.params['gpus'] if collect_usb: usb_devices = format_device_list(usb.core.find(find_all=True)) else: usb_device = [] if collect_pci: pci_devices = format_device_list(get_pci_devices()) else: pci_devices = [] if collect_modules: k = kmodpy.Kmod() modules = [m[0] for m in k.loaded()] else: modules = [] if collect_gpus: gpus = format_gpu_device_list(get_pci_devices()) else: gpus = [] data = {'usb': usb_devices, 'pci': pci_devices, 'modules': modules, 'gpus': gpus} module.exit_json(changed=False, ansible_facts=data, msg=data) if __name__ == '__main__': main()
9.2 satip_facts.py
DOCUMENTATION = ''' --- module: hardware_facts short_description: "check if at least one SAT>IP server responds on the network" description: - This script sends a multicast message and awaits responses by Sat>IP servers. Returns the boolean variable 'satip_detected' ''' EXAMPLES = ''' - name: "detect SAT>IP Server on the network" action: satip_facts - debug: var: satip_detected ''' import json import socket import sys import time from ansible.module_utils.basic import * SSDP_ADDR = "239.255.255.250" SSDP_PORT = 1900 # SSDP_MX = max delay for server response # a value of 2s is recommended by the SAT>IP specification 1.2.2 SSDP_MX = 2 SSDP_ST = "urn:ses-com:device:SatIPServer:1" ssdpRequest = "\r\n".join(( "M-SEARCH * HTTP/1.1", "HOST: %s:%d" % (SSDP_ADDR, SSDP_PORT), "MAN: \"ssdp:discover\"", "MX: %d" % (SSDP_MX), "ST: %s" % (SSDP_ST), "\r\n")) def main(): module = AnsibleModule(argument_spec={}, supports_check_mode=True,) sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # according to Sat>IP Specification 1.2.2, p. 20 # a client should send three requests within 100 ms with a ttl of 2 sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 2) sock.settimeout(SSDP_MX + 0.5) for _ in range(3): sock.sendto(ssdpRequest, (SSDP_ADDR, SSDP_PORT)) time.sleep(0.03) try: response = sock.recv(1000) if response and "SERVER:" in response: got_response = True else: raise ValueError('No satip server detected') except (socket.timeout, ValueError): got_response = False module.exit_json(changed=False, ansible_facts={'satip_detected': got_response}) if __name__ == '__main__': main()
9.3 xrandr_facts.py
[ ]
support multiple screens (-d :0.0 .. :0.n)
from __future__ import print_function import ast import binascii import csv import re import subprocess from collections import namedtuple from ansible.module_utils.basic import * DOCUMENTATION = ''' --- module: xrandr_facts short_description: "gather facts about connected monitors and available modelines" description: - This module needs a running x-server on a given display in order to successfully call xrandr. Returns the dictionary "xrandr", wich contains all screens with output states, connected displays, EDID info and their modes and a recommendation for the best fitting tv mode. options: display: required: False default: ":0" description: - the DISPLAY variable to use when calling xrandr preferred_outpus: required: False default: ["HDMI", "DP", "DVI", "VGA", "TV": 0] description: - ranking of the preferred display connectors preferred_refreshrates: required: False default: ["50", "60", "75", "30", "25"] description: - ranking of the preferred display refreshrate preferred_resolutions: required: False default: ["7680x4320", "3840x2160", "1920x1080", "1280x720", "720x576"] description: - ranking of the preferred display resolutions write_edids: required: False default: True description: - write edid data to /etc/X11/edid.{connector}.bin ''' EXAMPLES = ''' - name: "collect facts for connected displays" action: xserver_facts display: ":0" - debug: var: xrandr - debug: var: xorg ''' ARG_SPECS = { 'display': dict(default=":0", type='str', required=False), 'preferred_outputs': dict( default=["HDMI", "DP", "DVI", "VGA", "TV"], type='list', required=False), 'preferred_refreshrates': dict( default=[50, 60, 75, 30, 25], type='list', required=False), 'preferred_resolutions': dict( default=[ "7680x4320", "3840x2160", "1920x1080", "1280x720", "720x576"], type='list', required=False), 'write_edids': dict(default=True, type='bool', required=False), } SCREEN_REGEX = re.compile("^(?P<screen>Screen\s\d+:)(?:.*)") CONNECTOR_REGEX = re.compile( "^(?P<connector>.*-\d+)\s(?P<connection_state>connected|disconnected)\s(?P<primary>primary)?") MODE_REGEX = re.compile("^\s+(?P<resolution>\d{3,}x\d{3,}).*") Mode = namedtuple('Mode', ['connection', 'resolution', 'refreshrate']) def check_for_screen(line): """check line for screen information""" match = re.match(SCREEN_REGEX, line) if match: return match.groupdict()['screen'] def check_for_connection(line): """check line for connection name and state""" match = re.match(CONNECTOR_REGEX, line) connector = None is_connected = False if match: match = match.groupdict() connector = match['connector'] is_connected = True if match['connection_state'] == 'connected' else False return connector, is_connected def get_indentation(line): """return the number of leading whitespace characters""" return len(line) - len(line.lstrip()) def sort_mode(mode): """rate modes by several criteria""" connection_score = 0 rrate_score = 0 resolution_score = 0 preferred_rrates = module.params['preferred_refreshrates'] # [50, 60] preferred_resolutions = module.params['preferred_resolutions'] # ["7680x4320", "3840x2160", "1920x1080", "1280x720", "720x576"] preferred_outputs = module.params['preferred_outputs'] # ["HDMI", "DP", "DVI", "VGA"] if mode.refreshrate in preferred_rrates: rrate_score = len(preferred_rrates) - preferred_rrates.index(mode.refreshrate) if mode.resolution in preferred_resolutions: resolution_score = len(preferred_resolutions) - preferred_resolutions.index(mode.resolution) x_resolution, y_resolution = (int(n) for n in mode.resolution.split('x')) connection = mode.connection.split('-')[0] if connection in preferred_outputs: connection_score = len(preferred_outputs) - preferred_outputs.index(connection) return (rrate_score, resolution_score, x_resolution, y_resolution, connection_score) def parse_xrandr_verbose(iterator): """parse the output of xrandr --verbose using an iterator delivering single lines""" xorg = {} is_connected = False for line in iterator: if line.startswith('Screen'): screen = check_for_screen(line) xorg[screen] = {} elif 'connected' in line: connector, is_connected = check_for_connection(line) xorg[screen][connector] = { 'is_connected': is_connected, 'EDID': '', 'modes': {}, 'preferred': '', 'current': '', 'auto': '', } elif is_connected and 'EDID:' in line: edid_str = "" outer_indentation = get_indentation(line) while True: line = next(iterator) if get_indentation(line) > outer_indentation: edid_str += line.strip() else: break xorg[screen][connector]['EDID'] = edid_str elif is_connected and "MHz" in line and not "Interlace" in line: match = re.match(MODE_REGEX, line) if match: match = match.groupdict() preferred = bool("+preferred" in line) current = bool("*current" in line) while True: line = next(iterator) if line.strip().startswith('v:'): refresh_rate = ast.literal_eval(line.split()[-1][:-2]) rrate = int(round(refresh_rate)) if xorg[screen][connector]['modes'].get(match['resolution']) is None: xorg[screen][connector]['modes'][match['resolution']] = [] if rrate not in xorg[screen][connector]['modes'][match['resolution']]: xorg[screen][connector]['modes'][match['resolution']].append(rrate) if preferred: xorg[screen][connector]['preferred'] = "{}_{}".format( match['resolution'], rrate) if current: xorg[screen][connector]['current'] = "{}_{}".format( match['resolution'], rrate) break return xorg def parse_edid_data(edid): vendor = "Unknown" model = "Unknown" data = subprocess.check_output("parse-edid < {}".format(edid), shell=True, universal_newlines=True) for line in data.splitlines(): if "VendorName" in line: vendor = line.strip().split('"')[1] if "ModelName" in line: model = line.strip().split('"')[1] return vendor, model def collect_nvidia_data(): BusID_RE = re.compile(( '(?P<domain>[0-9a-fA-F]+)' ':' '(?P<bus>[0-9a-fA-F]+)' ':' '(?P<device>[0-9a-fA-F]+)' '\.' '(?P<function>[0-9a-fA-F]+)' )) try: data = subprocess.check_output(["nvidia-smi", "--query-gpu=name,pci.bus_id", "--format=csv", "-i0"], universal_newlines=True) except subprocess.CalledProcessError: pass else: for row in csv.DictReader(data.splitlines(), delimiter=',', skipinitialspace=True): name = row['name'] bus_id = row['pci.bus_id'] # pci.bus_id structure as reported by nvidia-smi: "domain:bus:device.function", in hex. match = BusID_RE.search(bus_id) if match: domain, bus, device, function = (int(n, 16) for n in match.groups()) bus_id = "PCI:{:d}@{:d}:{:d}:{:d}".format(bus, domain, device, function) return name, bus_id raise ValueError def output_data(data, write_edids=True): if data: modes = [] for _, screen_data in data.items(): for connector, connection_data in screen_data.items(): if connection_data.get('EDID') and write_edids: with open('/etc/X11/edid.{}.bin'.format(connector), 'wb') as edid: edid.write(binascii.a2b_hex(connection_data['EDID'])) for resolution, refreshrates in connection_data['modes'].items(): for refreshrate in refreshrates: modes.append(Mode(connector, resolution, refreshrate)) if modes: result = {} try: gpu_name, bus_id = collect_nvidia_data() except ValueError: gpu_name = None bus_id = None def create_entry(my_dict, name, connector, resolution, refreshrate, vendor, model): my_dict[name] = { 'connector': connector, 'resolution': resolution, 'refreshrate': refreshrate, 'edid': '/etc/X11/edid.{}.bin'.format(connector), 'mode': "{}_{}".format(resolution, refreshrate), 'vendor': vendor, 'model': model, } if gpu_name and bus_id: result[name]['gpu_name'] = gpu_name result[name]['bus_id'] = bus_id connector_0, resolution_0, refreshrate_0 = max(modes, key=sort_mode)[:3] vendor_0, model_0 = parse_edid_data('/etc/X11/edid.{}.bin'.format(connector_0)) create_entry(result, 'primary', connector_0, resolution_0, refreshrate_0, vendor_0, model_0) # check if additional monitors exist other_modes = [mode for mode in modes if mode[0] != connector_0] if other_modes: connector_1, resolution_1, refreshrate_1 = max(other_modes, key=sort_mode)[:3] vendor_1, model_1 = parse_edid_data('/etc/X11/edid.{}.bin'.format(connector_1)) create_entry(result, 'secondary', connector_1, resolution_1, refreshrate_1, vendor_1, model_1) #print(json.dumps(data, sort_keys=True, indent=4)) module.exit_json(changed=True if write_edids else False, ansible_facts={'xrandr': data, 'xorg': result}) if __name__ == '__main__': module = AnsibleModule(argument_spec=ARG_SPECS, supports_check_mode=False,) try: d = subprocess.check_output(['xrandr', '-d', module.params['display'], '--verbose'], universal_newlines=True).splitlines() except subprocess.CalledProcessError: xorg_data = {} else: xorg_data = parse_xrandr_verbose(iter(d)) output_data(xorg_data, module.params['write_edids'])
10 Handlers
- name: Restart Samba systemd: name: smbd.service state: restarted enabled: yes #masked: no register: samba_reload - name: Restart NFS Kernel Server systemd: name: nfs-server.service state: restarted enabled: yes #masked: no register: nfs_reload - name: Restart VDR systemd: name: vdr.service state: restarted enabled: yes register: vdr_restart - name: Stop VDR systemd: name: vdr.service state: stopped enabled: yes register: vdr_stop - name: Start VDR systemd: name: vdr.service state: started enabled: yes register: vdr_start - name: Stop xlogin systemd: name: xlogin@vdr.service state: stopped enabled: yes register: xlogin_stop - name: Stop x systemd: name: x@vt7.service state: stopped register: x_stop