RetroPie forum home
    • Recent
    • Tags
    • Popular
    • Home
    • Docs
    • Register
    • Login

    systemd integration for kodi & emulationstation

    Scheduled Pinned Locked Moved Ideas and Development
    kodisystemdretropie configessystemguide
    1 Posts 1 Posters 782 Views
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • M
      mdx
      last edited by mdx

      Hello,

      UPDATED: 07/06/2022. Added tvservice -c entries for dispmanx_vnc support. Some users may choose to run their RetroPie without a physical display over dispmanx_vnc.

      I'd like to share a few systemd service definitions that enable running kodi & emulationstation back to back.

      To use these services:

      1. Disable the existing entries in /opt/retropie/configs/all/autostart.sh (which is what retropie typically uses to run those) or remove /etc/profile.d/10-retropie.sh (which triggers /opt/retropie/configs/all/autostart.sh) when logged in.
      2. Install the fbset package.

      How the services are supposed to work:

      1. Kodi runs after boot by default, which is defined via the following systemd link:
      # ls -la /etc/systemd/system/multi-user.target.wants/kodi.service 
      lrwxrwxrwx 1 root root 32 Aug 18  2021 /etc/systemd/system/multi-user.target.wants/kodi.service -> /etc/systemd/system/kodi.service
      

      It may be modified to run emulationstation by removing the above link to kodi and adding one pointing to emulationstation.service:

      lrwxrwxrwx 1 root root 32 Aug 18  2021 /etc/systemd/system/multi-user.target.wants/emulationstation.service -> /etc/systemd/system/emulationstation.service
      
      1. Kodi service definition. Of note, the service intentionally conflicts with emulationstation on purpose, rendering the startup of both impossible.
        On kodi shut down, the service will start emulationstation.
        Should kodi fail to start, a getty on the initial tty (tty1) is started. The getty definition is included below. The pulseaudio related parts are relevant for starting pulseaudio (as a system-wide service) alongside kodi. Either comment them out or follow the guide for glitchless playback to install them. Note this service sets original depth to allow restoring it easily by getty.
      # cat /etc/systemd/system/kodi.service 
      [Unit]
      Description=kodi
      After=pulseaudio.service
      BindsTo=pulseaudio.service
      Conflicts=emulationstation.service
      OnFailure=getty@tty1.service
      
      [Service]
      User=pi
      Environment=PULSE_SERVER=/run/pulse/native
      # If screen is off, we enable it here (NTSC 4:3 is the default when no display is plugged in)
      ExecStartPre=sh -c 'tvservice -s | grep -v off || tvservice -c "NTSC 4:3"'
      # Record original depth to restore it later
      ExecStartPre=+sh -c 'fbset | grep -Pom1 "geometry.* \K[0-9]+$" | xargs -ri systemctl set-environment ORIGINAL_DEPTH={}'
      ExecStart=kodi-standalone
      StandardOutput=journal
      StandardError=journal
      TTYPath=/dev/tty1
      
      [Install]
      WantedBy=multi-user.target
      

      Drop-in that controls the service spawned after kodi service completes (successfully or not):

      # cat /etc/systemd/system/kodi.service.d/quit_to_es.conf 
      [Service]
      # Missing OnSuccess in systemd 241, quit to es or fall back to getty@tty1
      ExecStopPost=+sh -c 'case $${EXIT_STATUS} in 0) systemctl start emulationstation;; *) systemctl start getty@tty1;; esac'
      
      1. Emulationstation service. Likewise, it conflicts with kodi to prevent startup of both at the same time. On failure, it will run getty on tty1. On emulationstation shut down this service will run kodi.
      # cat /etc/systemd/system/emulationstation.service
      [Unit]
      Description=emulationstation
      Conflicts=kodi.service
      OnFailure=getty@tty1.service
      
      [Service]
      User=pi
      # getty@tty1 hogs /dev/tty1, preventing input to amiberry and the runcommand menu, we stop it if it is still running
      ExecStartPre=+sh -c 'systemctl is-active getty@tty1 && systemctl stop getty@tty1 || systemctl reset-failed getty@tty1'
      # Enable screen if it is still off
      ExecStartPre=sh -c 'tvservice -s | grep -v off || tvservice -c "NTSC 4:3"'
      ExecStart=/usr/bin/emulationstation
      ExecStopPost=+systemctl start kodi
      # Key part: ensure the emulationstation process owns /dev/tty1; without this runcommand input & output won't work
      StandardInput=tty-force
      StandardOutput=tty
      StandardError=journal
      TTYPath=/dev/tty1
      
      [Install]
      WantedBy=multi-user.target
      
      1. Additional drop-in: if no joypad is plugged in, emulationstation will not start. In which case, fall back to kodi. It isn't strictly necessary when you are ok with emulationstation starting without a joypad (but it might make you unable to control it without one).
        It's particularly useful when there isn't any keyboard connected to your raspberry pi and the only controls are either the joypad (attached or not) and the CEC-driven input (a tv remote).

      When emulationstation allows fall-back control via CEC input, this drop-in will be redundant.

      # cat /etc/systemd/system/emulationstation.service.d/require_controls.conf
      [Unit]
      ConditionPathExists=|/dev/input/js0
      
      1. Getty configuration, updated via drop-ins. Specific to the getty instance on tty1, gettys on other ttys are not impacted by these drop-ins.
      # cat /etc/systemd/system/getty@tty1.service.d/post_kodi_failure.conf
      [Service]
      # Reset output if off, keep dispmanx_vnc on
      ExecStartPre=sh -c 'tvservice -s | grep -v off || tvservice -c "NTSC 4:3"'
      # Restores console after kodi depth changes
      ExecStartPre=-fbset -depth $ORIGINAL_DEPTH
      # Autologin to pi
      ExecStart=
      ExecStart=-/sbin/agetty --autologin pi --noclear %I $TERM
      # Stop all spawned processes including login to avoid hogging /dev/tty1
      KillMode=control-group
      # Allow quitting to kodi or emulationstation
      Restart=no
      

      On a default raspbian build, getty is normally configured to run on boot. Since it will be either kodi or emulationstation that run on the console, getty startup on boot needs to be disabled. Getty will still run when kodi or emulationstation fail.

      # ls -la /etc/systemd/system/multi-user.target.wants/getty.target 
      lrwxrwxrwx 1 root root 9 May 11 10:47 /etc/systemd/system/multi-user.target.wants/getty.target -> /dev/null
      

      These two drop-ins control what happens when getty process finishes (or dies). They're numbered sequentially to indicate the parsing order for systemd. kodi runs by default. If emulationstation service exists, it replaces (note OnFailureJobMode=replace) kodi.

      The last service from systemctl show prevails:

      # systemctl show getty@tty1 | grep OnFailure
      OnFailure=kodi.service emulationstation.service
      OnFailureJobMode=replace
      

      Admittedly, these drop-ins are a hack: systemd 241 from buster doesn't support starting a service when getty@tty1 completes successfully other than by triggering a pretend failure. When a more recent systemd with OnSuccess is available, ExecStopPost=false may be removed and OnFailure amended to OnSuccess.

      # cat /etc/systemd/system/getty@tty1.service.d/01_quit_to_kodi.conf
      [Unit]
      OnFailure=kodi.service 
      [Service]
      # Missing OnSuccess in systemd 241, triggers failure to run OnFailure process
      ExecStopPost=false
      
      # cat /etc/systemd/system/getty@tty1.service.d/02_quit_to_es.conf
      [Unit]
      OnFailure=emulationstation.service 
      # Replace other queued failure processes
      OnFailureJobMode=replace
      [Service]
      # Missing OnSuccess in systemd 241, triggers failure to run OnFailure process
      ExecStopPost=false
      
      1. Getty service drop-in updates. Specific to the getty session on tty1.

      Do not run getty on tty1 when either kodi or emulationstation is active.

      # cat /etc/systemd/system/getty@tty1.service.d/conflicts.conf
      [Unit]
      Conflicts=emulationstation.service kodi.service
      

      Ensure the console on tty1 is not cleared.

      # cat /etc/systemd/system/getty@tty1.service.d/noclear.conf
      [Service]
      TTYVTDisallocate=no
      

      Do not run getty without a keyboard. It properly detects the dispmanx_vnc virtual keyboard.

      # cat /etc/systemd/system/getty@tty1.service.d/require_keyboard.conf
      [Service]
      ExecStartPre=sh -c 'grep -l 03 /sys/bus/*/*/*/bInterfaceClass | sed s/Class$$/Protocol/ | xargs grep -q 01 || grep -qi Keyboard /proc/bus/input/devices'
      

      I've had this running for quite some time and it works flawlessly.

      These services capture kodi & emulationstation console output in the systemd journal, viewable via:

      # journalctl -u emulationstation
      # journalctl -u kodi
      

      One caveat of how these services operate is restarting one service twice brings up the other service. Other than that, in regular operation without systemctl restarts, the services run truly back to back.

      [emulationstation running]
      # systemctl restart kodi
      [brings up kodi]
      # systemctl restart kodi
      Job for kodi.service canceled.
      [brings up emulationstation]
      
      1 Reply Last reply Reply Quote 0
      • M mdx referenced this topic on
      • M mdx referenced this topic on
      • M mdx referenced this topic on
      • First post
        Last post

      Contributions to the project are always appreciated, so if you would like to support us with a donation you can do so here.

      Hosting provided by Mythic-Beasts. See the Hosting Information page for more information.