RasPi4 with touch screen as living room media center with TV/Beamer autoswitch

By dose | September 13, 2023
Under: Uncategorized

I recently got a RasPi4 with official 7″ touch screen in a case and wanted to
make this my living-room media control center. I attached a video beamer to its
HDMI port (would also work for a TV set) and installed KODI.
My goal was to automatically restart Kodi and execute it on the video projector
screen, as soon as I turn on the device and restart it on the internal touch
screen when the device gets turned off again.
This way I can use the internal touch screen to i.e. listen to Internet Radio
or other live streams using the RasPi conveniently and also use it as a video
entertainment center when turning on the beamer.
This turned out to be not as easy as I initially thought it would be.

First of all, RaspiOS nowadays ships with the KMS/DRM video stack per default.
This is good for hardware accelleration and has a few other advantages, but is
bad for compatibility with the internal 7″ touchscreen display and KODI.
Here are the problems that I encountered:

  1. Current RaspiOS is based on debian Bullseye and only ships with KODI 19.
    However, KODI 19 is missing a feature where its KMS backend can detect
    multiple attached Screens (so in my case: Internal DSI-1 display and
    external HDMI-1 display). So do most of the specialised Mediacenter
    distributions like LibreELEC.
    The first version that ships with KODI 20 is based on Debian Bookworm.
    So RasPi needs to be updated to Debian Bookworm for KODI 20.
  2. KODI 20 supports the detection of multiple screens (only can use one
    of them at the same time, but that’s not a problem for me yet), but
    it doesn’t support screen rotation in its KMS backend and doesn’t
    obey the console rotation settings. This was a problem in my case, as
    the screen got mounted upside-down in the case and due to the way the
    case was designed, this also couldn’t be changed physically.
    There is very few documentation about the KMS-DRM stack regarding rotation,
    so I had to spend a huge amount of time into reading about the workings
    of the KMS/DRM graphics stack, as most docuemntation just refers to X,
    which isn’t used by KODI on RasPi (and shouldn’t be because of lack
    in hardware accelleration).
  3. The libcec library, that also
    gets used by KODI internally for i.e. using the remote control of an
    attached HDMI-device and other stuff, demands exclusive access to the
    CEC interface, therefore I cannot monitor the CEC power status via
    another libcec-Based daemon like
    libcec-daemon
    concurrently.
  4. The FMKS-driver (vc4-fkms-v3d) supports rotation of the screen via
    firmware, but doesn’t seem to detect HDMI properly (with attached
    device in standby) and also doesn’t offer
    CEC kernel support.
    Therefore it is also unusable for my project.

So, how to solve all of these problems?

  1. Easy, just upgrade the OS to bookworm and we have a working KODI 20.
  2. Unfortunately, there didn’t seem to be a solution for KODI at the
    time of writing. It just doesn’t have a setting for screen rotation
    and the KMS-DRM requires the application driving the video screen to
    set rotation itself. The Raspi-Docs just know about on how to let X
    rotate the screen which isn’t what we need.
    Therefore the only solution to this is to recompile kodi with a
    hardcoded rotation for the internal DSI-1 port.
    I made a little patch for Kodi and recompiled it for Debian bookworm
    and documented everything in this
    Github-Issue. It also documents on how to rotate the touch screen.
    If you have the “brilliant” idea to rotate the screen from another
    application by setting the rotation property of the active screen locked
    by Kodi, like I did, I must disappoint you: You get “access denied”
    in this case, so you have to bite the bullet and recompile kodi.
    Altough I already provide a Debian package for it on the linked issue,
    you can take the patch from there and recompile Kodi yourself, if you
    want.
    Approximately, this is something like:

       apt install build-essential devscripts
       apt source kodi
       apt build-dep kodi
       # Apply patch here
       export DEB_BUILD_OPTIONS="lang=en-US ccache nocheck"
       export EMAIL='leecher@dose.0wnz.at'
       dch -n
       debuild -us -uc -nc
  3. As libcec-daemon wasn’t usable for me due to mentioned reasons, I
    wrote a little application to monitor the CEC0 port myself for changes
    in power status and then execute a shell-script that restarts KODI
    on change. The program is available in this github repo.

