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

    systemd integration for kodi & emulationstation

    Ideas and Development
    kodi systemd retropie config essystem guide
    1
    1
    56
    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.
    • mdx
      mdx last edited by mdx

      Hello,

      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).
      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 and may be commented out. 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
      ExecStartPre=+sh -c 'fbset | grep -Pom1 "geometry.* \K[0-9]+$" | xargs -ri systemctl set-environment ORIGINAL_DEPTH={}'
      ExecStart=kodi-standalone
      ExecStopPost=+sh -c 'ip route show default | cut -f3 -d" " | xargs ping -c1 -w3 -q'
      ExecStopPost=+sh -c "systemctl start emulationstation && systemctl -q is-active emulationstation || systemctl start getty@tty1"
      StandardOutput=journal
      StandardError=journal
      TTYPath=/dev/tty1
      
      [Install]
      WantedBy=multi-user.target
      
      1. Emulation station 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
      ExecStart=/usr/bin/emulationstation
      ExecStopPost=+systemctl start kodi
      StandardOutput=journal
      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/10_controls.conf 
      [Unit]
      ConditionPathExists=|/dev/input/js0
      

      To allow quitting to getty from kodi when the joypad is plugged in, create a /dev/shm/getty file (via ssh):

      # cat /etc/systemd/system/emulationstation.service.d/10_force_getty.conf
      [Unit]
      ConditionPathExists=!/dev/shm/getty
      
      1. Mandatory TTY redirection for emulationstation. The problem here is emulationstation needs a tty for standard input. By default a service receives /dev/null for standard input. Without this service drop-in, emulationstation or emulators will face input problems. /dev/tty1 is normally owned by root so to grant direct access, it needs to be made world-writable:
      # cat /etc/systemd/system/emulationstation.service.d/10_tty.conf 
      [Service]
      TTYPath=/dev/tty1
      StandardOutput=tty
      StandardInput=tty
      ExecStartPre=!chmod o+rw /dev/tty1
      
      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.

      Restores console depth post kodi (or emulationstation failure. If it fails, kodi will be started. On a log out from getty on tty1, it will run kodi.

      # cat /etc/systemd/system/getty@tty1.service.d/post_kodi_failure.conf 
      [Unit]
      OnFailure=kodi.service
      [Service]
      ExecStartPre=fbset -depth $ORIGINAL_DEPTH
      ## Commented out - detect if keyboard is attached and fail to run getty if none is found. However, when none found it has the side effect of leading to a failure of the service (systemd rev 246 in buster is missing the ConditionExec statement that doesn't fail a service)
      #ExecStartPre=sh -c 'grep -l 03 /sys/bus/*/*/*/bInterfaceClass | sed s/Class$$/Protocol/ | xargs grep -q 01'
      ExecStart=
      ExecStart=-/sbin/agetty --autologin pi --noclear %I $TERM
      ExecStopPost=+systemctl start kodi
      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
      
      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
      [Unit]
      Conflicts="kodi.service emulationstation.service"
      

      Ensure the console on tty1 is not cleared.

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

      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
      • Referenced by  mdx mdx 
      • Referenced by  mdx mdx 
      • Referenced by  mdx mdx 
      • 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.