# PyRadio Headless Operation

## Table of Contents Top

- Goal
  - Usage
  - How it works
- Installation
  - Notice
  - Using tmux
    - systemd
  - Using screen
    - systemd
  - systemd service file
  - Notice for systemd installation

[ Return to main doc ]

## Goal Top

This is a document that provides info on running PyRadio in “headless” mode (well, kind of), on a Linux, BSD, or Pi system.

Now, PyRadio is a terminal application; it actually needs a terminal to run. But there is a way to make it run on a “terminal” and at the same time run in the background, being “invisible” so to speak, or run as a weird kind of a daemon; the way to do that is run it in a tmux detached session or a screen detached session.

tmux man page reads:

“tmux is a terminal multiplexer: it enables a number of terminals to be created, accessed, and controlled from a single screen. tmux may be detached from a screen and continue running in the background, then later reattached.”

screen man page reads:

“Screen is a full-screen window manager that multiplexes a physical terminal between several processes (typically interactive shells)… Programs continue to run when their window is currently not visible and even when the whole screen session is detached from the user’s terminal.”

PyRadio users Wikinaut and aleksandr-sabitov on github have come up with the idea to use this approach to run the application on their headless Raspberry Pi, so kudos to them!

### Usage

After the program is started, the only way to interact with it is through its integrated web server. Please refer to the relevant document for more info on the remote control server.