So in order to make the same installation as I did, here is a step-by-step
guide:

    1. Install RapiOS Bookworm
      At the time of writing, Debian Bookworm wasn’t available as ready-made
      distribution for the RasPi 4, so I had to install RaspiOS Bullseye and
      then upgrade it.
      If RaspOS based on Debian Bookworm or later is already available when you are
      reading this, just install it with the RasPi Imager and you are good to go.
      I selected the following
      * Raspberry Pi OS (other)
      * Raspberry Pi OS Lite (32-bit)Then, upgrade the newly-installed system(as root):

      apt update
      apt upgrade --without-new-pkgs
      sed -i 's/bullseye/bookworm/g' /etc/apt/sources.list
      sed -i 's/bullseye/bookworm/g' /etc/apt/sources.list.d/*
      apt update
      apt full-upgrade
      reboot
    2. Install KODI (as root)
      apt install kodi socat

      2a) If your screen is swapped, install special 180° rotated version of KODI
      (as root)

      wget https://github.com/xbmc/xbmc/files/12452936/kodi-bin_20.0%2Bdfsg-2.1_armhf.zip
      unzip kodi-bin_20.0+dfsg-2.1_armhf.zip
      rm kodi-bin_20.0+dfsg-2.1_armhf.zip
      dpkg -i kodi-bin_20.0+dfsg-2.1_armhf.deb
      sed -i "s/kodi-bin (<< 2:20.0+dfsg-2.1~), //g" /var/lib/dpkg/status
      vi /boot/cmdline.txt
      #add at the end of the first line:
        video=DSI-1:800x480M,rotate=180
      echo 'ACTION=="add|change", KERNEL=="event[0-9]*", ENV{LIBINPUT_CALIBRATION_MATRIX}="-1 0 1 0 -1 1"' >/etc/udev/rules.d/90-libinput-rotate.rules
    3. Install cec-powmon and necessary scripts (as normal user)
      Ensure that you are running as normal user and not as root!

      cd ~
      wget https://github.com/leecher1337/cecpowmon/archive/refs/heads/main.zip
      unzip main.zip
      rm main.zip
      mv cecpowmon-main cecpowmon
      cd cecpowmon
      make
      vi restart_kodi.sh
      #!/bin/sh
      echo '{"jsonrpc":"2.0","method":"Application.Quit","id":1}' | socat -t 1 - TCP-CONNECT:localhost:9090
      chmod 755 restart_kodi.sh
      vi start_kodi.sh
      #!/bin/sh
      # Configure CEC for first use
      cec-ctl -d 0 --tv -S
       
      # Wait for HDMI status
      while :
      do
          STATUS=`cec-ctl --give-device-power-status --to 0`
          echo "$STATUS" | grep "pwr-state" >/dev/null
          if [ $? -eq 0 ]; then
            break
          fi
          sleep 2
      done
      echo "$STATUS" | grep pwr-state | grep "on".
      if [ $? -eq 0 ]; then.
          OUTPUT=HDMI-A-1
          SKIN=skin.estuary
      else.
          OUTPUT=DSI-1
          SKIN=skin.estouchy
      fi
      echo "$OUTPUT$SKIN" >~/.kodi/userdata/advancedsettings.xml
      /usr/bin/kodi --standalone
      chmod 755 start_kodi.sh
      mkdir -p ~/.kodi/userdata/
      sudo vi /etc/systemd/system/kodi.service
      [Unit]
      Description=Kodi Media Center
      After=remote-fs.target network-online.target
      Wants=network-online.target
      
      [Service]
      User=[username]
      Type = simple
      ExecStart=/home/[username]/cecpowmon/start_kodi.sh
      ExecStop=/bin/kill -TERM $MAINPID
      TimeoutStopSec=5
      Restart=always
      RestartSec=2
      StartLimitInterval=0
      LimitNOFILE=16384
      SyslogIdentifier = kodi
      
      # lowering memory fragmentation
      # https://linux.die.net/man/3/mallopt
      # https://github.com/xbmc/xbmc/pull/11620
        Environment=MALLOC_MMAP_THRESHOLD_=131072
      
      # Workaround for high CPU load with nvidia GFX
        Environment=__GL_YIELD=USLEEP
      
      [Install]
      WantedBy= multi-user.target
      
      USER=`whoami` sudo sed -i "s/\[username\]/$USER/g" /etc/systemd/system/kodi.service
      sudo vi /etc/systemd/system/cecpowmon.service
      [Unit]
      Description=HDMI CEC Monitor
      After=kodi.service
      Requires=multi-user.target
      Wants=network-online.target
      
      [Service]
      ExecStart=/home/[username]/cecpowmon/cecpowmon /home/[username]/cecpowmon/restart_kodi.sh
      ExecStop=/bin/kill -TERM $MAINPID
      TimeoutStopSec=5
      Restart=always
      RestartSec=2
      StartLimitInterval=0
      LimitNOFILE=16384
      
      [Install]
      WantedBy=default.target
      
      USER=`whoami` sudo sed -i "s/\[username\]/$USER/g" /etc/systemd/system/cecpowmon.service
      sudo systemctl enable cecpowmon
      sudo systemctl enable kodi
      sudo systemctl daemon-reload
      sudo reboot

Now you should be greeted with KODI on one of the screens depending on
which you have turned on.

Leave a Comment

Name:

E-Mail :

Subscribe :
Website :

Comments :