Embedded Clementine Music Player

Project goals and background

Convert an Odroid-XU4 single board computer to a music “kiosk”. Connect it to my stereo receiver, and play my music collection via the Clementine music player.

The Clementine project is amazing, “Clementine is a modern music player and library organizer”. It is supported on multiple platforms and one of my favorite features is its Android remote control app, that lets you control the player from your phone. You should certainly check it out if you haven’t heard of it before: https://www.clementine-player.org/

For years I’ve been keeping a music collection on CDs (and also LPs hehe, but that will be dealt with another day). Most of the CDs have been imported into iTunes using the lossy AAC encoding. I wanted to switch over to using the Clementine player and re-rip the CDs using lossless FLAC encoding. With that arduous task done, I was ready to replace my CD player (that I hardly use anyway) with the kiosk. I wonder if there is someone out there that would pay money for a sweet Sony 5 disk CD player and a milk crate full of CDs?

Let the fun begin.

Setting up Ubuntu on the XU4

Here we will do some basic security hardening, customization, and service setup.

Change the root password from “odroid”

https://www.cyberciti.biz/faq/change-root-password-ubuntu-linux/

The procedure to change the root user password on Ubuntu Linux:

Type the following command to become root user and issue passwd:

sudo -i
passwd

OR set a password for root user in a single step:

sudo passwd root

Test your new root password by typing the following command:

su -

After entering the new root password, you will be elevated to be the root user.

Change the odroid user’s password

Simply use the passwd command while logged in as odroid.

passwd

Then logout and login again, or reboot.

Change the machine’s hostname

https://www.cyberciti.biz/faq/ubuntu-change-hostname-command/

The procedure to change the computer name on Ubuntu Linux:

Type the following command to edit /etc/hostname using nano or vi text editor:

sudo nano /etc/hostname

Delete the old name and setup a new name. Next Edit the /etc/hosts file:

sudo nano /etc/hosts

Replace any occurrence of the existing computer name with your new one. Reboot the system for changes to take effect:

sudo reboot

Display the current Ubuntu hostname (as a test). Simply type the following command:

hostname

WiFi Configuration

If using a WiFi network, set that up and allow all users to use the network.

https://askubuntu.com/questions/16376/connect-to-network-before-user-login

Disable automatic login

https://askubuntu.com/questions/106428/how-to-disable-automatic-login-in-lightdm

sudo gpasswd -d <user> nopasswdlogin

Change <user> to your user name (in our case “odroid”).

Then logout and login again, or reboot. You should be required to enter a password in order to log in.

(Paranoid) is odroid the only admin user?

https://askubuntu.com/questions/611584/how-could-i-list-all-super-users

Check to see which users are in the sudo group.

getent group sudo | cut -d: -f4

Building Clementine

We will roughly follow instructions provided for installing/building Clementine provided here:

https://github.com/clementine-player/Clementine/wiki/Clementine-on-Raspberry-Pi

The instructions are a bit out of date, at least with respect to the latest version of Ubuntu running on an ARM system. It is actually difficult if not ill advised to try to install the current ARM Clementine .deb package since many of the dependency packages in Ubuntu 18.04 have advanced and there are many significant incompatibilities with the Latest official stable release of Clementine with an ARM build (v1.3.1). So we will build Clementine from source from the master branch!

As of this writing (6/18/2020), master was here:

:~/Clementine$ git log
commit 06544054a69433715442af7c86da60b321dd2cf0 (HEAD -> master, origin/master, origin/HEAD)
Author: Clementine Buildbot <buildbot@clementine-player.org>
Date:   Mon Jun 15 02:27:43 2020 +0000

Install dependencies

sudo apt-get install liblastfm-dev \
    libtag1-dev \
    gettext \
    libboost-dev \
    libboost-serialization-dev \
    libqt4-dev \
    qt4-dev-tools \
    libqt4-opengl-dev \
    cmake \
    libgstreamer1.0-dev \
    libgstreamer-plugins-base1.0-dev \
    libglew1.5-dev \
    libqjson-dev \
    libgpod-dev \
    libplist-dev \
    libusbmuxd-dev \
    libmtp-dev \
    libcdio-dev \
    protobuf-compiler \
    libprotobuf-dev \
    libcrypto++-dev \
    libfftw3-dev \
    libsparsehash-dev \
    libsqlite3-dev \
    libpulse-dev \
    libqtwebkit-dev \

    libechonest-dev \ # (Problem) E: Unable to locate package

    libchromaprint-dev \
    libqca2-dev