The web server can be accessed either through a terminal (address http://ip:port) using wget or curl, or through a web browser (address http://ip:port/html).

The ip and port will be set using the –headless command line option.

The ip can either be:

1. localhost
   The server will be accessible only by programs running in the system. The ip is 127.0.0.1.
2. lan
   The server will be accessible by any system on the LAN. The ip is the one assigned to the network interface of the system.
3. An actual IP
   This is in case when a machine has more than one network interfaces and the lan setting is ambiguous.

For example:

- using –headless lan:12345
  will make the web server listen to the network interface IP address, port 12345.

- using –headless 192.168.122.101:4567
  will make the web server listen to the IP 192.168.122.101, port 4567.
  If the IP is not assigned to any network interfaces, the default (localhost:1111) will be silently used; please always check the server’s address with the command: pyradio –addr.

- using –headless localhost:23456
  will make the web server listen to 127.0.0.1, port 23456

- using –headless auto
  will make the web server listen to 127.0.0.1, port 11111; this is the default and fallback configuration.

To get the server ip and port, execute on a terminal

    pyradio --addr

Which will return something like:

    PyRadio Remote Control Server
      Headless server
        Text address: http://127.0.0.1:11111
        HTML address: http://127.0.0.1:11111/html

If both a “headless” and a normal instance of PyRadio is running, you will get something like this:

    PyRadio Remote Control Server
      Headless server
        Text address: http://127.0.0.1:11111
        HTML address: http://127.0.0.1:11111/html
      Server
        Text address: http://127.0.0.1:9998
        HTML address: http://127.0.0.1:9998/html

### How it works

When PyRadio is executed with the –headles command line option, it will basically start the web server and wait for connections.

To make it less memory hungry, the default (aka “dark” theme) will be loaded, and access to themes and the configuration window will be restricted.

Additionally, it will not create a “session lock file”, so that other instances of the program can be executed normally (in a terminal), and be able to function properly.

It will create a “headless server lock file”, though, so that

- we cannot start a second headless server, and

- we can get info about the server running.

The “headless server lock file” is saved as ~/.config/pyradio/data/server-headles.txt (or ~/.local/share/pyradio/server-headles.txt if xdg_compliant is set to True), and will contain the IP address and port the servers is listening to. This is especially useful in case a user script needs to get this info (instead of parsing the output of the command pyradio –addr).

## Installation Top

By the term “installation”, we mean that we set up things in such a way, that after we log into the system, we find PyRadio ready to accept connections.

So, the installation can be as easy as adding a line in a configuration file (or the startup section of the desktop environment) or as hard as adding a system service.

### Notice

The commands that follow use the following conventions:

1. The username is spiros.
   Please replace it with your username.

2. PyRadio is installed from source; this means that its executable is ~/.local/bin/pyradio. If this is not the case (using a distribution package, for example), please replace it with the correct one.

3. Both tmux and screen are executed using their absolute path (/usr/bin/tmux and /usr/bin/screen respectively). If they are installed at a different location, please use the correct one instead.

### Using tmux

If bash is the default shell, this would do the trick:

    echo "/usr/bin/tmux new-session \
            -dA -s pyradio-session /home/spiros/.local/bin/pyradio \
            --headless auto" >> ~/.profile

In case a Window manager is used, adding a line in its autostart file would be enough. For example, this would work for openbox:

    echo "(sleep 10; /usr/bin/tmux new-session -dA -s pyradio-session /home/spiros/.local/bin/pyradio --headless auto)" >> ~/.config/openbox/autostart

And so on, and so forth…

#### systemd

The first thing you do is to create the start file. Write this to ~/.local/bin/start-headless-pyradio.sh

    #!/bin/bash
    touch ~/pyradio.log
    /usr/bin/tmux new-session -dA -s pyradio-session /home/spiros/.local/bin/pyradio --headless auto

Then create the stop file. Writhe this to ~/.local/bin/stop-headless-pyradio.sh

    #!/bin/bash
    [ -z "$(/usr/bin/tmux ls | grep pyradio-session)" ] || /usr/bin/tmux send-keys -t pyradio-session q
    sleep 2
    [ -z "$(/usr/bin/tmux ls | grep pyradio-session)" ] || /usr/bin/tmux send-keys -t pyradio-session q
    [ -e /home/spiros/.config/pyradio/data/server-headless.txt ] && rm /home/spiros/.config/pyradio/data/server-headless.txt
    [ -e /home/spiros/.local/state/pyradio/server-headless.txt ] && rm /home/spiros/.local/state/pyradio/server-headless.txt

Make both files executable:

    chmod +x ~/.local/bin/start-headless-pyradio.sh
    chmod +x ~/.local/bin/stop-headless-pyradio.sh

Now you are ready to create the service file.

### Using screen

If bash is the default shell, this would do the trick:

    echo "/usr/bin/screen -U -S pyradio-session -d -m \
            /home/spiros/.local/bin/pyradio \
            --headless auto" >> ~/.profile

In case a Window manager is used, adding a line in its autostart file would be enough. For example, this would work for openbox:

    echo "(sleep 10; /usr/bin/screen -U -S pyradio-session -d -m /home/spiros/.local/bin/pyradio --headless auto)" >> ~/.config/openbox/autostart

And so on, and so forth…

#### systemd

The first thing you do is create the log file:

    touch ~/pyradio.log

Then create the start file. Write this to ~/.local/bin/start-headless-pyradio.sh

    #!/bin/bash
    /usr/bin/screen -U -S pyradio-session -d -m /home/spiros/.local/bin/pyradio --headless auto

Then create the stop file. Writhe this to ~/.local/bin/stop-headless-pyradio.sh

    #!/bin/bash
    [ -z "$(/usr/bin/screen -ls | grep pyradio-session)" ] || /usr/bin/screen -S pyradio-session -p 0 -X stuff q
    sleep 2
    [ -z "$(/usr/bin/screen -ls | grep pyradio-session)" ] || /usr/bin/screen -S pyradio-session -p 0 -X stuff q
    [ -e /home/spiros/.config/pyradio/data/server-headless.txt ] && rm /home/spiros/.config/pyradio/data/server-headless.txt
    [ -e /home/spiros/.local/state/pyradio/server-headless.txt ] && rm /home/spiros/.local/state/pyradio/server-headless.txt

Make both files executable:

    chmod +x ~/.local/bin/start-headless-pyradio.sh
    chmod +x ~/.local/bin/stop-headless-pyradio.sh

Now you are ready to create the service file

### systemd service file

Create the file /lib/systemd/system/pyradio.service

    [Unit]
    Description=PyRadio Service
    After=multi-user.target

    [Service]
    Type=forking
    User=spiros
    Environment="XDG_RUNTIME_DIR=/run/user/1000"
    Environment="PULSE_RUNTIME_PATH=/run/user/1000/pulse/"
    StandardOutput=append:/home/spiros/pyradio.log
    StandardError=append:/home/spiros/pyradio.log
    ExecStart=/home/spiros/.local/bin/start-headless-pyradio.sh
    ExecStop=/home/spiros/.local/bin/stop-headless-pyradio.sh

    [Install]
    WantedBy=multi-user.target

Then execute:

    sudo chmod 644 /lib/systemd/system/pyradio.service
    sudo systemctl daemon-reload
    sudo systemctl enable pyradio # enabling the autostart on every boot

### Notice for systemd installation

The service file has two lines starting with “Environment=”

These two lines provide an environment for systemd; I’ve found out that on Arch Linux, for example, PyRadio would produce no sound at all without them (it would not be able to connect to the sound server).

Note that you may have to change the value 1000 to the one given by the id command; this is actually your uid (user id), which is set to 1000 by default on many distros.

On other systems, on Raspberry Pi for example, they can be omitted altogether.