Compare commits
366 Commits
Author | SHA1 | Date | |
---|---|---|---|
12f0b831b8 | |||
|
2468270ee6 | ||
|
9e58e0b4e4 | ||
|
9648bae2bd | ||
|
6cf02c5304 | ||
|
c96c146ff2 | ||
|
5f7414c008 | ||
|
23e54c67a7 | ||
|
c522d19c2b | ||
|
adab0137d2 | ||
|
5f5dec80ea | ||
|
e2e7ec8a0c | ||
|
252d6b65d1 | ||
|
de699b12b1 | ||
|
6cff93c558 | ||
|
85de5f119e | ||
|
3ebd5df3cb | ||
|
a3331d82e4 | ||
|
9b16bd9971 | ||
|
36050df5e0 | ||
|
7459c79595 | ||
|
ce24cedf53 | ||
|
f33eae5cd2 | ||
|
9acae05e63 | ||
|
f16e0cdb70 | ||
|
10c1c662c4 | ||
|
e2326c5083 | ||
|
9a35ed4a67 | ||
|
f4788484a9 | ||
|
9d61e71246 | ||
|
186319044a | ||
|
20812dc872 | ||
|
5bb14e04e6 | ||
|
4973ca953f | ||
|
8f22f9bf80 | ||
|
d306eb118e | ||
|
251a9b978d | ||
|
c88f919380 | ||
|
1542c64c5a | ||
|
202fb89165 | ||
|
f9a61eece0 | ||
|
62473292fc | ||
|
8dbbfcc0c7 | ||
|
811686490f | ||
|
d86e5f2159 | ||
|
be33234084 | ||
|
01d95ae89b | ||
|
c706146eac | ||
|
c0ad4c9c49 | ||
|
71e772cdca | ||
|
fa25896096 | ||
|
877e651917 | ||
|
76ace23b5e | ||
|
b816a03d69 | ||
|
71c2079f53 | ||
|
08ed05594e | ||
|
c0dc185952 | ||
|
65e2ac1e5f | ||
|
4a2f644bb3 | ||
|
4bdabc7992 | ||
|
c2962eed4c | ||
|
579f3e0cd3 | ||
|
9180f8d74e | ||
|
d4cbb054bd | ||
|
8b885221ae | ||
|
a4dcadabcf | ||
|
58859dd8d7 | ||
|
387daa0134 | ||
|
6f91f95d49 | ||
|
128e1683c1 | ||
|
964d41a41a | ||
|
f5d5d78a57 | ||
|
a29189252e | ||
|
711afd35d0 | ||
|
2559779de3 | ||
|
89c7254d43 | ||
|
6522156b07 | ||
|
1622bbd6e6 | ||
|
7dd080e9e7 | ||
|
f253d7c864 | ||
|
b3195507fa | ||
|
81aeade96c | ||
|
b45785bb6d | ||
|
f1709c8494 | ||
|
326c7d3119 | ||
|
21710fc62b | ||
|
b4afe5129f | ||
|
142487622e | ||
|
591579a492 | ||
|
f2b75bb5f7 | ||
|
ab2cf081b4 | ||
|
82ecb114b1 | ||
|
01e91cc529 | ||
|
9ac3f32c32 | ||
|
fb9ea5a363 | ||
|
6f2b486608 | ||
|
96b029fd24 | ||
|
febd80390f | ||
|
03b70283ae | ||
|
c4ddbb135a | ||
|
1fbd634d43 | ||
|
ae5d68ed79 | ||
|
553ff47248 | ||
|
2d966364e5 | ||
|
cd10eb1970 | ||
|
f1c422d151 | ||
|
8fbc3f08a5 | ||
|
244d5b63c1 | ||
|
4286ede906 | ||
|
cbce3852d9 | ||
|
a4a1440177 | ||
|
47061871ed | ||
|
dab64fe2e3 | ||
|
619a46649e | ||
|
f6f5dc59ca | ||
|
4c78cdf79a | ||
|
d851a4a9aa | ||
|
260653229b | ||
|
804f9f172f | ||
|
468de0a2f3 | ||
|
171bdd2eff | ||
|
3a349fd6ed | ||
|
73a7e75db9 | ||
|
4c6c77ccc5 | ||
|
8a91c4f7cd | ||
|
057411cec8 | ||
|
48710c22c6 | ||
|
5035437aa2 | ||
|
9d9ac03f5d | ||
|
e4eebf2e2d | ||
|
88d16009c7 | ||
|
840423bacf | ||
|
fa2e50128d | ||
|
da6cac8e24 | ||
|
264f1b311c | ||
|
43ced38313 | ||
|
16b84b080d | ||
|
6460697d33 | ||
|
9ec3fb07ec | ||
|
16886c3806 | ||
|
b8bd4b405e | ||
|
4170935a5a | ||
|
8694b2b05c | ||
|
46de4a1b80 | ||
|
281e73cab4 | ||
|
0e00ea7469 | ||
|
05ca162830 | ||
|
3138c16a60 | ||
|
4cbb78ca34 | ||
|
b00876f0fd | ||
|
b1389ae487 | ||
|
96b19af073 | ||
|
2ac7044459 | ||
|
de6ea4615b | ||
|
ddfd3cc441 | ||
|
3f989fcffb | ||
|
7b83faf750 | ||
|
d87fcd98f4 | ||
|
65dc2b4fd7 | ||
|
d68cbc252a | ||
|
70945dc97b | ||
|
6724ddcc23 | ||
|
524f43d494 | ||
|
d73bc61d69 | ||
|
96d2cc9a08 | ||
|
a330dd00a2 | ||
|
183bd4bc30 | ||
|
e5e15fa527 | ||
|
47c6a06ef2 | ||
|
85d9d624e6 | ||
|
f779fba01c | ||
|
37df4f25bb | ||
|
85fe14ffd2 | ||
|
4f857589d9 | ||
|
a55eccce33 | ||
|
c43bcc30bb | ||
|
c6df27ca0c | ||
|
2dc40f1595 | ||
|
4bfe28d0a9 | ||
|
71a48021eb | ||
|
f33d0e1e64 | ||
|
b310e3341c | ||
|
d2afb2f2cc | ||
|
3610ab3471 | ||
|
3e14f0a969 | ||
|
d8f70de0b5 | ||
|
00d4b49aa7 | ||
|
d0e13acdb3 | ||
|
70cec795de | ||
|
cbfa45c4f2 | ||
|
5f34537b03 | ||
|
477bcc136b | ||
|
218007ea77 | ||
|
fa6f49de85 | ||
|
0663b6fcb2 | ||
|
84cb485404 | ||
|
b0ddbb852d | ||
|
d74da7560a | ||
|
928bbb5b08 | ||
|
3b4f9d947d | ||
|
85a0b26471 | ||
|
d3ca791a75 | ||
|
b43181b9cc | ||
|
9a53fbc1de | ||
|
2745fa83b3 | ||
|
5c385c03fa | ||
|
4d393d924f | ||
|
e51cfe4447 | ||
|
43e1e10989 | ||
|
19bdac4219 | ||
|
528d022d54 | ||
|
5e971cec4c | ||
|
7f2c92d7a2 | ||
|
9c17b948af | ||
|
06ee0d83a8 | ||
|
08c2154220 | ||
|
b08f5d842a | ||
|
b8b86e8a1d | ||
|
252cade885 | ||
|
92128ccce7 | ||
|
51dd198799 | ||
|
7de6a0e193 | ||
|
3e24e74cff | ||
|
c53470f2fe | ||
|
dacbabee0e | ||
|
7c88fd6e6a | ||
|
3eb292f7fb | ||
|
54401f74e0 | ||
|
c44ee8867c | ||
|
1bcf91fecc | ||
|
7f8f5b8290 | ||
|
e1b17e00aa | ||
|
b1ebc54438 | ||
|
fbb6003cf9 | ||
|
c36056561f | ||
|
af3ef457b6 | ||
|
98729f7cbd | ||
|
ffc4707fdc | ||
|
886fff4f09 | ||
|
c6207490b8 | ||
|
3006830cc1 | ||
|
9f42da23f6 | ||
|
4b8ff236b5 | ||
|
2e8bd59576 | ||
|
ec0234f938 | ||
|
d09df785b6 | ||
|
1d108dc61f | ||
|
d8c3b9c5bd | ||
|
ce941ce722 | ||
|
2c08b97090 | ||
|
4c96c0a128 | ||
|
13209045b8 | ||
|
27278862a5 | ||
|
88254f8e79 | ||
|
41e44b67a4 | ||
|
467c960bf3 | ||
|
6468b5d432 | ||
|
7476635066 | ||
|
34a0a0e36c | ||
|
b9c56955b4 | ||
|
4682af7c3a | ||
|
14d05a742b | ||
|
c54313c6e7 | ||
|
f42fc8f144 | ||
|
02a1d94108 | ||
|
9440928891 | ||
|
1689195d42 | ||
|
8d201c2e62 | ||
|
98674ffc4f | ||
|
2f02f49aa1 | ||
|
07b9f18659 | ||
|
fb4483c01f | ||
|
4f95b57a9d | ||
|
4b9332b277 | ||
|
1befca797e | ||
|
fd1d7744fb | ||
|
784ea1d0b2 | ||
|
3aadc14dbb | ||
|
ea39de7a21 | ||
|
4c4705e49f | ||
|
87969286f2 | ||
|
a84b9b1742 | ||
|
bde3106c47 | ||
|
0c1f52d986 | ||
|
04662f2b83 | ||
|
4cf30fabd0 | ||
|
3051e04c53 | ||
|
767807e3e4 | ||
|
89963fa35b | ||
|
b9e4f1bc33 | ||
|
7726ce1399 | ||
|
345e373a52 | ||
|
63bc6828aa | ||
|
5d6ffd6f4c | ||
|
dd0cd703fe | ||
|
4097b01602 | ||
|
b1532f7a7a | ||
|
f94dd32250 | ||
|
7b685ebe98 | ||
|
1405c73c87 | ||
|
59685f9a99 | ||
|
dabc057ed7 | ||
|
036fd26287 | ||
|
2b749ba457 | ||
|
a7bc7a4386 | ||
|
3708289de7 | ||
|
048ae4e5d4 | ||
|
295a99c622 | ||
|
1f2a51dd37 | ||
|
6b130a3df3 | ||
|
9860f607a0 | ||
|
f302e4e06c | ||
|
f8553943ab | ||
|
c5d0277610 | ||
|
19a1f98d74 | ||
|
748df6954e | ||
|
49bcecb027 | ||
|
68396b3797 | ||
|
c70d6f97c6 | ||
|
f6ec12448a | ||
|
4ed8729282 | ||
|
885b5bd893 | ||
|
d08d060439 | ||
|
0cd621b6a6 | ||
|
6ae45c65ce | ||
|
11eb950977 | ||
|
23e09863dc | ||
|
b93b0e7ec6 | ||
|
cfb28e88cc | ||
|
440032137b | ||
|
3372fcec4c | ||
|
0d01ee282b | ||
|
75cd1eb560 | ||
|
d9eb820ea0 | ||
|
115bfe66c9 | ||
|
74159df8ac | ||
|
7fc4dee8fc | ||
|
9060429ba6 | ||
|
052b46ee34 | ||
|
3e8e077164 | ||
|
7682a3373d | ||
|
51226ff994 | ||
|
636ff5722a | ||
|
eb02b5e3a7 | ||
|
0616ac4982 | ||
|
446fb8d53f | ||
|
04bf735d28 | ||
|
beb27b8c66 | ||
|
5a0e076e26 | ||
|
c6837bde93 | ||
|
cebb916477 | ||
|
757eb39366 | ||
|
3ffeb101aa | ||
|
fe985aa6d9 | ||
|
1f5b845a4f | ||
|
69e6b90885 | ||
|
45376bea14 | ||
|
3dec24c10a | ||
|
21e5150981 | ||
|
7257d8845a | ||
|
98513bba11 | ||
|
c78f370aca | ||
|
55770c4eb6 | ||
|
5c5826db9a | ||
|
fc2a33da97 | ||
|
c05b98cdf1 |
9528
Manual.html
9528
Manual.html
File diff suppressed because it is too large
Load Diff
4857
Manual.org
4857
Manual.org
File diff suppressed because it is too large
Load Diff
67
README.md
67
README.md
@ -1,12 +1,75 @@
|
||||
# yavdr-ansible
|
||||
ansible playbooks for yaVDR
|
||||
|
||||
## What can yavdr-ansible do for me?
|
||||
[Ansible](https://docs.ansible.com/ansible/latest/index.html) is an automation tool which can be used to configure systems and deploy software.
|
||||
yavdr-ansible uses Ansible to set up a yaVDR System on top of an Ubuntu 18.04 Server installation (see below for details) and allows the user to fully customize the installation - have a look at the Ansible documentation if you want to learn how it works.
|
||||
|
||||
Please note that this is still work in progress and several features of yaVDR 0.6 haven't been implemented (yet).
|
||||
|
||||
## System Requirements and Compatiblity Notes
|
||||
- RTC must be set to UTC in order for vdr-addon-acpiwakeup to work properly
|
||||
- 32 Bit Installations are untested, but should work
|
||||
- You need an IGP/GPU with support for VDPAU or VAAPI if you want to use software output plugins for VDR like softhddevice or vaapidevice
|
||||
- xineliboutput/vdr-sxfe works with software rendering, too
|
||||
- Can be used in a VirtualBox VM (VirtualBox 5.22 works better than Version 6.0.0)
|
||||
|
||||
## Usage:
|
||||
|
||||
On a Ubuntu Server 16.04.x Installation run the following commands:
|
||||
Set up a Ubuntu Server 18.04.x Installation and install `openssh-server`.
|
||||
|
||||
NOTE: it is important to use the [alternative server installer](https://www.ubuntu.com/download/alternative-downloads#alternate-ubuntu-server-installer) or the [mini.iso](https://help.ubuntu.com/community/Installation/MinimalCD), otherwise the boot splash and Xorg won't work properly.
|
||||
|
||||
### Download yavdr-ansible
|
||||
NOTE: It is recommended to use a SSH connection to run the playbook, especially if a nvidia card is used (in order to change from the nouveau to the nvidia driver the local console output needs to be disabled temporarily).
|
||||
|
||||
Run the following commands to download the current version of yavdr-ansible:
|
||||
```
|
||||
sudo apt-get install git
|
||||
git clone https://github.com/yavdr/yavdr-ansible
|
||||
cd yavdr-ansible
|
||||
sudo ./install-yavdr.sh
|
||||
git checkout bionic
|
||||
```
|
||||
|
||||
### Customizing the Playbooks and Variables
|
||||
You can choose the roles run by the playbooks `yavdr07.yml` or ` yavdr07-headless.yml`.
|
||||
|
||||
If you want to customize the variables in [group_vars/all](group_vars/all), copy the file to `host_vars/localhost` before changing it. This way you can change the PPAs used and choose which extra vdr plugins and packages should be installed by default.
|
||||
|
||||
### Run the Playbook
|
||||
If you want a system with Xorg output run:
|
||||
```
|
||||
sudo -H ./install-yavdr.sh
|
||||
```
|
||||
NOTE: on systems with a nvidia card unloading the noveau driver after installing the proprietary nvidia driver can fail (in this case ansible throws an error). If this happens please reboot your system to allow the nvidia driver to be loaded and run the install script again.
|
||||
|
||||
If you want a headless vdr server run:
|
||||
```
|
||||
sudo -H ./install-yavdr-headless.sh
|
||||
```
|
||||
|
||||
## First Steps after the installation:
|
||||
|
||||
### Wait for local dvb adapters
|
||||
The yaVDR VDR Package provides a systemd service `wait-for-dvb@.service` which allows to delay the start of vdr until all given locally connected dvb adapters have been initalized - e.g. to wait for `/dev/dvb/adapter0 .. /dev/dvb/adapter3`you can enable the required instances of this service like this:
|
||||
```shell
|
||||
systemctl enable wait-for-dvb@{0..3}.service
|
||||
```
|
||||
Please remember to adapt the enabled service instances if you change your configuration.
|
||||
|
||||
This should work foll all DVB adaptors for which udev events are generated. Note that devices with userspace drivers (e.g. by Sundtek) won't emit such events.
|
||||
|
||||
### Add a /var/lib/vdr/channels.conf
|
||||
|
||||
You can use the wirbelscan-Plugin, w_scan, t2scan (especially useful for DVB-T2) or ready-to-use channellists from http://channelpedia.yavdr.com/gen/
|
||||
|
||||
Important: vdr.service must be stopped if you want to edit VDR configuration files: `sudo stop vdr.service`
|
||||
|
||||
### Rescan displays
|
||||
If you change the connected displays you may need to update the display configuration. This can be achived by running the `yavdr-xorg` role:
|
||||
```shell
|
||||
sudo -H ansible-playbook yavdr07.yml -b -i 'localhost_inventory' --connection=local --tags="yavdr-xorg"
|
||||
```
|
||||
|
||||
### running single roles without a custom playbook
|
||||
You can choose to (re-)run single roles included in a playbook by including their name in the `--tags` argument (see example above for rescanning displays with `yavdr-xorg`).
|
||||
|
5
ansible.cfg
Normal file
5
ansible.cfg
Normal file
@ -0,0 +1,5 @@
|
||||
[defaults]
|
||||
callback_plugins = plugins/callbacks
|
||||
callback_whitelist = auto_tags
|
||||
ansible_managed = *** ANSIBLE MANAGED FILE ***
|
||||
template: {file}
|
@ -1,8 +1,8 @@
|
||||
---
|
||||
# file: displays.yml
|
||||
# this playbook runs the yavdr-xorg playbook
|
||||
# this playbook runs the yavdr-xorg role
|
||||
|
||||
- name: set up yaVDR
|
||||
- name: rescan displays
|
||||
hosts: all
|
||||
become: true
|
||||
roles:
|
||||
|
35
filter_plugins/translate_yavdr.py
Normal file
35
filter_plugins/translate_yavdr.py
Normal file
@ -0,0 +1,35 @@
|
||||
# Copyright (c) 2017 Ansible Project
|
||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
|
||||
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
|
||||
|
||||
ANSIBLE_METADATA = {
|
||||
'metadata_version': '1.1',
|
||||
'status': ['preview'],
|
||||
'supported_by': 'yavdr'
|
||||
}
|
||||
|
||||
import gettext
|
||||
from ansible.errors import AnsibleFilterError
|
||||
from ansible.utils import helpers
|
||||
from ansible.module_utils._text import to_text
|
||||
|
||||
|
||||
def translate_yavdr(text):
|
||||
gettext.textdomain('yavdr')
|
||||
try:
|
||||
return to_text(gettext.gettext(text))
|
||||
except:
|
||||
return to_text(text)
|
||||
|
||||
# ---- Ansible filters ----
|
||||
class FilterModule(object):
|
||||
''' URI filter '''
|
||||
|
||||
def filters(self):
|
||||
return {
|
||||
'translate': translate_yavdr
|
||||
}
|
@ -1,40 +1,67 @@
|
||||
---
|
||||
# file: group_vars/all
|
||||
|
||||
# this is the standard text to put in templates
|
||||
ansible_managed_file: "*** YAVDR: ANSIBLE MANAGED FILE ***"
|
||||
branch: unstable
|
||||
branch: experimental
|
||||
ppa_owner: 'ppa:yavdr'
|
||||
# add the following PPAs
|
||||
repositories:
|
||||
- '{{ ppa_owner }}/main'
|
||||
- '{{ ppa_owner }}/unstable-main'
|
||||
- '{{ ppa_owner }}/{{branch}}-main'
|
||||
- '{{ ppa_owner }}/{{branch}}-vdr'
|
||||
- '{{ ppa_owner }}/{{branch}}-yavdr'
|
||||
- '{{ ppa_owner }}/{{branch}}-kodi'
|
||||
- 'ppa:frodo-vdr/experimental-vdr-yavdr'
|
||||
#- '{{ ppa_owner }}/{{branch}}-yavdr'
|
||||
# properties of the user vdr and vdr-related options
|
||||
# NOTE: user name, uid and confdir must match the values set by the vdr package
|
||||
vdr:
|
||||
user: vdr
|
||||
group: vdr
|
||||
uid: 666
|
||||
gid: 666
|
||||
home: /var/lib/vdr
|
||||
etc_confdir: /etc/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
|
||||
|
||||
# copy channels.conf from a local file
|
||||
# vdr_channels_conf: /path/to/channels.conf
|
||||
|
||||
# download channels.conf from a given url (supports HTTP(S) and FTP)
|
||||
# vdr_channels_conf_url: http://example.com/vdr/channels.conf
|
||||
|
||||
# add the vdr plugins you want to install
|
||||
vdr_plugins:
|
||||
- vdr-plugin-devstatus
|
||||
- vdr-plugin-markad
|
||||
- vdr-plugin-restfulapi
|
||||
- vdr-plugin-softhddevice-vpp
|
||||
- vdr-plugin-dvbapi
|
||||
- vdr-plugin-satip
|
||||
|
||||
# IP (range) filter for vdr and plugins (this must be an array):
|
||||
vdr_allowed_hosts:
|
||||
- 192.168.0.0/16
|
||||
#
|
||||
# hosts and subnets for svdrphosts.conf (overrides vdr_allowed_hosts):
|
||||
vdr_svdrphosts:
|
||||
- 192.168.0.0/16
|
||||
#
|
||||
# hosts and subnets for allowed_hosts.conf of xineliboutput (overrides vdr_allowed_hosts):
|
||||
xineliboutput_allowed_hosts:
|
||||
- 192.168.0.0/16
|
||||
#
|
||||
# hosts and subnets for allowed_hosts.conf of vnsiserver (overrides vdr_allowed_hosts):
|
||||
vnsiserver_allowed_hosts:
|
||||
- 192.168.0.0/16
|
||||
#
|
||||
# hosts and subnets for streamdevhosts.conf (overrides vdr_allowed_hosts):
|
||||
streamdev_server_allowed_hosts:
|
||||
- 192.168.0.0/16
|
||||
# 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
|
||||
video: /srv/video
|
||||
pictures: /srv/picture
|
||||
files: /srv/files
|
||||
backups: /srv/backups
|
||||
@ -50,12 +77,26 @@ extra_packages:
|
||||
- bpython3
|
||||
- htop
|
||||
- tree
|
||||
- vdr-addon-acpiwakeup
|
||||
- vim
|
||||
- w-scan
|
||||
- t2scan
|
||||
- plymouth-theme-yavdr-logo
|
||||
- vdr-addon-lifeguard-ng
|
||||
- vdrpbd
|
||||
- wajig
|
||||
frontend: vdr
|
||||
|
||||
# vdr shutdown command - SHUTDOWNCMD variable in /etc/default/vdr
|
||||
# for standby use "/bin/systemctl suspend"
|
||||
vdr_shutdown_command: poweroff
|
||||
|
||||
#system:
|
||||
# shutdown: poweroff
|
||||
wakeup_method: acpiwakeup
|
||||
grub:
|
||||
timeout: 0
|
||||
boot_options: quiet nosplash
|
||||
boot_options: quiet splash
|
||||
# Serial device to configure for a homebrew receiver.
|
||||
# Choose either ttyS0 (COM1) or ttyS1 (COM2)
|
||||
# Also ensure that the role serial-ir is enabled in yavdr07.yml
|
||||
serial_ir_device: ttyS0
|
||||
|
@ -1,6 +1,9 @@
|
||||
- name: Reconfigure unattended upgrades with dpkg
|
||||
command: '/usr/sbin/dpkg-reconfigure --frontend noninteractive unattended-upgrades'
|
||||
|
||||
- name: Trigger Udev
|
||||
command: 'udevadm trigger '
|
||||
|
||||
- name: Restart Samba
|
||||
systemd:
|
||||
name: smbd.service
|
||||
@ -17,6 +20,13 @@
|
||||
#masked: no
|
||||
register: nfs_reload
|
||||
|
||||
- name: Restart sundtek.service
|
||||
systemd:
|
||||
name: sundtek.service
|
||||
state: restarted
|
||||
enabled: yes
|
||||
masked: no
|
||||
|
||||
- name: Restart VDR
|
||||
systemd:
|
||||
name: vdr.service
|
||||
@ -38,6 +48,15 @@
|
||||
enabled: yes
|
||||
register: vdr_start
|
||||
|
||||
- name: Start yavdr-xorg
|
||||
systemd:
|
||||
daemon_reload: yes
|
||||
name: 'yavdr-xorg'
|
||||
enabled: yes
|
||||
state: started
|
||||
register: yavdr_xorg_start
|
||||
|
||||
|
||||
- name: Stop xlogin
|
||||
systemd:
|
||||
name: xlogin@vdr.service
|
||||
@ -45,8 +64,20 @@
|
||||
enabled: yes
|
||||
register: xlogin_stop
|
||||
|
||||
- name: Start xlogin
|
||||
systemd:
|
||||
daemon_reload: yes
|
||||
name: 'xlogin@{{ vdr.user }}'
|
||||
enabled: yes
|
||||
state: started
|
||||
register: xlogin_start
|
||||
|
||||
- name: Stop x
|
||||
systemd:
|
||||
name: x@vt7.service
|
||||
state: stopped
|
||||
register: x_stop
|
||||
|
||||
- name: reboot required
|
||||
debug:
|
||||
msg: PLEASE REBOOT YOUR SYSTEM.
|
||||
|
17
install-yavdr-headless.sh
Executable file
17
install-yavdr-headless.sh
Executable file
@ -0,0 +1,17 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
if (( $EUID != 0 )); then
|
||||
echo "This script must be run using sudo -H or as root"
|
||||
exit
|
||||
fi
|
||||
|
||||
# update packages
|
||||
apt update
|
||||
apt -y install software-properties-common
|
||||
add-apt-repository -y ppa:ansible/ansible-2.7
|
||||
|
||||
# install required packages
|
||||
apt-get -y install --no-install-recommends ansible python-jmespath
|
||||
|
||||
# TODO: run ansible on local host
|
||||
ansible-playbook yavdr07-headless.yml -b -i 'localhost_inventory' --connection=local --tags="all"
|
@ -1,16 +1,17 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
if (( $EUID != 0 )); then
|
||||
echo "This script must be run using sudo or as root"
|
||||
echo "This script must be run using sudo -H 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
|
||||
apt update
|
||||
apt -y install software-properties-common
|
||||
add-apt-repository -y ppa:ansible/ansible-2.7
|
||||
|
||||
# install required packages
|
||||
apt-get -y install ansible
|
||||
apt-get -y install --no-install-recommends ansible python-jmespath
|
||||
|
||||
# TODO: run ansible on local host
|
||||
ansible-playbook yavdr07.yml -b -i 'localhost_inventory' --connection=local --tags=install
|
||||
ansible-playbook yavdr07.yml -b -i 'localhost_inventory' --connection=local --tags="all"
|
||||
|
174
library/dpkg_reconfigure
Normal file
174
library/dpkg_reconfigure
Normal file
@ -0,0 +1,174 @@
|
||||
#!/usr/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
Ansible module for reconfiguring debian packages.
|
||||
(c) 2013, Sebastien Bocahu <sebastien.bocahu@nuxit.com>
|
||||
|
||||
This file is part of Ansible
|
||||
|
||||
Ansible is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Ansible is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Ansible. If not, see <http://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: dpkg_reconfigure
|
||||
short_description: Reconfigure a Debian package.
|
||||
description:
|
||||
- Reconfigure a Debian package using dpkg-reconfigure.
|
||||
version_added: "1.2"
|
||||
notes:
|
||||
- A number of questions has to be answered (depending on the package).
|
||||
Use 'DEBIAN_FRONTED=editor dpkg-reconfigure $pkg' for finding them.
|
||||
options:
|
||||
pkg:
|
||||
description:
|
||||
- Package to configure.
|
||||
required: true
|
||||
default: null
|
||||
aliases: []
|
||||
answers:
|
||||
description:
|
||||
- Debconf configuration answer(s)/question(s).
|
||||
required: true
|
||||
default: null
|
||||
aliases: []
|
||||
author: Sebastien Bocahu
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
# Set default locale to fr_FR.UTF-8, and generate en_US.UTF-8 as well:
|
||||
dpkg_reconfigure:
|
||||
pkg: locales
|
||||
answers:
|
||||
locales/default_environment_locale: fr_FR.UTF-8
|
||||
locales/locales_to_be_generated: en_US.UTF-8 UTF-8, fr_FR.UTF-8 UTF-8
|
||||
|
||||
# Reconfigure roundcube, using configuration answers stored in a file:
|
||||
dpkg_reconfigure: pkg=roundcube answers='$FILE(/path/dpkg-reconfigure/roundcube)'"
|
||||
'''
|
||||
|
||||
import sys
|
||||
import os
|
||||
import pwd
|
||||
import os.path
|
||||
import re
|
||||
import tempfile
|
||||
|
||||
def get_selections(module, pkg):
|
||||
cmd = [module.get_bin_path('debconf-show', True)]
|
||||
cmd.append(' %s' % pkg)
|
||||
rc, out, err = module.run_command(' '.join(cmd))
|
||||
|
||||
if rc == 0:
|
||||
selections = {}
|
||||
for answer in out.split('\n'):
|
||||
item = re.search('^[* ] ([^:]+): (.*)$', answer)
|
||||
if item:
|
||||
value = item.group(2).strip()
|
||||
if value == 'true':
|
||||
value = 'yes'
|
||||
elif value == 'false':
|
||||
value = 'no'
|
||||
selections[ item.group(1).strip() ] = value
|
||||
return selections
|
||||
else:
|
||||
module.fail_json(msg=err)
|
||||
|
||||
|
||||
def dpkg_reconfigure(module, pkg, wanted_config):
|
||||
editor_script = [ '#!/bin/sh', 'sed -i "$1" -f - <<EOF' ]
|
||||
for question in wanted_config:
|
||||
e_question = re.sub(r'([\\/&])', r'\\\1', question)
|
||||
e_answer = re.sub(r'([\\/&])', r'\\\1', wanted_config[question])
|
||||
editor_script.append('s/^\\(%s\\)\\s*=.*/\\1="%s"/' % (e_question, e_answer))
|
||||
editor_script.append('EOF')
|
||||
|
||||
outfd, outsock_path = tempfile.mkstemp()
|
||||
tmp = os.fdopen(outfd,'w')
|
||||
tmp.write('\n'.join(editor_script))
|
||||
tmp.close()
|
||||
os.chmod(outsock_path, stat.S_IEXEC)
|
||||
|
||||
cmd = [ 'EDITOR=%s DEBIAN_FRONTEND=editor' % outsock_path ]
|
||||
cmd.append(module.get_bin_path('dpkg-reconfigure', True))
|
||||
cmd.append(pkg)
|
||||
rc, out, err = module.run_command(' '.join(cmd), use_unsafe_shell=True)
|
||||
os.unlink(outsock_path)
|
||||
|
||||
if rc == 0:
|
||||
return True, err
|
||||
else:
|
||||
return False, err
|
||||
|
||||
|
||||
def enforce_state(module, params):
|
||||
|
||||
pkg = params["pkg"]
|
||||
answers = params["answers"]
|
||||
|
||||
wanted_config = {}
|
||||
|
||||
if type(answers) is dict:
|
||||
wanted_config = answers
|
||||
else:
|
||||
for answer in answers.split('\n'):
|
||||
item = re.findall(r"[^\s]+", answer)
|
||||
if len(item) > 1:
|
||||
wanted_config[ item[0].strip() ] = ' '.join(item[1:])
|
||||
elif len(item) == 1:
|
||||
wanted_config[ item[0].strip() ] = ''
|
||||
|
||||
for key in wanted_config:
|
||||
value = wanted_config[key]
|
||||
if isinstance(value, bool):
|
||||
if value:
|
||||
wanted_config[key] = 'yes'
|
||||
else:
|
||||
wanted_config[key] = 'no'
|
||||
|
||||
current_config = get_selections(module, params["pkg"])
|
||||
|
||||
already_configured = 1
|
||||
for answer in wanted_config:
|
||||
if not answer in current_config or current_config[answer] != wanted_config[answer]:
|
||||
already_configured = 0
|
||||
|
||||
if already_configured:
|
||||
module.exit_json(changed=False, msg="Already configured")
|
||||
else:
|
||||
rc, msg = dpkg_reconfigure(module, pkg, wanted_config)
|
||||
if not rc:
|
||||
module.fail_json(msg=msg)
|
||||
|
||||
params['changed'] = True
|
||||
params['msg'] = msg
|
||||
return params
|
||||
|
||||
|
||||
def main():
|
||||
|
||||
module = AnsibleModule(
|
||||
argument_spec = dict(
|
||||
pkg = dict(required=True),
|
||||
answers = dict(required=True),
|
||||
)
|
||||
)
|
||||
|
||||
results = enforce_state(module, module.params)
|
||||
module.exit_json(**results)
|
||||
|
||||
# this is magic, see lib/ansible/module_common.py
|
||||
#<<INCLUDE_ANSIBLE_MODULE_COMMON>>
|
||||
main()
|
@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env/python
|
||||
#!/usr/bin/env python
|
||||
# This Module collects the vendor- and device ids for USB- and PCI(e)-devices and currently loaded kernel modules.
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
@ -31,6 +31,12 @@ DOCUMENTATION = '''
|
||||
default: True
|
||||
description:
|
||||
- return a list of devices of the pci gpu class (0x030000)
|
||||
|
||||
acpi_power_modes:
|
||||
required: False
|
||||
default: True
|
||||
description:
|
||||
- return a list of supported acpi power saving modes
|
||||
notes:
|
||||
- requres python-pyusb and python-kmodpy
|
||||
requirements: [ ]
|
||||
@ -43,13 +49,14 @@ EXAMPLES = '''
|
||||
usb: True
|
||||
pci: True
|
||||
modules: True
|
||||
acpi_power_modes: True
|
||||
- debug:
|
||||
var: usb
|
||||
- debug
|
||||
- debug:
|
||||
var: pci
|
||||
- debug
|
||||
- debug:
|
||||
var: modules
|
||||
- debug
|
||||
- debug:
|
||||
var: gpus
|
||||
'''
|
||||
|
||||
@ -59,6 +66,7 @@ import os
|
||||
import sys
|
||||
import usb.core
|
||||
from collections import namedtuple
|
||||
from itertools import chain
|
||||
|
||||
import kmodpy
|
||||
from ansible.module_utils.basic import *
|
||||
@ -74,7 +82,7 @@ vendor_dict = {
|
||||
}
|
||||
|
||||
def get_pci_devices():
|
||||
for device in glob.glob('/sys/devices/pci*/*:*:*/*:*:*/'):
|
||||
for device in chain(glob.glob('/sys/devices/pci*/*:*:*/'), glob.glob('/sys/devices/pci*/*:*:*/*:*:*/')):
|
||||
try:
|
||||
with open(os.path.join(device, 'device')) as d:
|
||||
product_id = int(d.read().strip(), 16)
|
||||
@ -97,11 +105,21 @@ def format_gpu_device_list(iterator):
|
||||
"VendorID": d.idVendor, "ProductID": d.idProduct}
|
||||
return [entry for entry in get_entries(iterator)]
|
||||
|
||||
def list_acpi_power_modes():
|
||||
acpi_power_modes = []
|
||||
try:
|
||||
with open('/sys/power/state') as f:
|
||||
acpi_power_modes = [l for l in f.readline().split()]
|
||||
except IOError:
|
||||
pass
|
||||
return acpi_power_modes
|
||||
|
||||
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),
|
||||
'acpi_power_modes': dict(default=True, type='bool', required=False),
|
||||
}
|
||||
|
||||
|
||||
@ -111,24 +129,42 @@ def main():
|
||||
collect_pci = module.params['pci']
|
||||
collect_modules = module.params['modules']
|
||||
collect_gpus = module.params['gpus']
|
||||
collect_acpi_power_modes = module.params['acpi_power_modes']
|
||||
|
||||
usb_devices = []
|
||||
pci_devices = []
|
||||
modules = []
|
||||
gpus = []
|
||||
nvidia_detected = False
|
||||
intel_detected = False
|
||||
amd_detected = False
|
||||
virtualbox_detected = False
|
||||
acpi_power_modes = []
|
||||
|
||||
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}
|
||||
nvidia_detected = any((True for gpu in gpus if gpu['VendorName'] == 'nvidia'))
|
||||
intel_detected = any((True for gpu in gpus if gpu['VendorName'] == 'intel'))
|
||||
amd_detected = any((True for gpu in gpus if gpu['VendorName'] == 'amd'))
|
||||
virtualbox_detected = any((True for gpu in gpus if gpu['VendorName'] == 'virtualbox'))
|
||||
|
||||
if collect_acpi_power_modes:
|
||||
acpi_power_modes = list_acpi_power_modes()
|
||||
|
||||
data = {'usb': usb_devices, 'pci': pci_devices, 'modules': modules, 'gpus': gpus,
|
||||
'acpi_power_modes': acpi_power_modes, 'nvidia_detected': nvidia_detected,
|
||||
'intel_detected': intel_detected, 'amd_detected': amd_detected,
|
||||
'virtualbox_detected': virtualbox_detected}
|
||||
module.exit_json(changed=False, ansible_facts=data, msg=data)
|
||||
|
||||
|
||||
|
69
library/pci_facts.py
Executable file
69
library/pci_facts.py
Executable file
@ -0,0 +1,69 @@
|
||||
#!/usr/bin/env python
|
||||
# This module parses the output of lspci for detailed information about available (sub) devices.
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: pci_facts
|
||||
short_description: parses lspci output for detailed (sub) devices data
|
||||
description:
|
||||
- This module parses the output of lspci for detailed information about available (sub) devices.
|
||||
- returns a list with a dict for each device
|
||||
|
||||
notes:
|
||||
- requires lspci (package pciutils)
|
||||
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
- name: get detailled pci device infos
|
||||
pci_facts:
|
||||
|
||||
- debug:
|
||||
var: pci_devices
|
||||
'''
|
||||
|
||||
|
||||
import argparse
|
||||
import shlex
|
||||
import subprocess
|
||||
from collections import namedtuple
|
||||
|
||||
from ansible.module_utils.basic import *
|
||||
|
||||
def convert2hex(arg):
|
||||
arg = arg.strip('"')
|
||||
if arg:
|
||||
return int(arg, 16)
|
||||
else:
|
||||
return None
|
||||
|
||||
def parse_lspci_data():
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('-r', '--revision', help='revision', type=convert2hex)
|
||||
parser.add_argument('-p', '--progif', help='proginf', type=convert2hex)
|
||||
parser.add_argument('slot')
|
||||
parser.add_argument('device_class', type=convert2hex)
|
||||
parser.add_argument('vendor_id', type=convert2hex)
|
||||
parser.add_argument('device_id', type=convert2hex)
|
||||
parser.add_argument('sub_vendor_id', type=convert2hex)
|
||||
parser.add_argument('sub_device_id', type=convert2hex)
|
||||
parser.add_argument('other', nargs='*', default=[])
|
||||
|
||||
devices = []
|
||||
for line in subprocess.check_output(['lspci', '-nm'], universal_newlines=True).splitlines():
|
||||
args = parser.parse_args(args=shlex.split(line))
|
||||
devices.append(vars(args))
|
||||
return devices
|
||||
|
||||
|
||||
def main():
|
||||
arg_specs = {}
|
||||
module = AnsibleModule(argument_spec=arg_specs, supports_check_mode=True,)
|
||||
try:
|
||||
pci_devices = parse_lspci_data()
|
||||
except:
|
||||
module.fail_json(msg="Something fatal happened")
|
||||
data = {'pci_devices': pci_devices}
|
||||
module.exit_json(changed=False, ansible_facts=data, msg=data)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
83
library/rmmod.py
Normal file
83
library/rmmod.py
Normal file
@ -0,0 +1,83 @@
|
||||
#!/usr/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright: (c) 2019, Alexander Grothe <seahawk1986@gmx.de>
|
||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
|
||||
from __future__ import absolute_import, division, print_function
|
||||
__metaclass__ = type
|
||||
import traceback
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils._text import to_native
|
||||
|
||||
|
||||
ANSIBLE_METADATA = {'metadata_version': '1.1',
|
||||
'status': ['preview'],
|
||||
'supported_by': 'community'}
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: rmmod
|
||||
short_description: unload kernel modules with rmmod
|
||||
version_added: 2.7
|
||||
author:
|
||||
- Alexander Grothe
|
||||
description:
|
||||
- Unload kernel modules with rmmod.
|
||||
- Builtin kernel modules can't be removed (will do nothing in this case).
|
||||
options:
|
||||
name:
|
||||
required: true
|
||||
description:
|
||||
- Name of kernel module to remove.
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
- name: Unload nouveau module
|
||||
rmmod:
|
||||
name: nouveau
|
||||
'''
|
||||
|
||||
|
||||
def main():
|
||||
module = AnsibleModule(
|
||||
argument_spec=dict(
|
||||
name=dict(type='str', required=True),
|
||||
),
|
||||
supports_check_mode=True,
|
||||
)
|
||||
|
||||
name = module.params['name']
|
||||
|
||||
# FIXME: Adding all parameters as result values is useless
|
||||
result = dict(
|
||||
changed=False,
|
||||
name=name,
|
||||
)
|
||||
|
||||
# Check if module is loaded
|
||||
try:
|
||||
is_loaded = False
|
||||
with open('/proc/modules') as modules:
|
||||
module_name = name.replace('-', '_') + ' '
|
||||
for line in modules:
|
||||
if line.startswith(module_name):
|
||||
is_loaded = True
|
||||
break
|
||||
except IOError as e:
|
||||
module.fail_json(msg=to_native(e), exception=traceback.format_exc(), **result)
|
||||
|
||||
# remove module if it is loaded
|
||||
if is_loaded:
|
||||
if not module.check_mode:
|
||||
rc, out, err = module.run_command([module.get_bin_path('rmmod', True), name])
|
||||
if rc != 0:
|
||||
module.fail_json(msg=err, rc=rc, stdout=out, stderr=err, **result)
|
||||
result['changed'] = True
|
||||
|
||||
module.exit_json(**result)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
@ -3,29 +3,40 @@ from __future__ import print_function
|
||||
import ast
|
||||
import binascii
|
||||
import csv
|
||||
import os
|
||||
import re
|
||||
import subprocess
|
||||
from collections import namedtuple
|
||||
from glob import glob
|
||||
|
||||
from ansible.module_utils.basic import *
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
|
||||
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.
|
||||
- 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, the dictionary
|
||||
"xorg" with a recommendation for the primary and secondary
|
||||
output and a "drm" dictionary whose "primary" key associates
|
||||
the primary device name of the drm subsystem with the one from
|
||||
the xrandr output by comparing the edid data and a list of
|
||||
"ignored_devices". Note that the proprietary nvidia driver
|
||||
doesn't support KMS/drm, so in this case the dictionary is
|
||||
always empty.
|
||||
options:
|
||||
display:
|
||||
required: False
|
||||
default: ":0"
|
||||
description:
|
||||
- the DISPLAY variable to use when calling xrandr
|
||||
preferred_outpus:
|
||||
preferred_outputs:
|
||||
required: False
|
||||
default: ["HDMI", "DP", "DVI", "VGA", "TV": 0]
|
||||
default: ["HDMI", "DP", "eDP", "DVI", "VGA", "TV", "Virtual"]
|
||||
description:
|
||||
- ranking of the preferred display connectors
|
||||
preferred_refreshrates:
|
||||
@ -43,6 +54,7 @@ options:
|
||||
default: True
|
||||
description:
|
||||
- write edid data to /etc/X11/edid.{connector}.bin
|
||||
- the dictionary "drm" can only be filled with data if write_edids is enabled
|
||||
'''
|
||||
EXAMPLES = '''
|
||||
- name: "collect facts for connected displays"
|
||||
@ -54,12 +66,15 @@ EXAMPLES = '''
|
||||
|
||||
- debug:
|
||||
var: xorg
|
||||
|
||||
- debug:
|
||||
var: drm
|
||||
'''
|
||||
|
||||
ARG_SPECS = {
|
||||
'display': dict(default=":0", type='str', required=False),
|
||||
'preferred_outputs': dict(
|
||||
default=["HDMI", "DP", "DVI", "VGA", "TV"], type='list', required=False),
|
||||
default=["HDMI", "DP", "eDP", "DVI", "VGA", "TV", "Virtual"], type='list', required=False),
|
||||
'preferred_refreshrates': dict(
|
||||
default=[50, 60, 75, 30, 25], type='list', required=False),
|
||||
'preferred_resolutions': dict(
|
||||
@ -67,21 +82,23 @@ ARG_SPECS = {
|
||||
"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+:)(?:.*)")
|
||||
SCREEN_REGEX = re.compile(r"^(?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,}).*")
|
||||
r"^(?P<connector>.*-?\d+)\s(?P<connection_state>connected|disconnected)\s(?P<primary>primary)?")
|
||||
MODE_REGEX = re.compile(r"^\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)
|
||||
@ -93,10 +110,12 @@ def check_for_connection(line):
|
||||
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
|
||||
@ -112,12 +131,13 @@ def sort_mode(mode):
|
||||
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'))
|
||||
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 = {}
|
||||
@ -135,7 +155,7 @@ def parse_xrandr_verbose(iterator):
|
||||
'preferred': '',
|
||||
'current': '',
|
||||
'auto': '',
|
||||
}
|
||||
}
|
||||
elif is_connected and 'EDID:' in line:
|
||||
edid_str = ""
|
||||
outer_indentation = get_indentation(line)
|
||||
@ -146,7 +166,7 @@ def parse_xrandr_verbose(iterator):
|
||||
else:
|
||||
break
|
||||
xorg[screen][connector]['EDID'] = edid_str
|
||||
elif is_connected and "MHz" in line and not "Interlace" in line:
|
||||
elif is_connected and "MHz" in line and "Interlace" not in line:
|
||||
match = re.match(MODE_REGEX, line)
|
||||
if match:
|
||||
match = match.groupdict()
|
||||
@ -171,32 +191,64 @@ def parse_xrandr_verbose(iterator):
|
||||
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
|
||||
modelines = []
|
||||
try:
|
||||
data = subprocess.check_output("parse-edid < {}".format(edid),
|
||||
shell=True, universal_newlines=True)
|
||||
except subprocess.CalledProcessError:
|
||||
pass
|
||||
else:
|
||||
for line in data.splitlines():
|
||||
line = line.strip()
|
||||
if "VendorName" in line:
|
||||
vendor = line.split('"')[1]
|
||||
if "ModelName" in line:
|
||||
model = line.split('"')[1]
|
||||
if "Modeline" in line:
|
||||
print(line)
|
||||
_, _, line = line.split('"', 2)
|
||||
if not line:
|
||||
print("no timing information")
|
||||
continue
|
||||
try:
|
||||
FF, H1, H2, H3, H4, V1, V2, V3, V4, FLAGS = line.split(None, 9)
|
||||
except ValueError:
|
||||
print("invalid timing information")
|
||||
continue
|
||||
print(FF, H1, H2, H3, H4, V1, V2, V3, V4, FLAGS)
|
||||
refresh = round(float(FF) * 1E6 / (float(H4) * float(V4)))
|
||||
interlaced = "interlaced" in FLAGS
|
||||
if interlaced:
|
||||
refresh /= 2
|
||||
refresh = int(refresh)
|
||||
modeline_name = '"{}x{}_{}{}"'.format(H1, V1, refresh, "i" if interlaced else '')
|
||||
modelines.append(" ".join(("Modeline", modeline_name,
|
||||
FF, H1, H2, H3, H4, V1, V2, V3, V4, FLAGS)))
|
||||
return vendor, model, modelines
|
||||
|
||||
|
||||
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]+)'
|
||||
))
|
||||
r'(?P<domain>[0-9a-fA-F]+)'
|
||||
r':'
|
||||
r'(?P<bus>[0-9a-fA-F]+)'
|
||||
r':'
|
||||
r'(?P<device>[0-9a-fA-F]+)'
|
||||
r'\.'
|
||||
r'(?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)
|
||||
data = subprocess.check_output(["nvidia-smi", "--query-gpu=name,pci.bus_id",
|
||||
"--format=csv", "-i0"], universal_newlines=True)
|
||||
except subprocess.CalledProcessError:
|
||||
pass
|
||||
except OSError:
|
||||
# nvidia-smi is not installed
|
||||
pass
|
||||
else:
|
||||
for row in csv.DictReader(data.splitlines(), delimiter=',', skipinitialspace=True):
|
||||
name = row['name']
|
||||
@ -210,7 +262,77 @@ def collect_nvidia_data():
|
||||
raise ValueError
|
||||
|
||||
|
||||
def find_drm_connectors(connections):
|
||||
"""
|
||||
returns a dict with the following schema (secondary may be empty):
|
||||
{
|
||||
'primary': {
|
||||
'edid': 'edid.HDMI-1.bin',
|
||||
'drm_connector': 'HDMI-A-1',
|
||||
'xrandr_connector': 'HDMI-1',
|
||||
},
|
||||
'secondary': {
|
||||
'edid': 'edid.eDP-1.bin',
|
||||
'drm_connector': 'eDP-1',
|
||||
'xrandr_connector': 'eDP-1',
|
||||
}
|
||||
'ignored_outputs': ['HDMI-A-2', 'DP-1']
|
||||
}
|
||||
"""
|
||||
STATUS_GLOB = '/sys/class/drm/card0*/status'
|
||||
CONNECTOR_RE = re.compile('card0-(?P<connector>[^/]+)/status')
|
||||
|
||||
def read_edid_bytes(edid_file):
|
||||
edid_bytes = b''
|
||||
try:
|
||||
with open(edid_file, 'rb') as f:
|
||||
edid_bytes = f.read()
|
||||
except IOError:
|
||||
pass
|
||||
return edid_bytes
|
||||
|
||||
xrandr_edid_bytes = read_edid_bytes(connections.get('primary', {}).get('edid', ""))
|
||||
secondary_xrandr_edid_bytes = read_edid_bytes(connections.get('secondary', {}).get('edid', ''))
|
||||
|
||||
drm = {'primary': {}, 'secondary': {}, 'ignored_outputs': []}
|
||||
for status_p in glob(STATUS_GLOB):
|
||||
match = re.search(CONNECTOR_RE, status_p)
|
||||
if match:
|
||||
drm_connector = match.group('connector')
|
||||
else:
|
||||
continue
|
||||
|
||||
try:
|
||||
with open(status_p) as f:
|
||||
connected = f.read().strip() == 'connected'
|
||||
except IOError:
|
||||
continue
|
||||
|
||||
if connected:
|
||||
edid = read_edid_bytes(os.path.join(
|
||||
os.path.dirname(status_p), 'edid'))
|
||||
if edid:
|
||||
if edid == xrandr_edid_bytes:
|
||||
drm['primary'] = {
|
||||
'edid': os.path.basename(connections['primary'].get('edid', "")),
|
||||
'drm_connector': drm_connector,
|
||||
'xrandr_connector': connections['primary'].get('connector',''),
|
||||
}
|
||||
continue
|
||||
if secondary_xrandr_edid_bytes:
|
||||
drm['secondary'] = {
|
||||
'edid': os.path.basename(connections.get('secondary').get('edid', '')),
|
||||
'drm_connector': drm_connector,
|
||||
'xrandr_connector': connections['secondary'].get('connector',''),
|
||||
}
|
||||
continue
|
||||
drm['ignored_outputs'].append(drm_connector)
|
||||
return drm
|
||||
|
||||
|
||||
def output_data(data, write_edids=True):
|
||||
result = {}
|
||||
drm = {}
|
||||
if data:
|
||||
modes = []
|
||||
for _, screen_data in data.items():
|
||||
@ -222,14 +344,13 @@ def output_data(data, write_edids=True):
|
||||
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):
|
||||
def create_entry(my_dict, name, connector, resolution, refreshrate, vendor, model, modelines):
|
||||
my_dict[name] = {
|
||||
'connector': connector,
|
||||
'resolution': resolution,
|
||||
@ -238,29 +359,40 @@ def output_data(data, write_edids=True):
|
||||
'mode': "{}_{}".format(resolution, refreshrate),
|
||||
'vendor': vendor,
|
||||
'model': model,
|
||||
'modelines': modelines,
|
||||
}
|
||||
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)
|
||||
connector_0_edid = '/etc/X11/edid.{}.bin'.format(connector_0)
|
||||
vendor_0, model_0, modelines_0 = parse_edid_data(connector_0_edid)
|
||||
create_entry(result, 'primary', connector_0, resolution_0,
|
||||
refreshrate_0, vendor_0, model_0, modelines_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)
|
||||
connector_1_edid = '/etc/X11/edid.{}.bin'.format(connector_1)
|
||||
vendor_1, model_1, modelines_1 = parse_edid_data(connector_1_edid)
|
||||
create_entry(result, 'secondary', connector_1, resolution_1,
|
||||
refreshrate_1, vendor_1, model_1, modelines_1)
|
||||
|
||||
if write_edids:
|
||||
drm = find_drm_connectors(result)
|
||||
|
||||
|
||||
module.exit_json(changed=True if write_edids else False,
|
||||
ansible_facts={'xrandr': data, 'xorg': result, 'drm': drm})
|
||||
|
||||
#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()
|
||||
d = subprocess.check_output(['xrandr', '-d', module.params['display'], '--verbose'],
|
||||
universal_newlines=True).splitlines()
|
||||
except subprocess.CalledProcessError:
|
||||
xorg_data = {}
|
||||
else:
|
||||
|
48
plugins/callbacks/auto_tags.py
Normal file
48
plugins/callbacks/auto_tags.py
Normal file
@ -0,0 +1,48 @@
|
||||
"""
|
||||
This module implements an Ansible plugin that is triggered at the start of a playbook.
|
||||
|
||||
The plugin dynamically generates a tag for each role. Each tag has the same name as its role.
|
||||
The advantage of this is that it saves you some boilerplate, because you don't have to wrap
|
||||
all tasks of a role in an additional block and assign a tag to that.
|
||||
Additionally, it works automatically when you add new roles to your playbook.
|
||||
|
||||
Usage is exactly the same as without this plugin:
|
||||
|
||||
ansible-playbook --tags=some_tag provision.yml
|
||||
|
||||
Here, the "some_tag" tag was generated dynamically (assuming there is a "some_tag" role).
|
||||
|
||||
Installation:
|
||||
1. Place this file in `plugins/callbacks/auto_tags.py` (relative to your playbook root)
|
||||
2. Add the following two lines to your `ansible.cfg` file:
|
||||
|
||||
callback_plugins = plugins/callbacks
|
||||
callback_whitelist = auto_tags
|
||||
"""
|
||||
from __future__ import print_function
|
||||
from ansible.plugins.callback import CallbackBase
|
||||
|
||||
|
||||
class CallbackModule(CallbackBase):
|
||||
"""
|
||||
Ansible supports several types of plugins. We are using the *callback* type here, since
|
||||
it seemed the best choice for our use case, because it allows you to hook into the start
|
||||
of a playbook.
|
||||
"""
|
||||
def v2_playbook_on_start(self, playbook):
|
||||
"""
|
||||
Dynamically add a tag of the same name to each role.
|
||||
Note: Plays, roles, task_blocks and tasks can have tags.
|
||||
"""
|
||||
plays = playbook.get_plays()
|
||||
|
||||
# Note: Although identical roles are shared between plays we cannot deduplicate them,
|
||||
# since Ansible treats them as different objects internally
|
||||
roles = [role for play in plays for role in play.get_roles()]
|
||||
|
||||
# Note: Tags for roles are set dynamically in `_load_role_data` instead of in __init__
|
||||
# I don't know why they do that.
|
||||
for role in roles:
|
||||
role_name = role._role_name
|
||||
if role_name not in role.tags:
|
||||
role.tags += [role_name]
|
4
roles/autoinstall-atric-usb/meta/main.yml
Normal file
4
roles/autoinstall-atric-usb/meta/main.yml
Normal file
@ -0,0 +1,4 @@
|
||||
---
|
||||
dependencies:
|
||||
- { role: collect-facts }
|
||||
- { role: yavdr-remote }
|
35
roles/autoinstall-atric-usb/tasks/main.yml
Normal file
35
roles/autoinstall-atric-usb/tasks/main.yml
Normal file
@ -0,0 +1,35 @@
|
||||
---
|
||||
# file roles/autoinstall-atric-usb/tasks/main.yml
|
||||
|
||||
- name: install and configure Atric IR-WakeupUSB
|
||||
block:
|
||||
- name: apt | install lirc-drv-irman
|
||||
apt:
|
||||
name: lirc-drv-irman
|
||||
state: present
|
||||
tags:
|
||||
- packages
|
||||
|
||||
- name: write lirc configuration
|
||||
template:
|
||||
src: templates/lirc_options.conf.j2
|
||||
dest: /etc/lirc/lirc_options.conf
|
||||
tags:
|
||||
- config
|
||||
- systemd
|
||||
|
||||
- name: enable lircd, eventlircd, lircd2uinput
|
||||
systemd:
|
||||
name: '{{ item }}'
|
||||
enabled: yes
|
||||
state: started
|
||||
masked: no
|
||||
daemon_reload: yes
|
||||
with_items:
|
||||
- eventlircd.service
|
||||
- lircd2uinput.service
|
||||
- lircd.service
|
||||
tags:
|
||||
- systemd
|
||||
|
||||
when: '"04d8:f844" in usb'
|
21
roles/autoinstall-atric-usb/templates/lirc_options.conf.j2
Normal file
21
roles/autoinstall-atric-usb/templates/lirc_options.conf.j2
Normal file
@ -0,0 +1,21 @@
|
||||
{{ ansible_managed | comment }}
|
||||
|
||||
[lircd]
|
||||
nodaemon = False
|
||||
driver = irman
|
||||
device = /dev/irman
|
||||
output = /var/run/lirc/lircd0
|
||||
pidfile = /var/run/lirc/lircd0.pid
|
||||
plugindir = /usr/lib/x86_64-linux-gnu/lirc/plugins
|
||||
permission = 666
|
||||
allow-simulate = No
|
||||
repeat-max = 600
|
||||
#loglevel = 6
|
||||
#release = true
|
||||
#release_suffix = _EVUP
|
||||
#logfile = ...
|
||||
#driver-options = ...
|
||||
|
||||
[lircmd]
|
||||
uinput = False
|
||||
nodaemon = False
|
3
roles/autoinstall-dvbhddevice/meta/main.yml
Normal file
3
roles/autoinstall-dvbhddevice/meta/main.yml
Normal file
@ -0,0 +1,3 @@
|
||||
---
|
||||
dependencies:
|
||||
- { role: collect-facts }
|
@ -3,6 +3,8 @@
|
||||
|
||||
- name: apt | install vdr-plugin-dvbhddevice if connected
|
||||
apt:
|
||||
name: vdr-plugin-dvbhddevice
|
||||
name:
|
||||
- vdr-plugin-dvbhddevice
|
||||
- yavdr-firmware
|
||||
when: '"13c2:300a" in pci or "13c2:300b" in pci'
|
||||
notify: [ 'Restart VDR' ]
|
||||
|
3
roles/autoinstall-dvbsddevice/meta/main.yml
Normal file
3
roles/autoinstall-dvbsddevice/meta/main.yml
Normal file
@ -0,0 +1,3 @@
|
||||
---
|
||||
dependencies:
|
||||
- { role: collect-facts }
|
@ -1,8 +1,12 @@
|
||||
---
|
||||
# file roles/autoinstall-dvbsddevice/tasks/main.yml
|
||||
|
||||
# TODO: install firmware
|
||||
|
||||
- name: apt | install vdr-plugin-dvbsddevice if module is loaded
|
||||
apt:
|
||||
name: vdr-plugin-dvbsddevice
|
||||
name:
|
||||
- vdr-plugin-dvbsddevice
|
||||
- yavdr-firmware
|
||||
when: '"dvb_ttpci" in modules'
|
||||
notify: [ 'Restart VDR' ]
|
||||
|
3
roles/autoinstall-dvbsky-firmware/defaults/main.yml
Normal file
3
roles/autoinstall-dvbsky-firmware/defaults/main.yml
Normal file
@ -0,0 +1,3 @@
|
||||
---
|
||||
# file roles/autoinstall-dvbsky-firmware
|
||||
dvbsky_firmware_files: []
|
3
roles/autoinstall-dvbsky-firmware/meta/main.yml
Normal file
3
roles/autoinstall-dvbsky-firmware/meta/main.yml
Normal file
@ -0,0 +1,3 @@
|
||||
---
|
||||
dependencies:
|
||||
- { role: collect-facts }
|
42
roles/autoinstall-dvbsky-firmware/tasks/main.yml
Normal file
42
roles/autoinstall-dvbsky-firmware/tasks/main.yml
Normal file
@ -0,0 +1,42 @@
|
||||
---
|
||||
# file roles/autoinstall-dvbsky-firmware/tasks/main.yml
|
||||
|
||||
- name: determine needed firmware files by device ids
|
||||
block:
|
||||
- name: add firmware files for DVBSky if a card has been detected
|
||||
set_fact:
|
||||
dvbsky_firmware_files: ['dvb-demod-m88ds3103.fw', 'dvb-demod-m88rs6000.fw', 'dvb-tuner-si2158-a20-01.fw', 'dvb-demod-si2168-a20-01.fw', 'dvb-demod-si2168-a30-01.fw', 'dvb-demod-si2168-b40-01.fw', 'dvb-fe-ds300x.fw', 'dvb-fe-ds3103.fw', 'dvb-fe-rs6000.fw']
|
||||
when:
|
||||
- '"1ade:3038" in pci'
|
||||
when:
|
||||
- not dvbsky_firmware_files
|
||||
|
||||
- name: Download firmware for DVBSky cards and copy required files to /lib/firmware
|
||||
block:
|
||||
# download and extract firmware
|
||||
- unarchive:
|
||||
src: http://www.dvbsky.net/download/linux/dvbsky-firmware.tar.gz
|
||||
dest: /tmp/
|
||||
remote_src: yes
|
||||
|
||||
# copy firmware file
|
||||
- copy:
|
||||
src: "/tmp/dvbsky-firmware/{{ item }}"
|
||||
dest: /lib/firmware/
|
||||
owner: root
|
||||
group: root
|
||||
mode: 0644
|
||||
with_items: '{{ dvbsky_firmware_files }}'
|
||||
notify: ['Trigger Udev']
|
||||
|
||||
# Remove temporary files
|
||||
- file:
|
||||
path: /tmp/dvbsky-firmware
|
||||
state: absent
|
||||
when:
|
||||
- dvbsky_firmware_files is defined
|
||||
- dvbsky_firmware_files | bool
|
||||
tags:
|
||||
- install
|
||||
- autodetect
|
||||
- dvbsky
|
3
roles/autoinstall-firmware/meta/main.yml
Normal file
3
roles/autoinstall-firmware/meta/main.yml
Normal file
@ -0,0 +1,3 @@
|
||||
---
|
||||
dependencies:
|
||||
- { role: collect-facts }
|
33
roles/autoinstall-firmware/tasks/main.yml
Normal file
33
roles/autoinstall-firmware/tasks/main.yml
Normal file
@ -0,0 +1,33 @@
|
||||
---
|
||||
|
||||
# This role provides easyily downloadable firmware files
|
||||
|
||||
- name: Firmware dvb-demod-si2168-b40-01.fw for Hauppauge WinTV HD Solo/Duo, PCTV 292e
|
||||
get_url:
|
||||
url: https://github.com/OpenELEC/dvb-firmware/raw/master/firmware/dvb-demod-si2168-b40-01.fw
|
||||
checksum: sha256:8507536630d75a316d0719d6b95c04b90c36baa5b457ad457c9bacadafcef134
|
||||
dest: /lib/firmware/dvb-demod-si2168-b40-01.fw
|
||||
when: '"2040:0264" in usb or "2013:025f" in usb'
|
||||
|
||||
- name: Firmware dvb-fe-xc5000-1.6.114.fw for Hauppauge WinTV-HVR-930C
|
||||
get_url:
|
||||
url: https://github.com/OpenELEC/dvb-firmware/raw/master/firmware/dvb-fe-xc5000-1.6.114.fw
|
||||
checksum: sha256:7104bda8df301fe1bd4c09de1708aeb6d0d8e1f9d55505449fecfad82639235f
|
||||
dest: /lib/firmware/dvb-fe-xc5000-1.6.114.fw
|
||||
when: '"2040:1605" in usb'
|
||||
|
||||
- name: Firmware ngenge_18.fw for ngene cards
|
||||
get_url:
|
||||
url: http://l4m-daten.de/downloads/firmware/dvb-s2/linux/all/ngene_18.fw
|
||||
checksum: sha256:213d98ec2cd575eba15d82ee79fed7098e670de43792f8aa773a95cfb7c32060
|
||||
dest: /lib/firmware/ngene_18.fw
|
||||
when: '"ngene" in modules'
|
||||
notify: reboot required
|
||||
|
||||
- name: Firmware drxk_a3.mc for drxk
|
||||
get_url:
|
||||
url: https://github.com/OpenELEC/dvb-firmware/raw/master/firmware/drxk_a3.mc
|
||||
checksum: sha256:f8956ad6f92a4ce90a6ab94ed23e2f9a27e9317e936fd3e0119778dd28e7e294
|
||||
dest: /lib/firmware/drxk_a3.mc
|
||||
when: '"ngene" in modules or "drxk" in modules'
|
||||
notify: reboot required
|
3
roles/autoinstall-hardware-irmp/meta/main.yml
Normal file
3
roles/autoinstall-hardware-irmp/meta/main.yml
Normal file
@ -0,0 +1,3 @@
|
||||
---
|
||||
dependencies:
|
||||
- { role: collect-facts }
|
@ -4,4 +4,5 @@
|
||||
- name: apt | install yavdr-hardware-irmp if connected
|
||||
apt:
|
||||
name: yavdr-hardware-irmp
|
||||
when: '"1209:4444" in usb'
|
||||
state: present
|
||||
when: '"1209:4444" in usb or "16c0:27d9" in usb'
|
||||
|
@ -11,5 +11,6 @@
|
||||
- name: apt | install vdr-plugin-satip if a Sat>IP server has been detected
|
||||
apt:
|
||||
name: vdr-plugin-satip
|
||||
when: satip_devices
|
||||
state: present
|
||||
when: satip_devices | bool
|
||||
notify: [ 'Restart VDR' ]
|
||||
|
@ -1,15 +1,16 @@
|
||||
---
|
||||
# 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: autoinstall ubuntu-drivers-common
|
||||
block:
|
||||
- name: apt | install ubuntu-drivers-common
|
||||
apt:
|
||||
name: ubuntu-drivers-common
|
||||
state: present
|
||||
|
||||
- name: let ubuntu-drivers automatically install additional drivers
|
||||
command: ubuntu-drivers --package-list /etc/yavdr/autoinstalled autoinstall
|
||||
- name: use ubuntu-drivers to install additional drivers automatically
|
||||
command: ubuntu-drivers --package-list /etc/yavdr/autoinstalled autoinstall
|
||||
when: (ansible_virtualization_type != "virtualbox" and ansible_virtualization_role != "guest")
|
||||
# ubuntu-drivers-common tries to autoinstall
|
||||
# conflicting packages for virtualbox in Ubuntu 16.04 and 18.04 :(
|
||||
# also alternates between virtualbox-guest-dkms and virtualbox-guest-dkms-hwe on successive runs
|
||||
|
41
roles/autoinstall-virtualbox-guest/tasks/main.yml
Normal file
41
roles/autoinstall-virtualbox-guest/tasks/main.yml
Normal file
@ -0,0 +1,41 @@
|
||||
---
|
||||
# file roles/autoinstall-virtualbox-guest/tasks/main.yml
|
||||
|
||||
- name: collect facts about installed packages
|
||||
package_facts:
|
||||
manager: "apt"
|
||||
|
||||
- name: install virtualbox guest additions
|
||||
block:
|
||||
- name: install packages
|
||||
apt:
|
||||
state: present
|
||||
name:
|
||||
- dkms
|
||||
- '{{ "virtualbox-guest-x11-hwe" if "xserver-xorg-hwe-18.04" in ansible_facts.packages else "virtualbox-guest-x11" }}'
|
||||
- '{{ "virtualbox-guest-dkms-hwe" if "linux-generic-hwe-18.04" in ansible_facts.packages else "virtualbox-guest-dkms" }}'
|
||||
|
||||
# TODO: set xineliboutput as frontend
|
||||
when:
|
||||
- ansible_virtualization_type == "virtualbox"
|
||||
- ansible_virtualization_role == "guest"
|
||||
- ansible_distribution == "Ubuntu"
|
||||
|
||||
- name: set xineliboutput as frontend
|
||||
block:
|
||||
- apt:
|
||||
name:
|
||||
- vdr-plugin-xineliboutput
|
||||
- xineliboutput-sxfe
|
||||
state: present
|
||||
- command: '{{ item }}'
|
||||
with_items:
|
||||
- vdrctl disable softhddevice
|
||||
- vdrctl disable vaapidevice
|
||||
- vdrctl disable xine
|
||||
- vdrctl disable pvr350
|
||||
- vdrctl enable xineliboutput
|
||||
ignore_errors: yes
|
||||
when:
|
||||
- ansible_virtualization_type in ["virtualbox", "VirtualPC", "VMware"]
|
||||
- ansible_virtualization_role == "guest"
|
3
roles/autoinstall-yausbir/meta/main.yml
Normal file
3
roles/autoinstall-yausbir/meta/main.yml
Normal file
@ -0,0 +1,3 @@
|
||||
---
|
||||
dependencies:
|
||||
- { role: yavdr-remote }
|
35
roles/autoinstall-yausbir/tasks/main.yml
Normal file
35
roles/autoinstall-yausbir/tasks/main.yml
Normal file
@ -0,0 +1,35 @@
|
||||
---
|
||||
# file roles/autoinstall-atric-usb/tasks/main.yml
|
||||
|
||||
- name: install and configure Atric IR-WakeupUSB
|
||||
block:
|
||||
- name: apt | install lirc-drv-yausbir
|
||||
apt:
|
||||
name: lirc-drv-yausbir
|
||||
state: present
|
||||
tags:
|
||||
- packages
|
||||
|
||||
- name: write lirc configuration
|
||||
template:
|
||||
src: templates/lirc_options.conf.j2
|
||||
dest: /etc/lirc/lirc_options.conf
|
||||
tags:
|
||||
- config
|
||||
- systemd
|
||||
|
||||
- name: enable lircd, eventlircd, lircd2uinput
|
||||
systemd:
|
||||
name: '{{ item }}'
|
||||
enabled: yes
|
||||
state: started
|
||||
masked: no
|
||||
daemon_reload: yes
|
||||
with_items:
|
||||
- eventlircd.service
|
||||
- lircd2uinput.service
|
||||
- lircd.service
|
||||
tags:
|
||||
- systemd
|
||||
|
||||
when: '"10c4:876c" in usb'
|
20
roles/autoinstall-yausbir/templates/lirc_options.conf.j2
Normal file
20
roles/autoinstall-yausbir/templates/lirc_options.conf.j2
Normal file
@ -0,0 +1,20 @@
|
||||
{{ ansible_managed | comment }}
|
||||
|
||||
[lircd]
|
||||
nodaemon = False
|
||||
driver = ya_usbir
|
||||
output = /var/run/lirc/lircd0
|
||||
pidfile = /var/run/lirc/lircd0.pid
|
||||
plugindir = /usr/lib/x86_64-linux-gnu/lirc/plugins
|
||||
permission = 666
|
||||
allow-simulate = No
|
||||
repeat-max = 600
|
||||
#loglevel = 6
|
||||
#release = true
|
||||
#release_suffix = _EVUP
|
||||
#logfile = ...
|
||||
#driver-options = ...
|
||||
|
||||
[lircmd]
|
||||
uinput = False
|
||||
nodaemon = False
|
1
roles/collect-facts/defaults/main.yml
Normal file
1
roles/collect-facts/defaults/main.yml
Normal file
@ -0,0 +1 @@
|
||||
|
39
roles/collect-facts/tasks/main.yml
Normal file
39
roles/collect-facts/tasks/main.yml
Normal file
@ -0,0 +1,39 @@
|
||||
- name: get information about usb and pci hardware and loaded kernel modules
|
||||
hardware_facts:
|
||||
usb: True
|
||||
pci: True
|
||||
modules: True
|
||||
gpus: True
|
||||
acpi_power_modes: True
|
||||
tags:
|
||||
- always
|
||||
|
||||
- debug:
|
||||
var: '{{ item }}'
|
||||
verbosity: 1
|
||||
with_items:
|
||||
- usb
|
||||
- pci
|
||||
- gpus
|
||||
- modules
|
||||
- acpi_power_modes
|
||||
- nvidia_detected
|
||||
- intel_detected
|
||||
- amd_detected
|
||||
- virtualbox_detected
|
||||
|
||||
- name: get detailed PCI device information
|
||||
pci_facts:
|
||||
tags:
|
||||
- always
|
||||
|
||||
- debug:
|
||||
var: pci_devices
|
||||
verbosity: 1
|
||||
|
||||
- name: known vdr output plugins
|
||||
set_fact:
|
||||
vdr_output_plugins:
|
||||
- softhddevice
|
||||
- xineliboutput
|
||||
- xine
|
@ -8,24 +8,20 @@
|
||||
|
||||
- name: apt | install libdvd-pkg
|
||||
apt:
|
||||
name: '{{ item }}'
|
||||
name: libdvd-pkg
|
||||
state: present
|
||||
install_recommends: no
|
||||
with_items:
|
||||
- 'libdvd-pkg'
|
||||
|
||||
- name: configure package libdvd-pkg
|
||||
debconf:
|
||||
name: 'libdvd-pkg'
|
||||
question: '{{ item }}'
|
||||
vtype: boolean
|
||||
value: true
|
||||
with_items:
|
||||
- 'libdvd-pkg/post-invoke_hook-install'
|
||||
- 'libdvd-pkg/build boolean'
|
||||
notify: ['Reconfigure unattended upgrades with dpkg']
|
||||
- name: reconfigure libdvd-pkg
|
||||
dpkg_reconfigure:
|
||||
pkg: libdvd-pkg
|
||||
answers: |
|
||||
libdvd-pkg/post-invoke_hook-install: boolean true
|
||||
libdvd-pkg/build: boolean true
|
||||
|
||||
|
||||
- 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
|
||||
warn: false
|
||||
|
40
roles/epgd/defaults/main.yml
Normal file
40
roles/epgd/defaults/main.yml
Normal file
@ -0,0 +1,40 @@
|
||||
---
|
||||
# file: roles/epgd/defaults/main.yml
|
||||
|
||||
epgd_dbhost: localhost
|
||||
epgd_dbport: 3306
|
||||
epgd_dbname: epg2vdr
|
||||
epgd_dbuser: epg2vdr
|
||||
epgd_dbpass: epg
|
||||
epgd_epgview: eventsview.sql
|
||||
epgd_epgviewweb: eventsviewplain.sql
|
||||
epgd_thetvdbview: thetvdbview.sql
|
||||
epgd_checkinitial: 1
|
||||
epgd_daysinadvance: 8
|
||||
epgd_daystoupdate: 4
|
||||
epgd_updatetime: 12
|
||||
epgd_updatethreshold: 500
|
||||
epgd_xmlstoretofs: 0
|
||||
epgd_getepgimages: 1
|
||||
# EpgImageSize
|
||||
# 0 = 174x130
|
||||
# 1 = 329x245
|
||||
# 2 = 525x400
|
||||
epgd_epgimagesize: 2
|
||||
epgd_maximagesperevent: 1
|
||||
epgd_seriesenabled: 1
|
||||
epgd_seriesport: 2006
|
||||
epgd_seriesstoretofs: 0
|
||||
epgd_seriesurl: www.eplists.de
|
||||
epgd_scrapepg: 1
|
||||
epgd_scrapRecordings: 1
|
||||
#epgd_scrapmoviedbapikey: ""
|
||||
epgd_cachepath: /var/cache/epgd/
|
||||
epgd_epghttpd_port: 9999
|
||||
#epgd_httpproxy: 127.0.0.1:8000
|
||||
epgd_httpproxy_username: ""
|
||||
epgd_httpproxy_password: ""
|
||||
epgd_LogLevel: 1
|
||||
epgd_epgdata_url: http://www.epgdata.com
|
||||
epgd_epgdata_pin: insert-your-pin-here
|
||||
epgd_epgdata_timeout: 180
|
98
roles/epgd/tasks/main.yml
Normal file
98
roles/epgd/tasks/main.yml
Normal file
@ -0,0 +1,98 @@
|
||||
---
|
||||
# file: roles/epgd/tasks/main.yml
|
||||
|
||||
#Installing mariadb, epg-daemon and epg2vdr.
|
||||
#bind-address is set to 0.0.0.0 --> 99-epgd.cnf.
|
||||
#The root SQL password is only stored (NONE), because the epgd-tool
|
||||
#is expecting it. But it is not really used,
|
||||
#because the connection is established via a socket without a password.
|
||||
#Normal users must use sudo if they want to access mysql as root.
|
||||
#TODO:
|
||||
# - Create channelmap if channels.conf is present.
|
||||
# (the script already exists at mld.)
|
||||
# - because skindesigner-logos delivers only svg-logos, logoSuffix svg should be the preset --> vdr-epg-daemon / lib / parameters.c
|
||||
# - customize epgd-tool for mariadb
|
||||
|
||||
|
||||
- name: MariaDB and Plugin | install
|
||||
apt:
|
||||
name: ['mariadb-server', 'mariadb-plugin-epglv', 'python-pymysql']
|
||||
state: present
|
||||
|
||||
- name: copy file | epgd mariadb config
|
||||
template:
|
||||
src: templates/etc_mysql_mariadb.conf.d_99-epgd.cnf.j2
|
||||
dest: /etc/mysql/mariadb.conf.d/99-epgd.cnf
|
||||
owner: root
|
||||
group: root
|
||||
|
||||
- name: create /root/.ssh if it doesn't exist yes
|
||||
file:
|
||||
path: /root/.ssh
|
||||
state: directory
|
||||
owner: root
|
||||
group: root
|
||||
mode: 0700
|
||||
|
||||
- name: copy file | mysqlpasswd
|
||||
template:
|
||||
src: templates/root_.ssh_mysqlpasswd.j2
|
||||
dest: /root/.ssh/mysqlpasswd
|
||||
owner: root
|
||||
group: root
|
||||
mode: 0600
|
||||
backup: yes
|
||||
|
||||
- name: Restart mariadb
|
||||
systemd:
|
||||
name: mariadb.service
|
||||
state: restarted
|
||||
enabled: yes
|
||||
masked: no
|
||||
|
||||
- name: Create a new database for epgd
|
||||
mysql_db:
|
||||
name: "{{ epgd_dbname }}"
|
||||
encoding: utf8
|
||||
state: present
|
||||
login_unix_socket: /var/run/mysqld/mysqld.sock
|
||||
|
||||
- name: Create User for epgd database
|
||||
mysql_user:
|
||||
name: "{{ epgd_dbuser }}"
|
||||
password: "{{ epgd_dbpass }}"
|
||||
host: '%'
|
||||
priv: '{{ epgd_dbname }}.*:ALL'
|
||||
state: present
|
||||
login_unix_socket: /var/run/mysqld/mysqld.sock
|
||||
|
||||
- name: Create User for epgd database
|
||||
mysql_user:
|
||||
name: "{{ epgd_dbuser }}"
|
||||
password: "{{ epgd_dbpass }}"
|
||||
host: 'localhost'
|
||||
priv: '{{ epgd_dbname }}.*:ALL'
|
||||
state: present
|
||||
login_unix_socket: /var/run/mysqld/mysqld.sock
|
||||
|
||||
- name: create epgd config folder
|
||||
file:
|
||||
path: /etc/epgd
|
||||
state: directory
|
||||
|
||||
- name: epgd config
|
||||
template:
|
||||
src: templates/etc_epgd_epgd.conf.j2
|
||||
dest: /etc/epgd/epgd.conf
|
||||
|
||||
- name: epgd | install
|
||||
apt:
|
||||
name: ['vdr-epg-daemon', 'vdr-plugin-epg2vdr', 'skindesigner-logos']
|
||||
state: present
|
||||
|
||||
#- name: epgd | start
|
||||
#systemd:
|
||||
#name: epgd_service
|
||||
#state: started
|
||||
#enabled: yes
|
||||
#masked: no
|
74
roles/epgd/templates/etc_epgd_epgd.conf.j2
Normal file
74
roles/epgd/templates/etc_epgd_epgd.conf.j2
Normal file
@ -0,0 +1,74 @@
|
||||
{{ ansible_managed | comment }}
|
||||
# ------------------------------------
|
||||
# Configuration of EPG Daemon
|
||||
# ------------------------------------
|
||||
|
||||
DbHost = {{ epgd_dbhost }}
|
||||
DbPort = {{ epgd_dbport }}
|
||||
DbName = {{ epgd_dbname }}
|
||||
DbUser = {{ epgd_dbuser }}
|
||||
DbPass = {{ epgd_dbpass }}
|
||||
|
||||
EpgView = {{ epgd_epgview }}
|
||||
EpgViewWeb = {{ epgd_epgviewweb }}
|
||||
TheTvDBView = {{ epgd_thetvdbview }}
|
||||
|
||||
CheckInitial = {{ epgd_checkinitial }}
|
||||
DaysInAdvance = {{ epgd_daysinadvance }}
|
||||
DaysToUpdate = {{ epgd_daystoupdate }}
|
||||
UpdateTime = {{ epgd_updatetime }}
|
||||
UpdateThreshold = {{ epgd_updatethreshold }}
|
||||
|
||||
XmlStoreToFs = {{ epgd_xmlstoretofs }}
|
||||
|
||||
GetEPGImages = {{ epgd_getepgimages }}
|
||||
# EpgImageSize
|
||||
# 0 = 174x130
|
||||
# 1 = 329x245
|
||||
# 2 = 525x400
|
||||
EpgImageSize = {{ epgd_epgimagesize }}
|
||||
MaxImagesPerEvent = {{ epgd_maximagesperevent }}
|
||||
|
||||
SeriesEnabled = {{ epgd_seriesenabled }}
|
||||
SeriesPort = {{ epgd_seriesport }}
|
||||
SeriesStoreToFs = {{ epgd_seriesstoretofs }}
|
||||
SeriesUrl = {{ epgd_seriesurl }}
|
||||
|
||||
ScrapEpg = {{ epgd_scrapepg }}
|
||||
ScrapRecordings = {{ epgd_scrapRecordings }}
|
||||
{% if epgd_scrapmoviedbapikey is defined %}
|
||||
ScapMovieDbApiKey = {{ epgd_scrapmoviedbapikey }}
|
||||
{% else %}
|
||||
#ScrapMovieDbApiKey =
|
||||
{% endif %}
|
||||
|
||||
{% if epgd_netdevice is defined %}
|
||||
NetDevice = {{ epgd_netdevice }}
|
||||
{% else %}
|
||||
# NetDevice = eth0
|
||||
{% endif %}
|
||||
|
||||
CachePath = {{ epgd_cachepath }}
|
||||
HttpPort = {{ epgd_epghttpd_port }}
|
||||
|
||||
{% if epgd_httpproxy is defined %}
|
||||
HttpProxy = {{ epgd_httpproxy }}
|
||||
UserName = {{ epgd_httpproxy_username }}
|
||||
Password = {{ epgd_httpproxy_password }}
|
||||
{% else %}
|
||||
# HttpProxy = 127.0.0.1:8000
|
||||
# UserName =
|
||||
# Password =
|
||||
{% endif %}
|
||||
|
||||
LogLevel = {{ epgd_LogLevel }}
|
||||
|
||||
# ---------------
|
||||
# epgdata plugin
|
||||
# ---------------
|
||||
|
||||
epgdata.url = {{ epgd_epgdata_url }}
|
||||
epgdata.pin = {{ epgd_epgdata_pin }}
|
||||
|
||||
# Download timeout in seconds (default 180)
|
||||
epgdata.timeout = {{ epgd_epgdata_timeout }}
|
@ -0,0 +1,4 @@
|
||||
{{ ansible_managed | comment }}
|
||||
[mysqld]
|
||||
bind-address = 0.0.0.0
|
||||
|
2
roles/epgd/templates/root_.ssh_mysqlpasswd.j2
Normal file
2
roles/epgd/templates/root_.ssh_mysqlpasswd.j2
Normal file
@ -0,0 +1,2 @@
|
||||
{{ ansible_managed | comment }}
|
||||
PASSWORD=NONE
|
@ -1,5 +1,10 @@
|
||||
---
|
||||
|
||||
- name: Update Initramfs
|
||||
command: "update-initramfs -u"
|
||||
failed_when: ('error' in initramfs_register_update.stderr)
|
||||
register: initramfs_register_update
|
||||
|
||||
- name: Update GRUB
|
||||
command: update-grub
|
||||
failed_when: ('error' in grub_register_update.stderr)
|
||||
|
@ -1,7 +1,7 @@
|
||||
#!/bin/sh
|
||||
exec tail -n +3 $0
|
||||
{{ ansible_managed | comment }}
|
||||
|
||||
# This file is configured by the ansible configuration for yaVDR
|
||||
exec tail -n +3 $0
|
||||
|
||||
{% if system.shutdown is defined and system.shutdown == 'reboot' %}
|
||||
menuentry "PowerOff" {
|
||||
|
@ -1,3 +1,4 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<lircmap>
|
||||
<remote device="linux-input-layer">
|
||||
<altname>cx23885_remote</altname>
|
||||
|
@ -1,3 +1,4 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- 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 -->
|
||||
|
@ -35,4 +35,9 @@
|
||||
group: '{{ vdr.group }}'
|
||||
mode: "0664"
|
||||
force: no
|
||||
# TODO: Add configuration files
|
||||
|
||||
- name: expand template for set-kodi-display
|
||||
template:
|
||||
src: 'templates/set-kodi-display.j2'
|
||||
dest: '/usr/bin/set-kodi-display'
|
||||
mode: "0755"
|
||||
|
@ -2,10 +2,24 @@
|
||||
|
||||
- name: apt | install kodi packages
|
||||
apt:
|
||||
name: '{{ item }}'
|
||||
name:
|
||||
- kodi
|
||||
- kodi-pvr-vdr-vnsi
|
||||
- python3-lxml
|
||||
state: present
|
||||
install_recommends: no
|
||||
with_items:
|
||||
- kodi
|
||||
- kodi-pvr-vdr-vnsi
|
||||
- kodi-eventclients-xbmc-send
|
||||
|
||||
- name: apt | install kodi-send (team-xbmc PPA)
|
||||
apt:
|
||||
name: "kodi-eventclients-xbmc-send" # team-xbmc uses "kodi-eventclients-xbmc-send for some reason
|
||||
state: present
|
||||
install_recommends: no
|
||||
register: team_xbmc_ppa
|
||||
ignore_errors: True
|
||||
|
||||
- name: apt | install kodi-send (Ubuntu package)
|
||||
apt:
|
||||
name: "kodi-eventclients-kodi-send" # fallback to ubuntu package
|
||||
state: present
|
||||
install_recommends: no
|
||||
when: team_xbmc_ppa.failed
|
||||
|
@ -1,2 +1,10 @@
|
||||
- import_tasks: install-kodi.yml tags=install,update,kodi:install
|
||||
- import_tasks: configure-kodi.yml tags=install,update,kodi:configure
|
||||
- import_tasks: install-kodi.yml
|
||||
tags:
|
||||
- install
|
||||
- update
|
||||
- kodi:install
|
||||
- import_tasks: configure-kodi.yml
|
||||
tags:
|
||||
- install
|
||||
- update
|
||||
- kodi:configure
|
||||
|
@ -6,7 +6,7 @@ Type=simple
|
||||
PassEnvironment=DISPLAY XDG_RUNTIME_DIR DBUS_SESSION_BUS_ADDRESS
|
||||
ExecStartPre=-/usr/bin/set-kodi-display
|
||||
ExecStart=/usr/bin/kodi -l /run/lirc/lircd
|
||||
ExecStop=/bin/bash -c "/usr/bin/kodi-send --action=QUIT; while /usr/bin/pgrep kodi; do sleep 1; done; sleep 1"
|
||||
ExecStop=/bin/bash -c "/usr/bin/kodi-send --action=QUIT; while ps -p $MAINPID -o comm=; do sleep .25; done"
|
||||
TimeoutStopSec=10
|
||||
SuccessExitStatus=0 127
|
||||
SuccessExitStatus=0 127 SIGKILL
|
||||
Restart=on-failure
|
117
roles/kodi/templates/set-kodi-display.j2
Normal file
117
roles/kodi/templates/set-kodi-display.j2
Normal file
@ -0,0 +1,117 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
{{ ansible_managed }}
|
||||
|
||||
This Script changes the monitor in KODI's guisettings.xml to the wanted output
|
||||
according to the DISPLAY environment variable. It works with KODI 18 (not KODI 17!).
|
||||
|
||||
In order to change the display we need to modify the settings/videoscreen nodes.
|
||||
|
||||
Basic algorithm:
|
||||
- get the current videoscreen.monitor
|
||||
- check if it needs to be changed
|
||||
- create a backup of the videoscreen nodes in /var/lib/vdr/.kodi/.display_cache/{CONNETOR}-videoscreen.xml
|
||||
- check if there is an existing backup for the new CONNECTOR
|
||||
- parse the backup of the videoscreen nodes
|
||||
- replace the videoscreen nodes with the backup data
|
||||
"""
|
||||
|
||||
import copy
|
||||
import os
|
||||
import sys
|
||||
import subprocess
|
||||
from lxml import etree as ET
|
||||
|
||||
|
||||
GUISETTINGS = '/var/lib/vdr/.kodi/userdata/guisettings.xml'
|
||||
CACHE_DIR = '/var/lib/vdr/.kodi/.display_cache'
|
||||
VIDEOSCREEN_TEMPLATE = """<settings version="2">
|
||||
<setting id="videoscreen.monitor">{}</setting>
|
||||
</settings>"""
|
||||
|
||||
|
||||
def create_cache_dir():
|
||||
try:
|
||||
os.makedirs(CACHE_DIR, exist_ok=True)
|
||||
except PermissionError:
|
||||
sys.exit(f"Error: insufficient permissions to create cachedir {CACHE_DIR}")
|
||||
except Exception as e:
|
||||
sys.exit(f"Unexpected Error when trying to create {CACHE_DIR}:", e)
|
||||
|
||||
|
||||
|
||||
def get_output_name():
|
||||
"""
|
||||
get display name from xrandr output for given DISPLAY environment variable
|
||||
"""
|
||||
try:
|
||||
xrandr_output = [
|
||||
l for l in subprocess.check_output(
|
||||
["xrandr"],
|
||||
env={"DISPLAY": os.environ["DISPLAY"]}
|
||||
).decode("utf-8").splitlines()
|
||||
]
|
||||
return next(l.split()[0] for l in xrandr_output if " connected " in l)
|
||||
except Exception as e:
|
||||
sys.exit("could not determine output name", e)
|
||||
|
||||
|
||||
def parse_template(template_path, template, output=""):
|
||||
"""read videoscreen settings from backup or create a stub file"""
|
||||
try:
|
||||
xml_tree = ET.parse(template_path)
|
||||
except OSError:
|
||||
print(f"{template_path} not found, creating stub file", file=sys.stderr)
|
||||
xml_template = ET.fromstring(template.format(output))
|
||||
xml_tree = ET.ElementTree(xml_template)
|
||||
finally:
|
||||
xml_tree.write(template_path)
|
||||
return xml_tree
|
||||
|
||||
|
||||
def main(output):
|
||||
guisettings = parse_template(GUISETTINGS, VIDEOSCREEN_TEMPLATE, "Default")
|
||||
|
||||
# parse guisettings Etree for display name an backup videoscreen data
|
||||
root = guisettings.getroot()
|
||||
old_output = root.find("./setting[@id='videoscreen.monitor']").text
|
||||
if old_output == output:
|
||||
print("no changes necessary, exiting", file=sys.stderr)
|
||||
sys.exit()
|
||||
|
||||
# create a minimal guisettings etree
|
||||
xml_path = os.path.join(CACHE_DIR, f'{old_output}-videoscreen.xml')
|
||||
base_tree = ET.fromstring('<settings version="2"></settings>')
|
||||
xml_tree = ET.ElementTree(base_tree)
|
||||
backup_root = xml_tree.getroot()
|
||||
|
||||
# copy videoscreen elements to backup etree
|
||||
videoscreen_elements = root.xpath(
|
||||
"./setting[starts-with(@id, 'videoscreen.')]")
|
||||
for element in videoscreen_elements:
|
||||
backup_root.append(copy.deepcopy(element))
|
||||
element.getparent().remove(element)
|
||||
xml_tree.write(xml_path)
|
||||
print(f"written backup for {old_output} to {xml_path}", file=sys.stderr)
|
||||
|
||||
# change videoscreen node to content of backup file
|
||||
xml_path = os.path.join(CACHE_DIR, f'{output}-videoscreen.xml')
|
||||
videodir_xml = parse_template(xml_path, VIDEOSCREEN_TEMPLATE, output)
|
||||
videodir_root = videodir_xml.getroot()
|
||||
videoscreen = videodir_root.find("./setting[@id='videoscreen.monitor']")
|
||||
# copy videoscreen.* elements from Backup
|
||||
videoscreen_elements = videodir_root.xpath(
|
||||
"./setting[starts-with(@id, 'videoscreen.')]")
|
||||
for element in videoscreen_elements:
|
||||
new_element = copy.deepcopy(element)
|
||||
root.append(new_element)
|
||||
guisettings.write(GUISETTINGS)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
create_cache_dir()
|
||||
output = get_output_name()
|
||||
try:
|
||||
main(output)
|
||||
except Exception as e:
|
||||
print("Could not change videoscreen.* settings:", str(e), file=sys.stderr)
|
@ -2,12 +2,11 @@
|
||||
|
||||
- name: install nfs server packages
|
||||
apt:
|
||||
name: '{{ item }}'
|
||||
name:
|
||||
- nfs-kernel-server
|
||||
- nfs-common
|
||||
state: present
|
||||
install_recommends: no
|
||||
with_items:
|
||||
- nfs-kernel-server
|
||||
- nfs-common
|
||||
|
||||
- name: create /etc/exports
|
||||
template:
|
||||
|
@ -1,4 +1,4 @@
|
||||
/srv *(rw,fsid=0,sync,no_subtree_check,all_squash,anongid={{ vdr.gid }},anonuid={{ vdr.uid }})
|
||||
{% for name, path in media_dirs.iteritems() %}
|
||||
{% for name, path in media_dirs.items() | list %}
|
||||
{{ path }} *(rw,fsid={{ loop.index }},sync,no_subtree_check,all_squash,anongid={{ vdr.gid }},anonuid={{ vdr.uid }}{{ ',insecure' if nfs.insecure else '' }})
|
||||
{% endfor %}
|
||||
|
@ -5,12 +5,15 @@
|
||||
repo: 'ppa:graphics-drivers/ppa'
|
||||
state: present
|
||||
update_cache: yes
|
||||
tags:
|
||||
- ppa
|
||||
|
||||
- name: install nvidia-387 and other required packages
|
||||
- name: install nvidia-396 and other required packages
|
||||
apt:
|
||||
name: '{{ item }}'
|
||||
name:
|
||||
- nvidia-396
|
||||
- nvidia-settings
|
||||
state: present
|
||||
install_recommends: no
|
||||
with_items:
|
||||
- nvidia-387
|
||||
- nvidia-settings
|
||||
tags:
|
||||
- packages
|
@ -1,13 +1,13 @@
|
||||
---
|
||||
|
||||
- name: apt | install pulseaudio and pavucontrol
|
||||
- name: apt | install pulseaudio, pavucontrol and vdr-plugin-pulsecontrol
|
||||
apt:
|
||||
name: '{{ item }}'
|
||||
name:
|
||||
- pulseaudio
|
||||
- pavucontrol
|
||||
- vdr-plugin-pulsecontrol
|
||||
state: present
|
||||
install_recommends: no
|
||||
with_items:
|
||||
- pulseaudio
|
||||
- pavucontrol
|
||||
|
||||
- name: create /etc/asound.conf with pulseaudio as default device
|
||||
template:
|
||||
|
@ -1,4 +1,4 @@
|
||||
{{ ansible_managed_file | comment }}
|
||||
{{ ansible_managed | comment }}
|
||||
|
||||
#======================= Global Settings =======================
|
||||
|
||||
@ -69,7 +69,8 @@
|
||||
|
||||
# This option controls how unsuccessful authentication attempts are mapped
|
||||
# to anonymous connections
|
||||
map to guest = bad user
|
||||
map to guest = bad password
|
||||
guest account = nobody
|
||||
|
||||
{% if samba.windows_compatible %}
|
||||
# disable unix extensions and enable following symlinks
|
||||
@ -77,7 +78,7 @@
|
||||
follow symlinks= yes
|
||||
wide links= yes
|
||||
{% endif %}
|
||||
{% for name, path in media_dirs.iteritems() %}
|
||||
{% for name, path in media_dirs.items() | list %}
|
||||
[{{ name }}]
|
||||
path = {{ path }}
|
||||
comment = {{ name }} on %h
|
||||
|
@ -3,11 +3,10 @@
|
||||
|
||||
- name: install samba server
|
||||
apt:
|
||||
name: '{{ item }}'
|
||||
name:
|
||||
- samba
|
||||
- samba-common
|
||||
- samba-common-bin
|
||||
- tdb-tools
|
||||
state: present
|
||||
install_recommends: no
|
||||
with_items:
|
||||
- samba
|
||||
- samba-common
|
||||
- samba-common-bin
|
||||
- tdb-tools
|
||||
|
4
roles/serial-ir/defaults/main.yml
Normal file
4
roles/serial-ir/defaults/main.yml
Normal file
@ -0,0 +1,4 @@
|
||||
---
|
||||
# file: roles/serial-ir/defaults/main.yml
|
||||
|
||||
serial_ir_device: ttyS0
|
21
roles/serial-ir/tasks/main.yml
Normal file
21
roles/serial-ir/tasks/main.yml
Normal file
@ -0,0 +1,21 @@
|
||||
---
|
||||
# file: roles/serial-ir/tasks/main.yml
|
||||
|
||||
- name: apt | install setserial
|
||||
apt:
|
||||
name: setserial
|
||||
|
||||
- name: load serial_ir on startup
|
||||
template:
|
||||
src: roles/serial-ir/templates/modules-load.d/serial_ir.conf.j2
|
||||
dest: /etc/modules-load.d/serial_ir.conf
|
||||
|
||||
- name: serial_ir module options
|
||||
template:
|
||||
src: roles/serial-ir/templates/modprobe.d/serial_ir.conf.j2
|
||||
dest: /etc/modprobe.d/serial_ir.conf
|
||||
|
||||
- name: setserial options
|
||||
template:
|
||||
src: roles/serial-ir/templates/serial.conf.j2
|
||||
dest: /etc/serial.conf
|
12
roles/serial-ir/templates/modprobe.d/serial_ir.conf.j2
Normal file
12
roles/serial-ir/templates/modprobe.d/serial_ir.conf.j2
Normal file
@ -0,0 +1,12 @@
|
||||
{{ ansible_managed | comment }}
|
||||
|
||||
{% if serial_ir_device == "ttyS0" %}
|
||||
#COM1 equivalent, /dev/ttyS0
|
||||
options serial_ir irq=4 io=0x3f8
|
||||
{% elif serial_ir_device == "ttyS1" %}
|
||||
#COM2 equivalent, /dev/ttyS1
|
||||
options serial_ir irq=3 io=0x2f8
|
||||
{% endif %}
|
||||
{% if serial_ir_device in ("ttyS0", "ttyS1") %}
|
||||
install serial_ir setserial /dev/{{serial_ir_device}} uart none; /sbin/modprobe --ignore-install serial_ir
|
||||
{% endif %}
|
@ -0,0 +1,3 @@
|
||||
{{ ansible_managed | comment }}
|
||||
|
||||
serial_ir
|
9
roles/serial-ir/templates/serial.conf.j2
Normal file
9
roles/serial-ir/templates/serial.conf.j2
Normal file
@ -0,0 +1,9 @@
|
||||
{{ ansible_managed | comment }}
|
||||
|
||||
{% if serial_ir_device == "ttyS0" %}
|
||||
#COM1 equivalent, /dev/ttyS0
|
||||
/dev/ttyS0 uart none
|
||||
{% elif serial_ir_device == "ttyS1" %}
|
||||
#COM2 equivalent, /dev/ttyS1
|
||||
/dev/ttyS1 uart none
|
||||
{% endif %}
|
15
roles/vdr-plugin-menuorg/tasks/main.yml
Normal file
15
roles/vdr-plugin-menuorg/tasks/main.yml
Normal file
@ -0,0 +1,15 @@
|
||||
---
|
||||
# file: roles/vdr-plugin-menuorg/tasks/main.yml
|
||||
|
||||
- name: apt | install vdr-plugin-menuorg and yavdr-i18n
|
||||
apt:
|
||||
name:
|
||||
- vdr-plugin-menuorg
|
||||
- yavdr-i18n
|
||||
state: present
|
||||
install_recommends: no
|
||||
|
||||
- name: create /var/lib/vdr/plugins/menuorg.xml
|
||||
template:
|
||||
src: templates/menuorg.xml.j2
|
||||
dest: /var/lib/vdr/plugins/menuorg.xml
|
51
roles/vdr-plugin-menuorg/templates/menuorg.xml.j2
Normal file
51
roles/vdr-plugin-menuorg/templates/menuorg.xml.j2
Normal file
@ -0,0 +1,51 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
{{ ansible_managed | comment('xml') }}
|
||||
<!--
|
||||
This is the config file for the Menuorg plug-in.
|
||||
See /usr/share/doc/vdr-plugin-menurg for examples and a full
|
||||
description of the config file format.
|
||||
-->
|
||||
<menus>
|
||||
<system name="Schedule" />
|
||||
<system name="Channels" />
|
||||
<system name="Timers" />
|
||||
<system name="Recordings" />
|
||||
<plugin name="tvguide" />
|
||||
<command name="Kodi" execute="frontend-dbus-send switchto kodi" />
|
||||
<plugin name="desktop" />
|
||||
<menu name="{{ 'VDR Plugins' | translate }}">
|
||||
<plugin name="epgsearchonly" />
|
||||
<plugin name="quickepgsearch" />
|
||||
<plugin name="conflictcheckonly" />
|
||||
<plugin name="markad" />
|
||||
<plugin name="recsearch" />
|
||||
<plugin name="undelete" />
|
||||
<plugin name="radio" />
|
||||
<plugin name="osd2web" />
|
||||
</menu>
|
||||
<menu name="{{ 'System' | translate }}">
|
||||
<menu name="{{ 'Commands' | translate }}">
|
||||
<command name="{{ "Safely remove usb mass storage" | translate }}" confirm="yes" execute="/usr/bin/vdr-mounter --unmount-all &> /dev/null" />
|
||||
<command name="{{ "Update vdr recordings list" | translate }}" execute="/usr/bin/vdr-dbus-send /Recordings recording.Update &> /dev/null " />
|
||||
<command name="{{ "Restart VDR" |translate }}" confirm="yes" execute="sudo /sbin/initctl restart vdr" />
|
||||
<command name="{{ "Reboot system"| translate }}" confirm="yes" execute="/usr/bin/at now -M -f /usr/bin/vdr-reboot" />
|
||||
<command name="{{ "Shutdown system" | translate }}" execute="/usr/bin/lircd2uinput-send KEY_POWER2 &> /dev/null & " />
|
||||
</menu>
|
||||
<system name="Setup" />
|
||||
<plugin name="femon" />
|
||||
<plugin name="devstatus" />
|
||||
<plugin name="epg2vdr" />
|
||||
<plugin name="scraper2vdr" />
|
||||
<plugin name="sndctl" />
|
||||
<plugin name="suspendoutput" />
|
||||
<plugin name="recstatus" />
|
||||
<plugin name="dynamite" />
|
||||
<plugin name="noepgmenu" />
|
||||
<plugin name="systeminfo" />
|
||||
<plugin name="filebrowser" />
|
||||
<plugin name="pin" />
|
||||
<plugin name="pulsecontrol" />
|
||||
<plugin name="softhddevice" />
|
||||
</menu>
|
||||
<system name="Commands" />
|
||||
</menus>
|
@ -3,13 +3,12 @@
|
||||
|
||||
- name: apt | install basic vdr packages
|
||||
apt:
|
||||
name: '{{ item }}'
|
||||
name:
|
||||
- vdr
|
||||
- vdrctl
|
||||
- vdr-plugin-dbus2vdr
|
||||
state: present
|
||||
install_recommends: no
|
||||
with_items:
|
||||
- vdr
|
||||
- vdrctl
|
||||
- vdr-plugin-dbus2vdr
|
||||
- name: add svdrp and svdrp-disc to /etc/services
|
||||
lineinfile:
|
||||
dest: /etc/services
|
||||
@ -30,11 +29,10 @@
|
||||
blockinfile:
|
||||
dest: /etc/vdr/conf.d/04-vdr-hide-first-recordinglevel.conf
|
||||
create: true
|
||||
state: "{{ 'present' if vdr.hide_first_recording_level else 'absent' }}"
|
||||
block: |
|
||||
[vdr]
|
||||
--hide-first-recording-level
|
||||
when:
|
||||
vdr.hide_first_recording_level
|
||||
|
||||
- name: create local dir in recdir
|
||||
file:
|
||||
@ -49,11 +47,9 @@
|
||||
# TODO: set recdir, user etc. in /etc/vdr/conf.d/
|
||||
- name: apt | install additional vdr plugins
|
||||
apt:
|
||||
name: '{{ item }}'
|
||||
name: '{{ vdr_plugins | default([]) }}'
|
||||
state: present
|
||||
install_recommends: no
|
||||
with_items:
|
||||
'{{ vdr_plugins | default({}) }}'
|
||||
notify: [ 'Restart VDR' ]
|
||||
- name: ensure vdr is stopped
|
||||
systemd:
|
||||
@ -70,11 +66,105 @@
|
||||
mode: 0644
|
||||
force: no
|
||||
|
||||
- name: "vdr configuration | copy keymacros.conf if it doesn't exist yet"
|
||||
- name: "vdr configuration | copy keymacros.conf"
|
||||
copy:
|
||||
src: files/keymacros.conf
|
||||
dest: '{{ vdr.confdir }}/keymacros.conf'
|
||||
dest: '{{ vdr.etc_confdir }}/keymacros.conf'
|
||||
owner: '{{ vdr.user }}'
|
||||
group: '{{ vdr.group }}'
|
||||
mode: 0644
|
||||
force: no
|
||||
|
||||
- name: "vdr configuration | copy channels.conf if it doesn't exist yet"
|
||||
copy:
|
||||
src: '{{ vdr_channels_conf }}'
|
||||
dest: '{{ vdr.confdir }}/channels.conf'
|
||||
owner: '{{ vdr.user }}'
|
||||
group: '{{ vdr.group }}'
|
||||
mode: 0644
|
||||
force: no
|
||||
when: vdr_channels_conf is defined
|
||||
|
||||
- name: "vdr configuration | download channels.conf if it doesn't exist yet"
|
||||
get_url:
|
||||
url: '{{ vdr_channels_conf_url }}'
|
||||
dest: '{{ vdr.confdir }}/channels.conf'
|
||||
owner: '{{ vdr.user }}'
|
||||
group: '{{ vdr.group }}'
|
||||
mode: 0644
|
||||
force: no
|
||||
when: vdr_channels_conf is not defined and vdr_channels_conf_url is defined
|
||||
|
||||
- name: "vdr configuration | svdrphosts.conf"
|
||||
template:
|
||||
src: templates/svdrphosts.conf.j2
|
||||
dest: '{{ vdr.etc_confdir }}/svdrphosts.conf'
|
||||
mode: 0644
|
||||
vars:
|
||||
svdrphosts: '{{ vdr_svdrphosts | default(vdr_allowed_hosts) }}'
|
||||
|
||||
- name: "vdr configuration | /etc/default/vdr"
|
||||
template:
|
||||
src: templates/default_vdr.j2
|
||||
dest: /etc/default/vdr
|
||||
- name: ensure directory '/etc/vdr/xineliboutput' exists
|
||||
file:
|
||||
state: directory
|
||||
mode: 0775
|
||||
dest: '/etc/vdr/plugins/xineliboutput'
|
||||
|
||||
- name: "vdr configuration | allowed_hosts.conf for xineliboutput"
|
||||
template:
|
||||
src: templates/generic_allowed_hosts.conf.j2
|
||||
dest: '/etc/vdr/plugins/{{ vdr_service }}/allowed_hosts.conf'
|
||||
mode: 0644
|
||||
vars:
|
||||
allowed_hosts: '{{ xineliboutput_allowed_hosts | default(vdr_allowed_hosts) }}'
|
||||
vdr_service: xineliboutput
|
||||
|
||||
- name: "vdr configuration | xineliboutput.conf host settings"
|
||||
template:
|
||||
src: templates/xineliboutput.conf.j2
|
||||
dest: /etc/vdr/conf.avail/xineliboutput.conf
|
||||
mode: 0644
|
||||
vars:
|
||||
allowed_hosts: '{{ xineliboutput_allowed_hosts | default(vdr_allowed_hosts) }}'
|
||||
- name: ensure directory '/etc/vdr/plugins/vnsiserver' exists
|
||||
file:
|
||||
state: directory
|
||||
mode: 0775
|
||||
dest: '/etc/vdr/plugins/vnsiserver'
|
||||
|
||||
- name: "vdr configuration | allowed_hosts.conf for vnsiserver"
|
||||
template:
|
||||
src: templates/generic_allowed_hosts.conf.j2
|
||||
dest: '/etc/vdr/plugins/{{ vdr_service }}/allowed_hosts.conf'
|
||||
mode: 0644
|
||||
vars:
|
||||
allowed_hosts: '{{ vnsiserver_allowed_hosts | default(vdr_allowed_hosts) }}'
|
||||
vdr_service: vnsiserver
|
||||
- name: ensure directory '/etc/vdr/plugins' exists
|
||||
file:
|
||||
state: directory
|
||||
mode: 0775
|
||||
dest: '/etc/vdr/plugins/'
|
||||
|
||||
- name: "vdr configuration | streamdevhosts.conf for streamdev-server"
|
||||
template:
|
||||
src: templates/generic_allowed_hosts.conf.j2
|
||||
dest: '/etc/vdr/plugins/streamdevhosts.conf'
|
||||
mode: 0644
|
||||
vars:
|
||||
allowed_hosts: '{{ streamdev_server_allowed_hosts | default(vdr_allowed_hosts) }}'
|
||||
vdr_service: streamdev-server
|
||||
- name: create directory for vdr.service systemd drop-in files
|
||||
file:
|
||||
dest: '{{ item }}'
|
||||
state: directory
|
||||
with_items:
|
||||
- "/etc/systemd/system/vdr.service.d/"
|
||||
|
||||
- name: systemd-drop-in | start vdr.service after network-online.target
|
||||
template:
|
||||
src: templates/systemd/network-online.j2
|
||||
dest: /etc/systemd/system/vdr.service.d/network-online.conf
|
||||
|
7
roles/vdr/templates/default_vdr.j2
Normal file
7
roles/vdr/templates/default_vdr.j2
Normal file
@ -0,0 +1,7 @@
|
||||
{{ ansible_managed | comment }}
|
||||
# /etc/default/vdr
|
||||
#
|
||||
# See also /usr/share/doc/vdr/README.Debian.gz
|
||||
#
|
||||
|
||||
SHUTDOWNCMD="{{ vdr_shutdown_command }}"
|
22
roles/vdr/templates/generic_allowed_hosts.conf.j2
Normal file
22
roles/vdr/templates/generic_allowed_hosts.conf.j2
Normal file
@ -0,0 +1,22 @@
|
||||
{{ ansible_managed | comment }}
|
||||
# This file describes a number of host addresses that
|
||||
# are allowed to connect to the {{ vdr_service }}
|
||||
# running with the Video Disk Recorder (VDR) on this system.
|
||||
#
|
||||
# Syntax:
|
||||
#
|
||||
# IP-Address[/Netmask]
|
||||
#
|
||||
# Examples:
|
||||
#
|
||||
# 192.168.100.0/24 # any host on the local net
|
||||
# 204.152.189.113 # a specific host
|
||||
{% if vdr_service == 'streamdev-server' %}
|
||||
# 239.255.0.0/16 # uncomment for IGMP multicast streaming
|
||||
{% endif %}
|
||||
# 0.0.0.0/0 # any host on any net (USE THIS WITH CARE!)
|
||||
|
||||
127.0.0.1 # always accept localhost
|
||||
{% for host_or_subnet in allowed_hosts %}
|
||||
{{ host_or_subnet }}
|
||||
{% endfor %}
|
18
roles/vdr/templates/svdrphosts.conf.j2
Normal file
18
roles/vdr/templates/svdrphosts.conf.j2
Normal file
@ -0,0 +1,18 @@
|
||||
{{ ansible_managed | comment }}
|
||||
#
|
||||
# svdrphosts This file describes a number of host addresses that
|
||||
# are allowed to connect to the SVDRP port of the Video
|
||||
# Disk Recorder (VDR) running on this system.
|
||||
# Syntax:
|
||||
#
|
||||
# IP-Address[/Netmask]
|
||||
#
|
||||
# Examples:
|
||||
# 192.168.100.0/24 # any host on the local net
|
||||
# 204.152.189.113 # a specific host
|
||||
# 0.0.0.0/0 # any host on any net (USE THIS WITH CARE!)
|
||||
|
||||
127.0.0.1 # always accept localhost
|
||||
{% for host_or_subnet in svdrphosts %}
|
||||
{{ host_or_subnet }}
|
||||
{% endfor %}
|
3
roles/vdr/templates/systemd/network-online.j2
Normal file
3
roles/vdr/templates/systemd/network-online.j2
Normal file
@ -0,0 +1,3 @@
|
||||
{{ansible_managed | comment }}
|
||||
[Unit]
|
||||
After=network-online.target
|
13
roles/vdr/templates/xineliboutput.conf.j2
Normal file
13
roles/vdr/templates/xineliboutput.conf.j2
Normal file
@ -0,0 +1,13 @@
|
||||
#
|
||||
# Command line parameters for vdr-plugin-xineliboutput
|
||||
#
|
||||
# For more details see:
|
||||
# - /usr/share/doc/vdr-plugin-xineliboutput/README.Debian
|
||||
# - `vdr --help -Pxineliboutput`
|
||||
# - /usr/share/doc/vdr-plugin-xineliboutput/README
|
||||
#
|
||||
[xineliboutput]
|
||||
--local=none
|
||||
--primary
|
||||
--remote={{ "" if allowed_hosts else "127.0.0.1" }}:37890
|
||||
--truecolor
|
3
roles/wakeup/defaults/main.yml
Normal file
3
roles/wakeup/defaults/main.yml
Normal file
@ -0,0 +1,3 @@
|
||||
---
|
||||
# file roles/wakeup/defaults/main.yml
|
||||
wakeup_method: "acpiwakeup"
|
13
roles/wakeup/tasks/main.yml
Normal file
13
roles/wakeup/tasks/main.yml
Normal file
@ -0,0 +1,13 @@
|
||||
---
|
||||
# file roles/wakeup/tasks/main.yml
|
||||
|
||||
- name: install and configure vdr-addon-acpiwakeup
|
||||
apt:
|
||||
name: vdr-addon-acpiwakeup
|
||||
state: present
|
||||
when: wakeup_method == "acpiwakeup"
|
||||
|
||||
- name: expand template for /etc/vdr/vdr-addon-acpiwakeup.conf
|
||||
template:
|
||||
src: templates/vdr-addon-acpiwakeup.conf.j2
|
||||
dest: /etc/vdr/vdr-addon-acpiwakeup.conf
|
16
roles/wakeup/templates/vdr-addon-acpiwakeup.conf.j2
Normal file
16
roles/wakeup/templates/vdr-addon-acpiwakeup.conf.j2
Normal file
@ -0,0 +1,16 @@
|
||||
{{ ansible_managed | comment }}
|
||||
|
||||
# Activate/deactivate ACPIWakeup with yes/no:
|
||||
ACPI_ENABLED="{% if wakeup_method == 'acpiwakeup' %}yes{% else %}no{% endif %}"
|
||||
|
||||
# How many minutes should the machine wake up before the timer starts:
|
||||
ACPI_START_AHEAD=5
|
||||
|
||||
# If you want your VDR machine to wakeup in regular intervals (i.e. for
|
||||
# updating EPG data), specify the days of the week and the wakeup time.
|
||||
#
|
||||
# Days of the week for regular wakeup (not set=Disabled, 1=Monday...7=Sunday)
|
||||
# ACPI_REGULAR_DAYS="1 2 3 4 5 6 7"
|
||||
|
||||
# Wakeup time
|
||||
#ACPI_REGULAR_TIME=01:00 # HH:MM
|
@ -28,3 +28,4 @@ vdr:
|
||||
hide_first_recording_level: false
|
||||
safe_dirnames: true
|
||||
override_vdr_charset: false
|
||||
vdr_allowed_hosts: []
|
||||
|
19
roles/yavdr-common/tasks/configure_apt.yml
Normal file
19
roles/yavdr-common/tasks/configure_apt.yml
Normal file
@ -0,0 +1,19 @@
|
||||
---
|
||||
|
||||
- name: apt | prevent automatic installation of recommended packages
|
||||
template:
|
||||
src: templates/90-norecommends.j2
|
||||
dest: /etc/apt/apt.conf.d/90norecommends
|
||||
- name: add PPAs
|
||||
apt_repository:
|
||||
repo: '{{ item }}'
|
||||
state: present
|
||||
update_cache: no
|
||||
with_items: '{{ repositories }}'
|
||||
tags:
|
||||
- ppa
|
||||
|
||||
- name: run apt-get dist-upgrade
|
||||
apt:
|
||||
upgrade: dist
|
||||
update_cache: yes
|
61
roles/yavdr-common/tasks/configure_system.yml
Normal file
61
roles/yavdr-common/tasks/configure_system.yml
Normal file
@ -0,0 +1,61 @@
|
||||
- name: use bash instead of dash
|
||||
shell: |
|
||||
echo "set dash/sh false" | debconf-communicate
|
||||
dpkg-reconfigure -f noninteractive dash
|
||||
- name: create vdr group
|
||||
group:
|
||||
gid: '{{ vdr.gid }}'
|
||||
state: present
|
||||
name: '{{ vdr.group }}'
|
||||
|
||||
- name: create vdr user
|
||||
user:
|
||||
name: '{{ vdr.user }}'
|
||||
group: '{{ vdr.group }}'
|
||||
uid: '{{ vdr.uid }}'
|
||||
home: '{{ vdr.home }}'
|
||||
shell: '/bin/bash'
|
||||
state: present
|
||||
append: true
|
||||
- name: disable release-upgrade notifications
|
||||
lineinfile:
|
||||
dest: /etc/update-manager/release-upgrades
|
||||
backrefs: yes
|
||||
state: present
|
||||
regexp: '^(Prompt=).*$'
|
||||
line: '\1never'
|
||||
ignore_errors: yes
|
||||
with_first_found:
|
||||
- files:
|
||||
- /etc/update-manager/release-upgrades
|
||||
errors: ignore
|
||||
- name: apt | install basic packages
|
||||
apt:
|
||||
name:
|
||||
- anacron
|
||||
- acl
|
||||
- at
|
||||
- bash-completion
|
||||
#- biosdevname # caution: may change device names after a minimal installation!
|
||||
- debconf-utils
|
||||
- linux-firmware
|
||||
- psmisc
|
||||
- python-jmespath
|
||||
- python-kmodpy
|
||||
- python-requests
|
||||
- python-usb
|
||||
- python3-usb
|
||||
- software-properties-common
|
||||
- ssh
|
||||
- wget
|
||||
- wpasupplicant
|
||||
- usbutils
|
||||
- xfsprogs
|
||||
- yavdr-i18n
|
||||
state: present
|
||||
install_recommends: no
|
||||
- name: apt | install extra packages
|
||||
apt:
|
||||
name: '{{ extra_packages }}'
|
||||
state: present
|
||||
install_recommends: no
|
19
roles/yavdr-common/tasks/create_directories.yml
Normal file
19
roles/yavdr-common/tasks/create_directories.yml
Normal file
@ -0,0 +1,19 @@
|
||||
- name: ensure /etc/yavdr exists
|
||||
file:
|
||||
path: /etc/yavdr
|
||||
state: directory
|
||||
mode: 0755
|
||||
|
||||
- name: touch /etc/yavdr/autoinstalled (this file must exist)
|
||||
file:
|
||||
path: /etc/yavdr/autoinstalled
|
||||
state: touch
|
||||
|
||||
- name: create media directories
|
||||
file:
|
||||
dest: '{{ item.value }}'
|
||||
owner: '{{ vdr.user }}'
|
||||
group: '{{ vdr.group }}'
|
||||
state: directory
|
||||
mode: '0777'
|
||||
with_dict: '{{ media_dirs }}'
|
6
roles/yavdr-common/tasks/create_sudoers.yml
Normal file
6
roles/yavdr-common/tasks/create_sudoers.yml
Normal file
@ -0,0 +1,6 @@
|
||||
- name: create /etc/sudoers.d/yavdr from template
|
||||
template:
|
||||
src: templates/yavdr.sudoers.j2
|
||||
dest: /etc/sudoers.d/yavdr
|
||||
mode: '0444'
|
||||
validate: visudo -cf %s
|
@ -1,97 +1,11 @@
|
||||
---
|
||||
# file: roles/yavdr-common/tasks/main.yml
|
||||
|
||||
- name: apt | prevent automatic installation of recommended packages
|
||||
template:
|
||||
src: templates/90-norecommends.j2
|
||||
dest: /etc/apt/apt.conf.d/90norecommends
|
||||
- name: use bash instead of dash
|
||||
shell: |
|
||||
echo "set dash/sh false" | debconf-communicate
|
||||
dpkg-reconfigure -f noninteractive dash
|
||||
- name: create vdr group
|
||||
group:
|
||||
gid: '{{ vdr.gid }}'
|
||||
state: present
|
||||
name: '{{ vdr.group }}'
|
||||
|
||||
- name: create vdr user
|
||||
user:
|
||||
name: '{{ vdr.user }}'
|
||||
group: '{{ vdr.group }}'
|
||||
uid: '{{ vdr.uid }}'
|
||||
home: '{{ vdr.home }}'
|
||||
shell: '/bin/bash'
|
||||
state: present
|
||||
append: true
|
||||
- name: disable release-upgrade notifications
|
||||
lineinfile:
|
||||
dest: /etc/update-manager/release-upgrades
|
||||
backrefs: yes
|
||||
state: present
|
||||
regexp: '^(Prompt=).*$'
|
||||
line: '\1never'
|
||||
- name: add PPAs
|
||||
apt_repository:
|
||||
repo: '{{ item }}'
|
||||
state: present
|
||||
update_cache: yes
|
||||
with_items: '{{ repositories }}'
|
||||
|
||||
- name: run apt-get dist-upgrade
|
||||
apt:
|
||||
upgrade: dist
|
||||
update_cache: yes
|
||||
- name: apt | install basic packages
|
||||
apt:
|
||||
name: '{{ item }}'
|
||||
state: present
|
||||
install_recommends: no
|
||||
with_items:
|
||||
- anacron
|
||||
- acl
|
||||
- at
|
||||
- bash-completion
|
||||
#- biosdevname # caution: may change device names after a minimal installation!
|
||||
- debconf-utils
|
||||
- linux-firmware
|
||||
- psmisc
|
||||
- python-kmodpy
|
||||
- python-requests
|
||||
- python-usb
|
||||
- python3-usb
|
||||
- software-properties-common
|
||||
- ssh
|
||||
- wget
|
||||
- wpasupplicant
|
||||
- usbutils
|
||||
- xfsprogs
|
||||
- name: apt | install extra packages
|
||||
apt:
|
||||
name: '{{ item }}'
|
||||
state: present
|
||||
install_recommends: no
|
||||
with_items:
|
||||
'{{ extra_packages }}'
|
||||
- name: get information about usb and pci hardware and loaded kernel modules
|
||||
hardware_facts:
|
||||
usb: True
|
||||
pci: True
|
||||
modules: True
|
||||
gpus: True
|
||||
|
||||
- debug:
|
||||
var: '{{ item }}'
|
||||
verbosity: 1
|
||||
with_items:
|
||||
- usb
|
||||
- pci
|
||||
- gpus
|
||||
- modules
|
||||
- name: create media directories
|
||||
file:
|
||||
dest: '{{ item.value }}'
|
||||
owner: '{{ vdr.user }}'
|
||||
group: '{{ vdr.group }}'
|
||||
state: directory
|
||||
mode: '0777'
|
||||
with_dict: '{{ media_dirs }}'
|
||||
- name: basic installation
|
||||
block:
|
||||
- import_tasks: configure_apt.yml
|
||||
- import_tasks: configure_system.yml
|
||||
- import_tasks: create_directories.yml
|
||||
- import_tasks: create_sudoers.yml
|
||||
- import_tasks: standby_support.yml
|
||||
tags: [install]
|
||||
|
11
roles/yavdr-common/tasks/standby_support.yml
Normal file
11
roles/yavdr-common/tasks/standby_support.yml
Normal file
@ -0,0 +1,11 @@
|
||||
- name: create /usr/local/bin/module-helper
|
||||
template:
|
||||
src: templates/module-helper.j2
|
||||
dest: /usr/local/bin/module-helper
|
||||
mode: '0755'
|
||||
|
||||
- name: create standby hooks /lib/systemd/system-sleep/yavdr
|
||||
template:
|
||||
src: templates/system-sleep_yavdr.j2
|
||||
dest: /lib/systemd/system-sleep/yavdr
|
||||
mode: '0755'
|
@ -1,4 +1,4 @@
|
||||
{{ ansible_managed_file | comment('c') }}
|
||||
{{ ansible_managed | comment('c') }}
|
||||
// Recommends are as of now still abused in many packages
|
||||
APT::Install-Recommends "0";
|
||||
APT::Install-Suggests "0";
|
||||
|
77
roles/yavdr-common/templates/module-helper.j2
Normal file
77
roles/yavdr-common/templates/module-helper.j2
Normal file
@ -0,0 +1,77 @@
|
||||
#!/usr/bin/env python3
|
||||
# {{ ansible_managed | comment }}
|
||||
# based on http://www.e-tobi.net/blog/files/module-helper
|
||||
# http://www.e-tobi.net/blog/2010/11/06/squeeze-vdr-teil-9-suspend-to-ram
|
||||
# ported to python3 by Alexander Grothe
|
||||
#
|
||||
# This script resolves linux kernel module dependencies automatically, so only
|
||||
# the base module has to be specified (e.g. dvb_core)
|
||||
|
||||
import argparse
|
||||
import subprocess
|
||||
import pickle
|
||||
|
||||
dependency_map = {}
|
||||
|
||||
|
||||
def find_dependencies(module, dependencies=[]):
|
||||
dependencies.append(module)
|
||||
if module in dependency_map:
|
||||
for dependency in dependency_map[module]:
|
||||
find_dependencies(dependency, dependencies)
|
||||
return dependencies
|
||||
|
||||
|
||||
def build_module_dependency_map():
|
||||
with subprocess.Popen(['lsmod'],
|
||||
stdout=subprocess.PIPE,
|
||||
universal_newlines=True
|
||||
) as p:
|
||||
for line in p.stdout:
|
||||
values = line.split()
|
||||
if len(values) > 3:
|
||||
#print("module {} depends on {}".format(values[0], values[3]))
|
||||
dependency_map[values[0]] = values[3].split(',')
|
||||
|
||||
|
||||
def run_command_on_module_list(command, module_list):
|
||||
for module in module_list:
|
||||
cmd = [command, module]
|
||||
subprocess.call(cmd)
|
||||
|
||||
|
||||
def create_argparser():
|
||||
parser = argparse.ArgumentParser(description="load or unload modules")
|
||||
group = parser.add_mutually_exclusive_group()
|
||||
group.add_argument('-u', '--unload', metavar='MODULE', nargs='+',
|
||||
help='unload modules')
|
||||
group.add_argument('-r', '--reload', action='store_true',
|
||||
help='reload modules')
|
||||
parser.add_argument('-t', '--temp-file', nargs='?',
|
||||
default='/tmp/modules.list',
|
||||
help='''store names of unloaded modules in a file,
|
||||
default location is /tmp/modules.list''')
|
||||
return parser
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = create_argparser()
|
||||
args = parser.parse_args()
|
||||
if args.unload:
|
||||
build_module_dependency_map()
|
||||
all_modules = []
|
||||
for module in args.unload:
|
||||
all_modules.extend(find_dependencies(module))
|
||||
all_modules.reverse()
|
||||
try:
|
||||
with open(args.temp_file, 'wb') as f:
|
||||
pickle.dump(all_modules, f)
|
||||
run_command_on_module_list('rmmod', all_modules)
|
||||
except Exception as e:
|
||||
print(e)
|
||||
pass
|
||||
elif args.reload:
|
||||
with open(args.temp_file, 'rb') as f:
|
||||
all_modules = pickle.load(f)
|
||||
run_command_on_module_list('modprobe', all_modules)
|
||||
else:
|
||||
parser.print_help()
|
21
roles/yavdr-common/templates/system-sleep_yavdr.j2
Normal file
21
roles/yavdr-common/templates/system-sleep_yavdr.j2
Normal file
@ -0,0 +1,21 @@
|
||||
#!/bin/bash
|
||||
{{ ansible_managed | comment }}
|
||||
|
||||
case $1 in
|
||||
pre)
|
||||
/bin/systemctl stop vdr
|
||||
/usr/local/bin/module-helper -u dvb_core
|
||||
;;
|
||||
post)
|
||||
# reload rc-core keytables
|
||||
[ -x /usr/bin/ir-keytable ] && {
|
||||
for remote in $(ir-keytable 2>&1 | grep rc/rc | egrep -o "rc[0-9]{1,}")
|
||||
do
|
||||
ir-keytable -a /etc/rc_maps.cfg --sysdev $remote
|
||||
done
|
||||
}
|
||||
|
||||
/usr/local/bin/module-helper -r
|
||||
/bin/systemctl start vdr
|
||||
;;
|
||||
esac
|
2
roles/yavdr-common/templates/yavdr.sudoers.j2
Normal file
2
roles/yavdr-common/templates/yavdr.sudoers.j2
Normal file
@ -0,0 +1,2 @@
|
||||
{{ vdr.user }} ALL=NOPASSWD: /bin/systemctl --no-block restart vdr.service
|
||||
{{ vdr.user }} ALL=NOPASSWD: /bin/systemctl --no-block reboot
|
160
roles/yavdr-desktop/tasks/main.yml
Normal file
160
roles/yavdr-desktop/tasks/main.yml
Normal file
@ -0,0 +1,160 @@
|
||||
---
|
||||
# file: roles/yavdr-desktop/tasks/main.yml
|
||||
|
||||
- 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'
|
||||
- '{{ vdr.home }}/bin'
|
||||
|
||||
- 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 vdr's .Xresources"
|
||||
template:
|
||||
src: 'templates/.Xresources.j2'
|
||||
dest: '{{ vdr.home }}/.Xresources'
|
||||
mode: 0644
|
||||
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: 0644
|
||||
owner: '{{ vdr.user }}'
|
||||
group: '{{ vdr.group }}'
|
||||
|
||||
- name: expand rc2.xml for openbox on second display
|
||||
template:
|
||||
src: 'templates/openbox/rc2.xml.j2'
|
||||
dest: '{{ vdr.home }}/.config/openbox/rc2.xml'
|
||||
mode: 0644
|
||||
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: 0644
|
||||
owner: '{{ vdr.user }}'
|
||||
group: '{{ vdr.group }}'
|
||||
|
||||
- name: disable pulseaudio autospawning
|
||||
lineinfile:
|
||||
path: '{{ vdr.home }}/.config/pulse/client.conf'
|
||||
line: 'autospawn = yes'
|
||||
create: yes
|
||||
state: present
|
||||
owner: '{{ vdr.user }}'
|
||||
group: '{{ vdr.group }}'
|
||||
|
||||
- name: create tmux.service for the session
|
||||
template:
|
||||
src: 'templates/systemd/user/tmux.service.j2'
|
||||
dest: '{{ vdr.home }}/.config/systemd/user/tmux.service'
|
||||
mode: 0644
|
||||
owner: '{{ vdr.user }}'
|
||||
group: '{{ vdr.group }}'
|
||||
|
||||
- name: create wm-exit.service for the session
|
||||
template:
|
||||
src: templates/systemd/user/wm-exit.service.j2
|
||||
dest: '{{ vdr.home }}/.config/systemd/user/wm-exit.service'
|
||||
mode: 0644
|
||||
owner: '{{ vdr.user }}'
|
||||
group: '{{ vdr.group }}'
|
||||
|
||||
- name: create detect-second-display.service for the session
|
||||
template:
|
||||
src: templates/systemd/user/detect-second-display.service.j2
|
||||
dest: '{{ vdr.home }}/.config/systemd/user/detect-second-display.service'
|
||||
mode: 0644
|
||||
owner: '{{ vdr.user }}'
|
||||
group: '{{ vdr.group }}'
|
||||
|
||||
- name: create detect-second-diplay script
|
||||
template:
|
||||
src: templates/bin/detect-second-display.j2
|
||||
dest: '{{ vdr.home }}/bin/detect-second-display'
|
||||
mode: 0755
|
||||
owner: '{{ vdr.user }}'
|
||||
group: '{{ vdr.group }}'
|
||||
|
||||
- name: create switch-displays script
|
||||
template:
|
||||
src: templates/bin/switch-displays.j2
|
||||
dest: '{{ vdr.home }}/bin/switch-displays'
|
||||
mode: 0755
|
||||
owner: '{{ vdr.user }}'
|
||||
group: '{{ vdr.group }}'
|
||||
|
||||
- name: create openbox-second.service for the session
|
||||
template:
|
||||
src: templates/systemd/user/openbox-second.service.j2
|
||||
dest: '{{ vdr.home }}/.config/systemd/user/openbox-second.service'
|
||||
mode: 0644
|
||||
owner: '{{ vdr.user }}'
|
||||
group: '{{ vdr.group }}'
|
||||
|
||||
- name: create osd2web.service for the session
|
||||
template:
|
||||
src: templates/systemd/user/osd2web.service.j2
|
||||
dest: '{{ vdr.home }}/.config/systemd/user/osd2web.service'
|
||||
owner: '{{ vdr.user }}'
|
||||
group: '{{ vdr.group }}'
|
||||
mode: 0644
|
||||
|
||||
- name: create irexec configuration for the session
|
||||
block:
|
||||
- template:
|
||||
src: templates/systemd/user/irexec.service.j2
|
||||
dest: '{{ vdr.home }}/.config/systemd/user/irexec.service'
|
||||
mode: 0644
|
||||
owner: '{{ vdr.user }}'
|
||||
group: '{{ vdr.group }}'
|
||||
- template:
|
||||
src: templates/.lircrc.j2
|
||||
dest: '{{ vdr.home }}/.lircrc'
|
||||
mode: 0644
|
||||
owner: '{{ vdr.user }}'
|
||||
group: '{{ vdr.group }}'
|
||||
force: no
|
||||
|
||||
- name: set up udiskie
|
||||
include_tasks: udiskie.yml
|
||||
|
||||
- name: link /usr/bin/start-desktop to /var/lib/vdr/plugins/desktop/starter
|
||||
file:
|
||||
src: /usr/bin/start-desktop
|
||||
dest: /var/lib/vdr/plugins/desktop/starter
|
||||
state: link
|
||||
|
||||
- name: enable and start yavdr-xorg for the vdr user
|
||||
systemd:
|
||||
daemon_reload: yes
|
||||
name: 'yavdr-xorg'
|
||||
enabled: yes
|
||||
state: started
|
27
roles/yavdr-desktop/tasks/udiskie.yml
Normal file
27
roles/yavdr-desktop/tasks/udiskie.yml
Normal file
@ -0,0 +1,27 @@
|
||||
- name: install udiskie
|
||||
apt:
|
||||
name:
|
||||
- udiskie
|
||||
|
||||
- name: create ~/.config/udiskie
|
||||
file:
|
||||
name: '{{ vdr.home }}/.config/udiskie'
|
||||
state: directory
|
||||
|
||||
- name: expand template for udiskie's config.yml
|
||||
template:
|
||||
src: templates/udiskie/config.yml.j2
|
||||
dest: '{{ vdr.home }}/.config/udiskie/config.yml'
|
||||
|
||||
- name: expand template for mount helper script
|
||||
template:
|
||||
src: templates/udiskie/udiskie_vdr_mount_helper.j2
|
||||
dest: '{{ vdr.home }}/bin/udiskie_vdr_mount_helper'
|
||||
mode: 0755
|
||||
owner: vdr
|
||||
group: vdr
|
||||
|
||||
- name: expand template for udiskie vdr commands
|
||||
template:
|
||||
src: templates/udiskie/umount_all.j2
|
||||
dest: /usr/share/vdr/command-hooks/commands.udiskie.conf
|
16
roles/yavdr-desktop/templates/.Xresources.j2
Normal file
16
roles/yavdr-desktop/templates/.Xresources.j2
Normal file
@ -0,0 +1,16 @@
|
||||
xterm*background: Black
|
||||
xterm*foreground: grey
|
||||
XTerm*locale: true
|
||||
XTerm*metaSendsEscape: true
|
||||
XTerm*eightBitInput: false
|
||||
XTerm*backarrowKey: false
|
||||
XTerm*ttyModes: erase ^?
|
||||
Xterm*saveLines: 4096
|
||||
XTerm.vt100.metaSendsEscape: true
|
||||
XTerm.vt100.geometry: 80x32
|
||||
XTerm.vt100.renderFont: true
|
||||
xterm*faceName: xft:DejaVu Sans Mono
|
||||
xterm*faceSize: 14
|
||||
xterm*renderFont: true
|
||||
XTerm.vt100.faceName: xft:DejaVu Sans Mono:size=12:antialias=false
|
||||
XTerm.vt100.font: 7x13
|
5
roles/yavdr-desktop/templates/.lircrc.j2
Normal file
5
roles/yavdr-desktop/templates/.lircrc.j2
Normal file
@ -0,0 +1,5 @@
|
||||
begin
|
||||
prog = irexec
|
||||
button = KEY_HOME
|
||||
config = frontend-dbus-send switchbetween kodi vdr
|
||||
end
|
@ -1,3 +1,3 @@
|
||||
#!/bin/bash
|
||||
# {{ ansible_managed_file }}
|
||||
{{ ansible_managed | comment }}
|
||||
exec openbox-session
|
@ -0,0 +1,9 @@
|
||||
#!/bin/bash
|
||||
source <(systemctl --user show-environment)
|
||||
SECOND_DISPLAY="${DISPLAY%\.[0-9]*}.1"
|
||||
if xrandr -d "$SECOND_DISPLAY" -q | grep -q "connected"; then
|
||||
[ "$DISPLAY" != "$SECOND_DISPLAY" ] && d="DISPLAY=$SECOND_DISPLAY" || d="DISPLAY=$DISPLAY"
|
||||
echo "$d" > ~/.second_display;
|
||||
else
|
||||
rm -f ~/.second_display
|
||||
fi
|
9
roles/yavdr-desktop/templates/bin/switch-displays.j2
Normal file
9
roles/yavdr-desktop/templates/bin/switch-displays.j2
Normal file
@ -0,0 +1,9 @@
|
||||
#!/bin/bash
|
||||
source <(systemctl --user show-environment)
|
||||
[[ "$DISPLAY" =~ \.1$ ]] && DISPLAY="${DISPLAY%.1}.0" || DISPLAY="${DISPLAY%.0}.1"
|
||||
|
||||
frontend-dbus-send stop
|
||||
systemctl --user stop osd2web
|
||||
frontend-dbus-send setDisplay "$DISPLAY"
|
||||
systemctl --user start osd2web
|
||||
frontend-dbus-send start
|
@ -3,11 +3,13 @@
|
||||
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
|
||||
|
||||
feh --bg-center "/usr/share/yavdr/images/yavdr_logo.png"
|
||||
|
||||
enabled_services=(
|
||||
"tmux.service" "detect-second-display.service"
|
||||
"openbox-second.service" "osd2web.service"
|
||||
"yavdr-frontend.service" "pulseaudio.socket"
|
||||
"pulseaudio.service" "wm-exit.service")
|
||||
"pulseaudio.service" "wm-exit.service" "irexec.service")
|
||||
disabled_services=()
|
||||
|
||||
# enable configured services for the user session
|
||||
@ -26,3 +28,4 @@ fi
|
||||
|
||||
# start systemd units for the yavdr user session
|
||||
systemctl --user isolate yavdr-desktop.target
|
||||
udiskie &
|
@ -54,7 +54,7 @@
|
||||
S: shade (roll up/down)
|
||||
D: omnipresent (on all desktops).
|
||||
-->
|
||||
<keepBorder>yes</keepBorder>
|
||||
<keepBorder>no</keepBorder>
|
||||
<animateIconify>yes</animateIconify>
|
||||
<font place="ActiveWindow">
|
||||
<name>sans</name>
|
||||
@ -178,6 +178,27 @@
|
||||
</dock>
|
||||
<keyboard>
|
||||
<chainQuitKey>C-g</chainQuitKey>
|
||||
<!-- Keybindings for yavdr-frontend -->
|
||||
<keybind key="W-a">
|
||||
<action name="Execute">
|
||||
<command>frontend-dbus-send start</command>
|
||||
</action>
|
||||
</keybind>
|
||||
<keybind key="W-s">
|
||||
<action name="Execute">
|
||||
<command>frontend-dbus-send stop</command>
|
||||
</action>
|
||||
</keybind>
|
||||
<keybind key="W-x">
|
||||
<action name="Execute">
|
||||
<command>frontend-dbus-send switchbetween kodi vdr</command>
|
||||
</action>
|
||||
</keybind>
|
||||
<keybind key="XF86HomePage">
|
||||
<action name="Execute">
|
||||
<command>frontend-dbus-send toggle</command>
|
||||
</action>
|
||||
</keybind>
|
||||
<!-- Keybindings for desktop switching -->
|
||||
<keybind key="C-A-Left">
|
||||
<action name="GoToDesktop">
|
||||
@ -321,22 +342,6 @@
|
||||
<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>
|
||||
@ -796,21 +801,39 @@
|
||||
<applications>
|
||||
<application title="softhddevice">
|
||||
<decor>no</decor>
|
||||
<maximized>true</maximized>
|
||||
<maximized>yes</maximized>
|
||||
<!--<skip_pager>yes</skip_pager>-->
|
||||
<skip_taskbar>no</skip_taskbar>
|
||||
</application>
|
||||
<application title="softhdcuvid">
|
||||
<decor>no</decor>
|
||||
<maximized>yes</maximized>
|
||||
<!--<skip_pager>yes</skip_pager>-->
|
||||
<skip_taskbar>no</skip_taskbar>
|
||||
</application>
|
||||
<application title="vaapidevice">
|
||||
<decor>no</decor>
|
||||
<maximized>yes</maximized>
|
||||
<!--<skip_pager>yes</skip_pager>-->
|
||||
<skip_taskbar>no</skip_taskbar>
|
||||
</application>
|
||||
<application class="VDR">
|
||||
<decor>no</decor>
|
||||
<maximized>yes</maximized>
|
||||
<!--<skip_pager>yes</skip_pager>-->
|
||||
<skip_taskbar>no</skip_taskbar>
|
||||
</application>
|
||||
<application title="browser">
|
||||
<decor>no</decor>
|
||||
<maximized>true</maximized>
|
||||
<maximized>yes</maximized>
|
||||
<!--<skip_pager>yes</skip_pager>-->
|
||||
<skip_taskbar>yes</skip_taskbar>
|
||||
<skip_taskbar>no</skip_taskbar>
|
||||
</application>
|
||||
<application title="osd2Web">
|
||||
<decor>no</decor>
|
||||
<maximized>true</maximized>
|
||||
<maximized>yes</maximized>
|
||||
<!--<skip_pager>yes</skip_pager>-->
|
||||
<skip_taskbar>yes</skip_taskbar>
|
||||
<skip_taskbar>no</skip_taskbar>
|
||||
</application>
|
||||
</applications>
|
||||
</openbox_config>
|
@ -7,7 +7,7 @@
|
||||
<screen_edge_strength>20</screen_edge_strength>
|
||||
</resistance>
|
||||
<focus>
|
||||
<focusNew>yes</focusNew>
|
||||
<focusNew>no</focusNew>
|
||||
<!-- always try to focus new windows when they appear. other rules do
|
||||
apply -->
|
||||
<followMouse>no</followMouse>
|
||||
@ -54,7 +54,7 @@
|
||||
S: shade (roll up/down)
|
||||
D: omnipresent (on all desktops).
|
||||
-->
|
||||
<keepBorder>yes</keepBorder>
|
||||
<keepBorder>no</keepBorder>
|
||||
<animateIconify>yes</animateIconify>
|
||||
<font place="ActiveWindow">
|
||||
<name>sans</name>
|
||||
@ -321,22 +321,6 @@
|
||||
<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>
|
||||
@ -796,21 +780,39 @@
|
||||
<applications>
|
||||
<application title="softhddevice">
|
||||
<decor>no</decor>
|
||||
<maximized>true</maximized>
|
||||
<maximized>yes</maximized>
|
||||
<!--<skip_pager>yes</skip_pager>-->
|
||||
<skip_taskbar>yes</skip_taskbar>
|
||||
<skip_taskbar>no</skip_taskbar>
|
||||
</application>
|
||||
<application title="softhdcuvid">
|
||||
<decor>no</decor>
|
||||
<maximized>yes</maximized>
|
||||
<!--<skip_pager>yes</skip_pager>-->
|
||||
<skip_taskbar>no</skip_taskbar>
|
||||
</application>
|
||||
<application title="vaapidevice">
|
||||
<decor>no</decor>
|
||||
<maximized>yes</maximized>
|
||||
<!--<skip_pager>yes</skip_pager>-->
|
||||
<skip_taskbar>no</skip_taskbar>
|
||||
</application>
|
||||
<application class="VDR">
|
||||
<decor>no</decor>
|
||||
<maximized>yes</maximized>
|
||||
<!--<skip_pager>yes</skip_pager>-->
|
||||
<skip_taskbar>no</skip_taskbar>
|
||||
</application>
|
||||
<application title="browser">
|
||||
<decor>no</decor>
|
||||
<maximized>true</maximized>
|
||||
<maximized>yes</maximized>
|
||||
<!--<skip_pager>yes</skip_pager>-->
|
||||
<skip_taskbar>yes</skip_taskbar>
|
||||
<skip_taskbar>no</skip_taskbar>
|
||||
</application>
|
||||
<application title="osd2Web">
|
||||
<decor>no</decor>
|
||||
<maximized>true</maximized>
|
||||
<maximized>yes</maximized>
|
||||
<!--<skip_pager>yes</skip_pager>-->
|
||||
<skip_taskbar>yes</skip_taskbar>
|
||||
<skip_taskbar>no</skip_taskbar>
|
||||
</application>
|
||||
</applications>
|
||||
</openbox_config>
|
@ -0,0 +1,10 @@
|
||||
[Unit]
|
||||
Description=Detect second DISPLAY using xrandr
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
RemainAfterExit=yes
|
||||
ExecStart=%h/bin/detect-second-display
|
||||
|
||||
[Install]
|
||||
WantedBy=yavdr-desktop.target
|
@ -0,0 +1,9 @@
|
||||
[Unit]
|
||||
Description=LIRC command handler
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
ExecStart=/usr/bin/irexec %h/.lircrc
|
||||
|
||||
[Install]
|
||||
WantedBy=yavdr-desktop.target
|
@ -6,9 +6,10 @@ 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
|
||||
ExecStart=/usr/bin/openbox --config-file %h/.config/openbox/rc2.xml
|
||||
ExecStartPost=/usr/bin/xset -dpms s off -display $DISPLAY
|
||||
ExecStartPost=/bin/bash %h/.fehbg
|
||||
|
||||
[Install]
|
||||
WantedBy=yavdr-desktop.target
|
@ -6,8 +6,10 @@ 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"'
|
||||
Environment=url="http://localhost:4444/skins/horchiTft/index.html?theme=anthraize&onlyView=1"
|
||||
Environment=browser="kiosk-browser"
|
||||
EnvironmentFile=-%h/.config/osd2web/config
|
||||
ExecStart=/usr/bin/on_vdr -o -c '${browser} "${url}"'
|
||||
KillSignal=SIGINT
|
||||
|
||||
[Install]
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user