Dependency Installation Errors:

:~$ sudo apt-get install libechonest-dev
Reading package lists... Done
Building dependency tree
Reading state information... Done
E: Unable to locate package libechonest-dev

This is the Amazon Echo/Nest library, hopefully we don’t need it (we don’t).

Clone and build Clementine

https://github.com/clementine-player/Clementine/wiki/Clementine-on-Raspberry-Pi#get-the-source

git clone https://github.com/clementine-player/Clementine.git
cd Clementine/bin

No need to make a swap file because the XU4 is a beast :)

First pass configuration trace:

:~/Clementine/bin$ cmake ..
-- The C compiler identification is GNU 7.5.0
-- The CXX compiler identification is GNU 7.5.0
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
CMake Deprecation Warning at CMakeLists.txt:4 (cmake_policy):
  The OLD behavior for policy CMP0011 will be removed from a future version
  of CMake.

  The cmake-policies(7) manual explains that the OLD behaviors of all
  policies are deprecated and that a policy should be set to OLD only under
  specific short-term circumstances.  Projects should be ported to the NEW
  behavior and not rely on setting a policy to OLD.


-- Found PkgConfig: /usr/bin/pkg-config (found version "0.29.1")
-- Found OpenGL: /usr/lib/arm-linux-gnueabihf/libOpenGL.so
-- Boost version: 1.65.1
-- Found Gettext: /usr/bin/msgmerge (found version "0.19.8.1")
-- Looking for pthread.h
-- Looking for pthread.h - found
-- Looking for pthread_create
-- Looking for pthread_create - not found
-- Looking for pthread_create in pthreads
-- Looking for pthread_create in pthreads - not found
-- Looking for pthread_create in pthread
-- Looking for pthread_create in pthread - found
-- Found Threads: TRUE
-- Found Protobuf: /usr/lib/arm-linux-gnueabihf/libprotobuf.so;-lpthread (found version "3.0.0")
-- Could NOT find ALSA (missing: ALSA_LIBRARY ALSA_INCLUDE_DIR)
-- Looking for XOpenDisplay in /usr/lib/arm-linux-gnueabihf/libX11.so;/usr/lib/arm-linux-gnueabihf/libXext.so
-- Looking for XOpenDisplay in /usr/lib/arm-linux-gnueabihf/libX11.so;/usr/lib/arm-linux-gnueabihf/libXext.so - found
-- Looking for gethostbyname
-- Looking for gethostbyname - found
-- Looking for connect
-- Looking for connect - found
-- Looking for remove
-- Looking for remove - found
-- Looking for shmat
-- Looking for shmat - found
-- Found X11: /usr/lib/arm-linux-gnueabihf/libX11.so
-- Checking for module 'libcdio'
--   Found libcdio, version 1.0.0
-- Checking for module 'libchromaprint'
--   Found libchromaprint, version 1.4.3
-- Checking for one of the modules 'cryptopp;libcrypto++'
-- Checking for module 'gio-2.0'
--   Found gio-2.0, version 2.56.4
-- Checking for module 'glib-2.0'
--   Found glib-2.0, version 2.56.4
-- Checking for module 'gobject-2.0'
--   Found gobject-2.0, version 2.56.4
-- Checking for module 'gstreamer-1.0'
--   Found gstreamer-1.0, version 1.14.5
-- Checking for module 'gstreamer-app-1.0'
--   Found gstreamer-app-1.0, version 1.14.5
-- Checking for module 'gstreamer-audio-1.0'
--   Found gstreamer-audio-1.0, version 1.14.5
-- Checking for module 'gstreamer-base-1.0'
--   Found gstreamer-base-1.0, version 1.14.5
-- Checking for module 'gstreamer-tag-1.0'
--   Found gstreamer-tag-1.0, version 1.14.5
-- Checking for module 'gstreamer-pbutils-1.0'
--   Found gstreamer-pbutils-1.0, version 1.14.5
-- Checking for module 'libgpod-1.0>=0.7.92'
--   Found libgpod-1.0, version 0.8.3
-- Checking for module 'libmtp>=1.0'
--   Found libmtp, version 1.1.13
-- Checking for module 'libmygpo-qt5>=1.0.9'
--   No package 'libmygpo-qt5' found
-- Checking for module 'libpulse'
--   Found libpulse, version 11.1
-- Checking for module 'libxml-2.0'
--   Found libxml-2.0, version 2.9.4
-- Checking for module 'libspotify>=12.1.45'
--   No package 'libspotify' found
-- Checking for module 'taglib'
--   Found taglib, version 1.11.1
CMake Error at CMakeLists.txt:93 (find_package):
  By not providing "FindQt5.cmake" in CMAKE_MODULE_PATH this project has
  asked CMake to find a package configuration file provided by "Qt5", but
  CMake did not find one.

  Could not find a package configuration file provided by "Qt5" (requested
  version 5.6.0) with any of the following names:

    Qt5Config.cmake
    qt5-config.cmake

  Add the installation prefix of "Qt5" to CMAKE_PREFIX_PATH or set "Qt5_DIR"
  to a directory containing one of the above files.  If "Qt5" provides a
  separate development package or SDK, be sure it has been installed.


-- Configuring incomplete, errors occurred!
See also "/home/odroid/Clementine/bin/CMakeFiles/CMakeOutput.log".
See also "/home/odroid/Clementine/bin/CMakeFiles/CMakeError.log".

Installed a few more packages,

For the missing ALSA headder files

sudo apt-get install libasound2-dev
sudo apt-get install libasound2
sudo apt-get install libasound2-data
sudo apt-get install libasound2-plugin-smixer

And for QT5

sudo apt-get install qtbase5-dev
sudo apt-get install qt5-default

And then try the configure again:

:~/Clementine/bin$ cmake ..
-- The C compiler identification is GNU 7.5.0
-- The CXX compiler identification is GNU 7.5.0
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
CMake Deprecation Warning at CMakeLists.txt:4 (cmake_policy):
  The OLD behavior for policy CMP0011 will be removed from a future version
  of CMake.

  The cmake-policies(7) manual explains that the OLD behaviors of all
  policies are deprecated and that a policy should be set to OLD only under
  specific short-term circumstances.  Projects should be ported to the NEW
  behavior and not rely on setting a policy to OLD.


-- Found PkgConfig: /usr/bin/pkg-config (found version "0.29.1")
-- Found OpenGL: /usr/lib/arm-linux-gnueabihf/libOpenGL.so
-- Boost version: 1.65.1
-- Found Gettext: /usr/bin/msgmerge (found version "0.19.8.1")
-- Looking for pthread.h
-- Looking for pthread.h - found
-- Looking for pthread_create
-- Looking for pthread_create - not found
-- Looking for pthread_create in pthreads
-- Looking for pthread_create in pthreads - not found
-- Looking for pthread_create in pthread
-- Looking for pthread_create in pthread - found
-- Found Threads: TRUE
-- Found Protobuf: /usr/lib/arm-linux-gnueabihf/libprotobuf.so;-lpthread (found version "3.0.0")
-- Found ALSA: /usr/lib/arm-linux-gnueabihf/libasound.so (found version "1.1.3")
-- Looking for XOpenDisplay in /usr/lib/arm-linux-gnueabihf/libX11.so;/usr/lib/arm-linux-gnueabihf/libXext.so
-- Looking for XOpenDisplay in /usr/lib/arm-linux-gnueabihf/libX11.so;/usr/lib/arm-linux-gnueabihf/libXext.so - found
-- Looking for gethostbyname
-- Looking for gethostbyname - found
-- Looking for connect
-- Looking for connect - found
-- Looking for remove
-- Looking for remove - found
-- Looking for shmat
-- Looking for shmat - found
-- Found X11: /usr/lib/arm-linux-gnueabihf/libX11.so
-- Checking for module 'libcdio'
--   Found libcdio, version 1.0.0
-- Checking for module 'libchromaprint'
--   Found libchromaprint, version 1.4.3
-- Checking for one of the modules 'cryptopp;libcrypto++'
-- Checking for module 'gio-2.0'
--   Found gio-2.0, version 2.56.4
-- Checking for module 'glib-2.0'
--   Found glib-2.0, version 2.56.4
-- Checking for module 'gobject-2.0'
--   Found gobject-2.0, version 2.56.4
-- Checking for module 'gstreamer-1.0'
--   Found gstreamer-1.0, version 1.14.5
-- Checking for module 'gstreamer-app-1.0'
--   Found gstreamer-app-1.0, version 1.14.5
-- Checking for module 'gstreamer-audio-1.0'
--   Found gstreamer-audio-1.0, version 1.14.5
-- Checking for module 'gstreamer-base-1.0'
--   Found gstreamer-base-1.0, version 1.14.5
-- Checking for module 'gstreamer-tag-1.0'
--   Found gstreamer-tag-1.0, version 1.14.5
-- Checking for module 'gstreamer-pbutils-1.0'
--   Found gstreamer-pbutils-1.0, version 1.14.5
-- Checking for module 'libgpod-1.0>=0.7.92'
--   Found libgpod-1.0, version 0.8.3
-- Checking for module 'libmtp>=1.0'
--   Found libmtp, version 1.1.13
-- Checking for module 'libmygpo-qt5>=1.0.9'
--   No package 'libmygpo-qt5' found
-- Checking for module 'libpulse'
--   Found libpulse, version 11.1
-- Checking for module 'libxml-2.0'
--   Found libxml-2.0, version 2.9.4
-- Checking for module 'libspotify>=12.1.45'
--   No package 'libspotify' found
-- Checking for module 'taglib'
--   Found taglib, version 1.11.1
CMake Error at /usr/lib/arm-linux-gnueabihf/cmake/Qt5/Qt5Config.cmake:28 (find_package):
  Could not find a package configuration file provided by "Qt5X11Extras" with
  any of the following names:

    Qt5X11ExtrasConfig.cmake
    qt5x11extras-config.cmake

  Add the installation prefix of "Qt5X11Extras" to CMAKE_PREFIX_PATH or set
  "Qt5X11Extras_DIR" to a directory containing one of the above files.  If
  "Qt5X11Extras" provides a separate development package or SDK, be sure it
  has been installed.
Call Stack (most recent call first):
  CMakeLists.txt:95 (find_package)


-- Configuring incomplete, errors occurred!
See also "/home/odroid/Clementine/bin/CMakeFiles/CMakeOutput.log".
See also "/home/odroid/Clementine/bin/CMakeFiles/CMakeError.log".

Fewer errors, still missing some stuff:

  • No package ‘libmygpo-qt5’ found
  • No package ‘libspotify’ found
  • Qt5X11Extras

Installed the following additional packages:

sudo apt-get install libmygpo-qt-dev
sudo apt-get install libqt5x11extras5-dev
:~/Clementine/bin$ sudo apt-get install libspotify
Reading package lists... Done
Building dependency tree
Reading state information... Done
E: Unable to locate package libspotify

Hopefully we can build without libspotify! (we can, though I do want Spotify…)

Final config trace:

:~/Clementine/bin$ cmake ..
-- The C compiler identification is GNU 7.5.0
-- The CXX compiler identification is GNU 7.5.0
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
CMake Deprecation Warning at CMakeLists.txt:4 (cmake_policy):
  The OLD behavior for policy CMP0011 will be removed from a future version
  of CMake.

  The cmake-policies(7) manual explains that the OLD behaviors of all
  policies are deprecated and that a policy should be set to OLD only under
  specific short-term circumstances.  Projects should be ported to the NEW
  behavior and not rely on setting a policy to OLD.


-- Found PkgConfig: /usr/bin/pkg-config (found version "0.29.1")
-- Found OpenGL: /usr/lib/arm-linux-gnueabihf/libOpenGL.so
-- Boost version: 1.65.1
-- Found Gettext: /usr/bin/msgmerge (found version "0.19.8.1")
-- Looking for pthread.h
-- Looking for pthread.h - found
-- Looking for pthread_create
-- Looking for pthread_create - not found
-- Looking for pthread_create in pthreads
-- Looking for pthread_create in pthreads - not found
-- Looking for pthread_create in pthread
-- Looking for pthread_create in pthread - found
-- Found Threads: TRUE
-- Found Protobuf: /usr/lib/arm-linux-gnueabihf/libprotobuf.so;-lpthread (found version "3.0.0")
-- Found ALSA: /usr/lib/arm-linux-gnueabihf/libasound.so (found version "1.1.3")
-- Looking for XOpenDisplay in /usr/lib/arm-linux-gnueabihf/libX11.so;/usr/lib/arm-linux-gnueabihf/libXext.so
-- Looking for XOpenDisplay in /usr/lib/arm-linux-gnueabihf/libX11.so;/usr/lib/arm-linux-gnueabihf/libXext.so - found
-- Looking for gethostbyname
-- Looking for gethostbyname - found
-- Looking for connect
-- Looking for connect - found
-- Looking for remove
-- Looking for remove - found
-- Looking for shmat
-- Looking for shmat - found
-- Found X11: /usr/lib/arm-linux-gnueabihf/libX11.so
-- Checking for module 'libcdio'
--   Found libcdio, version 1.0.0
-- Checking for module 'libchromaprint'
--   Found libchromaprint, version 1.4.3
-- Checking for one of the modules 'cryptopp;libcrypto++'
-- Checking for module 'gio-2.0'
--   Found gio-2.0, version 2.56.4
-- Checking for module 'glib-2.0'
--   Found glib-2.0, version 2.56.4
-- Checking for module 'gobject-2.0'
--   Found gobject-2.0, version 2.56.4
-- Checking for module 'gstreamer-1.0'
--   Found gstreamer-1.0, version 1.14.5
-- Checking for module 'gstreamer-app-1.0'
--   Found gstreamer-app-1.0, version 1.14.5
-- Checking for module 'gstreamer-audio-1.0'
--   Found gstreamer-audio-1.0, version 1.14.5
-- Checking for module 'gstreamer-base-1.0'
--   Found gstreamer-base-1.0, version 1.14.5
-- Checking for module 'gstreamer-tag-1.0'
--   Found gstreamer-tag-1.0, version 1.14.5
-- Checking for module 'gstreamer-pbutils-1.0'
--   Found gstreamer-pbutils-1.0, version 1.14.5
-- Checking for module 'libgpod-1.0>=0.7.92'
--   Found libgpod-1.0, version 0.8.3
-- Checking for module 'libmtp>=1.0'
--   Found libmtp, version 1.1.13
-- Checking for module 'libmygpo-qt5>=1.0.9'
--   No package 'libmygpo-qt5' found
-- Checking for module 'libpulse'
--   Found libpulse, version 11.1
-- Checking for module 'libxml-2.0'
--   Found libxml-2.0, version 2.9.4
-- Checking for module 'libspotify>=12.1.45'
--   No package 'libspotify' found
-- Checking for module 'taglib'
--   Found taglib, version 1.11.1
-- Could NOT find Qt5LinguistTools (missing: Qt5LinguistTools_DIR)
-- Using builtin taglib library
-- Check if the system is big endian
-- Searching 16 bit integer
-- Looking for sys/types.h
-- Looking for sys/types.h - found
-- Looking for stdint.h
-- Looking for stdint.h - found
-- Looking for stddef.h
-- Looking for stddef.h - found
-- Check size of unsigned short
-- Check size of unsigned short - done
-- Using unsigned short
-- Check if the system is big endian - little endian
-- Check size of short
-- Check size of short - done
-- Check size of int
-- Check size of int - done
-- Check size of long long
-- Check size of long long - done
-- Check size of wchar_t
-- Check size of wchar_t - done
-- Check size of float
-- Check size of float - done
-- Check size of double
-- Check size of double - done
-- Performing Test HAVE_STD_ATOMIC
-- Performing Test HAVE_STD_ATOMIC - Success
-- Performing Test HAVE_GCC_BYTESWAP
-- Performing Test HAVE_GCC_BYTESWAP - Success
-- Performing Test HAVE_VSNPRINTF
-- Performing Test HAVE_VSNPRINTF - Success
-- Performing Test HAVE_ISO_STRDUP
-- Performing Test HAVE_ISO_STRDUP - Failed
-- Found ZLIB: /usr/lib/arm-linux-gnueabihf/libz.so (found version "1.2.11")
CMake Deprecation Warning at 3rdparty/libprojectm/CMakeLists.txt:7 (cmake_policy):
  The OLD behavior for policy CMP0005 will be removed from a future version
  of CMake.

  The cmake-policies(7) manual explains that the OLD behaviors of all
  policies are deprecated and that a policy should be set to OLD only under
  specific short-term circumstances.  Projects should be ported to the NEW
  behavior and not rely on setting a policy to OLD.


CMake Deprecation Warning at 3rdparty/libprojectm/CMakeLists.txt:11 (cmake_policy):
  The OLD behavior for policy CMP0017 will be removed from a future version
  of CMake.

  The cmake-policies(7) manual explains that the OLD behaviors of all
  policies are deprecated and that a policy should be set to OLD only under
  specific short-term circumstances.  Projects should be ported to the NEW
  behavior and not rely on setting a policy to OLD.


-- Checking for module 'glew'
--   Found glew, version 2.0.0
-- Performing Test SUPPORTS_OPENMP
-- Performing Test SUPPORTS_OPENMP - Success
-- Performing Test GNUCXX_HAS_WLOGICAL_OP
-- Performing Test GNUCXX_HAS_WLOGICAL_OP - Success
-- Performing Test SUPPORTS_NOBOOL
-- Performing Test SUPPORTS_NOBOOL - Success

Building Clementine version: 1.4.0rc1-273-g06544054a

The following components will be built:
   ALSA integration
   Box support
   D-Bus support
   Devices: Audio CD support
   Devices: DeviceKit backend
   Devices: GIO device backend
   Devices: MTP support
   Devices: UDisks2 backend
   Devices: iPod classic support
   Dropbox support
   Google Drive support
   Moodbar support
   Pulse audio integration
   Seafile support
   Skydrive support
   Spotify support
   Visualisations
   Wiimote support

The following components WILL NOT be built:
   Crash reporting (disabled in CMake config)
   Last.fm support (missing liblastfm)
   Sparkle integration (missing macOS, Sparkle)
   Spotify support: non-GPL binary helper (missing libspotify)
   Translations (missing Qt5LinguistTools)

-- Configuring done
-- Generating done
-- Build files have been written to: /home/odroid/Clementine/bin

That looks acceptable.

Okay, compile and link success!

But clementine fails to start via X11 forwarding…

https://forum.odroid.com/viewtopic.php?t=23473

:~/Clementine/bin$ ./clementine
06:26:00.036 INFO  {anonymous}:226                  Using default config locations.
06:26:00.038 INFO  main:321                         Clementine-qt5 1.4.0rc1-273-g06544054a
06:26:00.387 WARN  unknown                          The X11 connection broke: Unsupported extension used (code 2)
XIO:  fatal IO error 11 (Resource temporarily unavailable) on X server "localhost:10.0"
      after 6 requests (6 known processed) with 0 events remaining.
^C

May actually be an Odroid specific problem, the post above seems to hit the nail on the head. Starting Clementine with X11 forwarding from my mac was the issue. I switched over to using another Ubuntu linux system to log in with SSH and X11 forwarding and starting clementine succeeded.

Next problem, no audio service started before a graphical login

Okay, so we got Clementine built from source, yay! But now there is no playback because the PulseAudio service is not started before a login…

Helpful links:

A variation on this solution is what got the audio service running:

Put this text in the file /etc/systemd/system/pulseaudio.service:

[Unit]
Description=PulseAudio system server

[Service]
Type=notify
ExecStart=/usr/bin/pulseaudio --daemonize=no --system --realtime --log-target=journal

[Install]
WantedBy=multi-user.target

This unit file starts PulseAudio as a service during system startup.

Now enable and start the unit file by running the following commands:

systemctl --system enable pulseaudio.service
systemctl --system start pulseaudio.service

It should be running now. You can check the status of the service with the command:

systemctl --system status pulseaudio.service

More notes:

Great! It works!

The final problem I had was with my sound card, I was trying to use a “fancy” DAC that was just not being handled over the XU4’s USB. I kept seeing device resets in the kernel log, and so I abandoned it in favor of a USB DAC/ADC that is supported.

DAC-X6 kernel log messages (duplicate messages omitted)

[ 3314.482210] usb 2-1: 3:1: usb_set_interface failed (-62)
[ 3322.123167] usb 2-1: reset full-speed USB device number 45 using exynos-ohci
[ 3322.383234] usb 2-1: can't restore configuration #1 (error=-62)
[ 3322.387793] usb 2-1: USB disconnect, device number 45
[ 3322.651168] usb 2-1: new full-speed USB device number 46 using exynos-ohci
[ 3322.912236] usb 2-1: config 1 has an invalid interface number: 3 but max is 2
[ 3322.912262] usb 2-1: config 1 has no interface number 2
[ 3322.932234] usb 2-1: New USB device found, idVendor=262a, idProduct=9023
[ 3322.932241] usb 2-1: New USB device strings: Mfr=1, Product=2, SerialNumber=0
[ 3322.932247] usb 2-1: Product: DAC-X6
[ 3322.932252] usb 2-1: Manufacturer: DAC-X6
[ 3322.953196] input: DAC-X6 DAC-X6 as /devices/platform/soc/12120000.usb/usb2/2-1/2-1:1.0/0003:262A:9023.002C/input/input44
[ 3323.011527] hid-generic 0003:262A:9023.002C: input,hidraw0: USB HID v1.00 Device [DAC-X6 DAC-X6] on usb-12120000.usb-1/input0
[ 3324.679174] usb 2-1: reset full-speed USB device number 46 using exynos-ohci

The USB audio interface that worked (Behringer U-Control UCA202) enumerates with the following messages:

[29491.553181] usb 2-1: new full-speed USB device number 48 using exynos-ohci
[29491.783239] usb 2-1: New USB device found, idVendor=08bb, idProduct=2902
[29491.783247] usb 2-1: New USB device strings: Mfr=1, Product=2, SerialNumber=0
[29491.783252] usb 2-1: Product: USB Audio CODEC
[29491.783258] usb 2-1: Manufacturer: Burr-Brown from TI
[29491.882446] input: Burr-Brown from TI               USB Audio CODEC  as /devices/platform/soc/12120000.usb/usb2/2-1/2-1:1.3/0003:08BB:2902.002D/input/input45
[29491.941518] hid-generic 0003:08BB:2902.002D: input,hidraw0: USB HID v1.00 Device [Burr-Brown from TI               USB Audio CODEC ] on usb-12120000.usb-1/input3

Disable the mood bar and visualization bar ASAP, they slow the system way down.

Also disable cross-fade on manual track change and on stopping playback (under Tools -> Preferences -> Playback).

TODO: it would be a cool contribution to the project to implement some kind of hardware acceleration for these features so they did not use the CPU on ARM systems, could be DSP or GPU or aux processor of some kind.

Things to follow up on

sudo apt-get install gstreamer1.0-plugins-bad

This did the trick, there is an additional instruction in the link above to install the package: ubuntu-restricted-extras, but that seems unnecessary or maybe it does partly the same thing as installing the gstreamer plugins.

It may be handy to add a touchscreen to the kiosk to allow for local control of the player, but for now starting the player remotely from another machine and using either that machine to control the player or the android remote app works well enough.

Summary

I now have a working music kiosk that replaces my CD player and CD collection (much more compact!) With my entire music library at my fingertips. I’ll go back and rebuild Clementine with Spotify support and then my music universe will be complete.

So far Clementine has been stable (no crashes) and music playback has been solid with no anomalous audio or stream gaps. I’m streaming audio files from a home-built NAS over a WiFi network, so the audio source hooked to the stereo receiver is simply the XU4 and an audio interface (USB DAC to RCA).

Follow up with libspotify

Installing libspotify. Spotify is no longer hosting libspotify. But there is an archive site, hopefully trustworthy…

wget https://github.com/mopidy/libspotify-archive/raw/master/libspotify-12.1.51-Linux-armv7-release.tar.gz
echo 'ad27b6c5aee5382b66b39bfea3b1752076b7abcc445979ce25c1ec9d7ff3aeda libspotify-12.1.51-Linux-armv7-release.tar.gz' | sha256sum --check
libspotify-12.1.51-Linux-armv7-release.tar.gz: OK

:~$ tar -xf libspotify-12.1.51-Linux-armv7-release.tar.gz
:~$ cd libspotify-12.1.51-Linux-armv7-release/
:~/libspotify-12.1.51-Linux-armv7-release$ sudo make install
[sudo] password for odroid:
mkdir -p /usr/local/include/libspotify
install include/libspotify/api.h /usr/local/include/libspotify
mkdir -p /usr/local/lib
install -T lib/libspotify.so.12 /usr/local/lib/libspotify.so.12.1.51
cd /usr/local/lib && ln -sf libspotify.so.12.1.51 libspotify.so.12 && ln -sf libspotify.so.12.1.51 libspotify.so
mkdir -p /usr/local/lib/pkgconfig
sed -e s:PKG_PREFIX:/usr/local:g <lib/pkgconfig/libspotify.pc >/usr/local/lib/pkgconfig/libspotify.pc
ldconfig

Now clean and remove files from Clementine/bin

:~$ cd Clementine/bin/
:~/Clementine/bin$ make clean
:~/Clementine/bin$ ls
3rdparty  CMakeCache.txt  CMakeFiles  Makefile  cmake_install.cmake  cmake_uninstall.cmake  dist  ext  gst  src  tests
:~/Clementine/bin$ rm -rf *

I also installed lastfm support with:

sudo apt-get install liblastfm5-dev

Now configure again, and rebuild.

cmake ..
...
make -j4
...
[100%] Building CXX object src/CMakeFiles/clementine_lib.dir/core/moc_ubuntuunityhack.cpp.o
[100%] Building CXX object src/CMakeFiles/clementine_lib.dir/qrc_data.cpp.o
[100%] Linking CXX static library libclementine_lib.a
[100%] Built target clementine_lib
Scanning dependencies of target clementine
[100%] Building CXX object src/CMakeFiles/clementine.dir/main.cpp.o
[100%] Linking CXX executable ../clementine
[100%] Built target clementine

It still does not work! :( I need to investigate the difference in FPU support between the spotify plugin and libspotify.

:~/Clementine/bin$ readelf -A /usr/local/lib/libspotify.so.12.1.51

Attribute Section: aeabi
File Attributes
  Tag_CPU_name: "CORTEX-A8"
  Tag_CPU_arch: v7
  Tag_CPU_arch_profile: Application
  Tag_ARM_ISA_use: Yes
  Tag_THUMB_ISA_use: Thumb-2
  Tag_FP_arch: VFPv3
  Tag_Advanced_SIMD_arch: NEONv1
  Tag_ABI_PCS_wchar_t: 4
  Tag_ABI_FP_denormal: Needed
  Tag_ABI_FP_exceptions: Needed
  Tag_ABI_FP_number_model: IEEE 754
  Tag_ABI_align_needed: 8-byte
  Tag_ABI_enum_size: int
  Tag_ABI_optimization_goals: Aggressive Speed
  Tag_DIV_use: Not allowed

Versus

:~/Clementine/bin$ readelf -A clementine-spotifyblob

Attribute Section: aeabi
File Attributes
  Tag_CPU_name: "7-A"
  Tag_CPU_arch: v7
  Tag_CPU_arch_profile: Application
  Tag_ARM_ISA_use: Yes
  Tag_THUMB_ISA_use: Thumb-2
  Tag_FP_arch: VFPv3-D16
  Tag_ABI_PCS_wchar_t: 4
  Tag_ABI_FP_rounding: Needed
  Tag_ABI_FP_denormal: Needed
  Tag_ABI_FP_exceptions: Needed
  Tag_ABI_FP_number_model: IEEE 754
  Tag_ABI_align_needed: 8-byte
  Tag_ABI_align_preserved: 8-byte, except leaf SP
  Tag_ABI_enum_size: int
  Tag_ABI_VFP_args: VFP registers
  Tag_CPU_unaligned_access: v6

Notice that libspotify has Tag_FP_arch: VFPv3 and Tag_Advanced_SIMD_arch: NEONv1 and clementine-spotifyblob does not, it is using Tag_FP_arch: VFPv3-D16, which I guess is the standard for Ubuntu ARM targeted packages. I can’t simply recompile/link because all of this stuff is apparently closed source from spotify… If it is not target arch incompatibility, then I thought it might be ABI incompatibility, so here is the diff of that:

XRDP Server

To run clementine from a Mac use remote desktop as a work around:

https://medium.com/@vivekteega/how-to-setup-an-xrdp-server-on-ubuntu-18-04-89f7e205bd4e

Adding a display to the kiosk

If we add a (touchscreen) display to the XU4, then we can control music playback directly on the kiosk.

Also having a display allows us to use VNC for remote control as well, and the screen on the kiosk will show a users remote actions, and indicate the current song/album, etc..