From 06ce146fd836541307a75f1b1e556b84e7f64a85 Mon Sep 17 00:00:00 2001 From: piradio Date: Sat, 15 Jun 2019 15:52:52 +0200 Subject: [PATCH] Add MPD with its corresponding services. --- .gitattributes | 1 + .gitmodules | 3 - README.md | 66 ++- stage2/04-pirate-radio/00-packages | 8 + stage2/04-pirate-radio/01-run.sh | 24 +- stage2/04-pirate-radio/02-run-chroot.sh | 22 + stage2/04-pirate-radio/03-run.sh | 3 + stage2/04-pirate-radio/files/etc/hostname | 1 + stage2/04-pirate-radio/files/etc/hosts | 6 + stage2/04-pirate-radio/files/etc/mpd.conf | 425 ++++++++++++++++++ .../systemd/system/radio-interface.service | 31 ++ .../files/etc/systemd/system/ympd.service | 14 + stage2/04-pirate-radio/files/interface.py | 102 +++++ stage2/04-pirate-radio/files/pivumeter | 1 - 14 files changed, 677 insertions(+), 30 deletions(-) create mode 100644 .gitattributes create mode 100644 stage2/04-pirate-radio/files/etc/hostname create mode 100644 stage2/04-pirate-radio/files/etc/hosts create mode 100644 stage2/04-pirate-radio/files/etc/mpd.conf create mode 100644 stage2/04-pirate-radio/files/etc/systemd/system/radio-interface.service create mode 100644 stage2/04-pirate-radio/files/etc/systemd/system/ympd.service create mode 100644 stage2/04-pirate-radio/files/interface.py delete mode 160000 stage2/04-pirate-radio/files/pivumeter diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..b0ff811 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +README.md merge=ours diff --git a/.gitmodules b/.gitmodules index 7c26bef..e69de29 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +0,0 @@ -[submodule "stage2/04-pirate-radio/files/pivumeter"] - path = stage2/04-pirate-radio/files/pivumeter - url = https://github.com//pivumeter diff --git a/README.md b/README.md index eadec17..25ab09e 100755 --- a/README.md +++ b/README.md @@ -1,41 +1,41 @@ # Piradio -Piradio is the image that you need to burn on your SD card in order for your Pirate Radio to work. +Piradio powers a streaming internet radio client for the "Pirate Radio" hardware sold by Pimoroni: https://shop.pimoroni.com/products/pirate-radio-pi-zero-w-project-kit +or any kit based on their Phat Beat DAC / Audio Amplifier and a Raspberry Pi. -Pirate Radio here refers to the product sold by Pimoroni here: https://shop.pimoroni.com/products/pirate-radio-pi-zero-w-project-kit - -Piradio specifically implements the internet radio project described here: https://github.com/pimoroni/phat-beat/tree/master/projects/vlc-radio - - -## motivation -The official documentation from Pimoroni suggest that you install the operating system and then execute some scripts on there to install the project. - -I personally find it more convenient when it comes to embedded devices to just burn an image to an SD card. - -## how it is built -The image is built with the official RaspberryPi.org tool (https://github.com/RPi-Distro/pi-gen) and the official scripts from Pimoroni (https://github.com/pimoroni/phat-beat/tree/master/projects/vlc-radio) adapted to work together. - -Nothing has been changed or otherwise improved from the original scripts, so the image you get here is the same as if you would install it the official way. +Features are the ones provided by [mpd](https://github.com/MusicPlayerDaemon/MPD): +- it retains the radio station that was playing after turning off / on the device and also the volume. +- it has a number of interfaces, currently on this image there is a web interface and a console one. +- managing your radio stations can be done from the interface (`add stream` and delete buttons). +- physical buttons do what is expected of them +- LEDs are used as a vumeter ## how to create the image -- First clone this repository with `git clone --recursive git@github.com:pirateradiohack/PiRadio.git`. -(Please note the `--recursive` here is important to get all the code, there is a submodule present.) -- Configure your radio stations: Pimoroni maintains a set of default internet radio streams. You can see them in the file `example.m3u`. This file will be installed if nothing else is supplied. If you create a file called `my-playlist.m3u` with your own list of internet radio streams, this file will be used instead. -- Configure your wifi settings: copy the file called `config.example` to `config` and edit this last one. You will see where to enter your wifi name, password and country. All 3 settings are necessary. -- Then build the image. (You can see the whole guide on the official RaspberryPi repo: https://github.com/RPi-Distro/pi-gen). I find it easier to use docker as there is nothing else to install, just run one command from this directory: `./build-docker.sh`. That's it. On my computer it takes between 15 and 30 minutes. And at the end you should see something like: `Done! Your image(s) should be in deploy/` +- First clone this repository with `git clone git@github.com:pirateradiohack/PiRadio.git`. +- Configure your radio stations: If you create a file called `my-playlist.m3u` with your own list of internet radio streams, it will be installed. +If not, then you can always add stations in the web interface. +- Configure your wifi settings: copy the file called `config.example` to `config` and edit this last one. You will see where to enter your wifi name, password and country. All 3 settings are necessary. Your changes to this file will be kept in future updates. +- Then build the image. (You can see the whole guide on the official RaspberryPi repo: https://github.com/RPi-Distro/pi-gen). I find it easier to use docker (obviously you need to have docker installed on your system) as there is nothing else to install, just run one command from this directory: `./build-docker.sh`. That's it. On my computer it takes between 15 and 30 minutes. And at the end you should see something like: `Done! Your image(s) should be in deploy/` If you don't see that, it's probably that the build failed. It happens to me sometimes for no reason and I find that just re-launching the build with `CONTINUE=1 ./build-docker.sh` finishes the build correctly. ## burn the image to a SD card -You should find the newly created image in the `deploy` directory. On linux an example to get it on the SD card would be: +You should find the newly created image in the `deploy` directory. + +### graphically +For a user friendly experience you can try [etcher](https://www.balena.io/etcher/) to flash the image to the SD card. + +### manually +On linux (and it probably works on Mac too) an example to get it on the SD card would be: `sudo dd bs=4M if=deploy/2019-05-23-Piradio-lite.img of=/dev/mmcblk0 conv=fsync` (of course you need to replace `/dev/mmcblk0` with the path to your own SD card. You can find it with the command `lsblk -f`) Those settings are recommended by the RaspberryPi instructions. - + ## controlling your radio via web interface -You can control your radio via web interface: find its IP and in your browser enter `http://[IP of your radio]:8080` with no username and password `raspberry`. +You can control your radio via web interface: try to open `http://radio.local` in a web browser. If that does not work then find its IP and in your browser enter `http://[IP of your radio]`. +If you prefer the command line, you can ssh into your radio (you need to set that up in the `config` file before building the image) and then use `ncmpcpp` to get a nice terminal interface (see some screenshots here: https://rybczak.net/ncmpcpp/screenshots/). ## ready-to-flash image Out of security concerns I recommend you read the [code](https://github.com/RPi-Distro/pi-gen/compare/master...pirateradiohack:master) and build the image yourself. -But, if you prefer to trust a stranger on the Internet with your Pirate Radio, for your convenience you will find the latest image pre-compiled here: [2019-05-23-Piradio-lite.img](https://github.com/pirateradiohack/PiRadio/releases/download/2019-05-23-PiRadio/2019-05-23-Piradio-lite.img) . Just flash it +But, if you prefer to trust a stranger on the Internet with your Pirate Radio, for your convenience you will find the latest image pre-compiled here: [2019-05-23-Piradio-lite.img](https://github.com/pirateradiohack/PiRadio/releases/download/2019-06-15-PiRadio/2019-06-14-Piradio-lite.img) . Just flash it and configure your wifi. You can also optionally configure your own radio streams playlist. The files to edit are: @@ -49,3 +49,21 @@ With Linux you can use `kpartx` (from the `multipath-tools` package) to be able (you will need to create the mount directory first and check what loop device you are using with `sudo kpartx -l path/to/2019-05-23-Piradio-lite.img`). Then you can edit the files mentionned above. And `sudo umount tmp`. You are safe to flash the image. - after flashing your operating system probably automounts the partitions. + +## how it is built +The image is built with the official RaspberryPi.org tool (https://github.com/RPi-Distro/pi-gen) to build a Raspbian lite system with all the software needed +to have a working internet radio stream client. It uses `mpd`. + +## motivation +The official documentation from Pimoroni has some instructions and examples to make an internet streaming client for the hardware: https://github.com/pimoroni/phat-beat/tree/master/projects/vlc-radio. It works fine and is a good source of inspiration. + + +But those examples assume an already installed OS and run some scripts on top of it. +I personally find it more convenient when it comes to embedded devices to just burn an image to an SD card. +Also, the provided software in the examples works fine, but comes in a format that I find hard to tinker with. +I tried to use an approach based on provisionning an image instead in order to make it a good ground for hacking. + +The first version of this project used the official scripts from Pimoroni. If you want that, you can find it here: https://github.com/pirateradiohack/PiRadio/tree/2019-05-25-PiRadio + + +Issues and pull requests are welcome. diff --git a/stage2/04-pirate-radio/00-packages b/stage2/04-pirate-radio/00-packages index 6c343f7..0758006 100644 --- a/stage2/04-pirate-radio/00-packages +++ b/stage2/04-pirate-radio/00-packages @@ -10,3 +10,11 @@ automake libtool libasound2-dev libfftw3-dev +mpd +mpc +ncmpcpp +python3-setuptools +python3-systemd +cmake +libmpdclient-dev +libssl-dev diff --git a/stage2/04-pirate-radio/01-run.sh b/stage2/04-pirate-radio/01-run.sh index d76a18f..9428294 100755 --- a/stage2/04-pirate-radio/01-run.sh +++ b/stage2/04-pirate-radio/01-run.sh @@ -1,10 +1,30 @@ #!/bin/bash -e +# set hostname +install -v -m 644 files/etc/hostname "${ROOTFS_DIR}/etc/" +install -v -m 644 files/etc/hosts "${ROOTFS_DIR}/etc/" + # pulseaudio install -v -m 644 files/etc/systemd/system/pulseaudio.service "${ROOTFS_DIR}/etc/systemd/system/" install -v -m 644 files/etc/pulse/client.conf "${ROOTFS_DIR}/etc/pulse/" install -v -m 644 files/etc/pulse/default.pa "${ROOTFS_DIR}/etc/pulse/" # pivumeter -cp -rf files/pivumeter "${ROOTFS_DIR}/root/" -install -v -m 644 files/pivumeter/dependencies/etc/asound.conf "${ROOTFS_DIR}/etc/" +git clone https://github.com/pimoroni/pivumeter.git "${ROOTFS_DIR}/root/pivumeter" +install -v -m 644 "${ROOTFS_DIR}/root/pivumeter/dependencies/etc/asound.conf" "${ROOTFS_DIR}/etc/" + +# mpd +git clone https://github.com/Mic92/python-mpd2.git "${ROOTFS_DIR}/root/python-mpd2" +install -v -m 644 files/etc/mpd.conf "${ROOTFS_DIR}/etc/" +if [ -f ../../my-playlist.m3u ]; then + install -v -m 644 ../../my-playlist.m3u "${ROOTFS_DIR}/var/lib/mpd/playlists/my-playlist.m3u" +fi + +# physical interface +install -v -m 644 files/etc/systemd/system/radio-interface.service "${ROOTFS_DIR}/etc/systemd/system/" +mkdir "${ROOTFS_DIR}/usr/local/lib/radio-interface/" +install -v -m 644 files/interface.py "${ROOTFS_DIR}/usr/local/lib/radio-interface/" + +# web interface +install -v -m 644 files/etc/systemd/system/ympd.service "${ROOTFS_DIR}/etc/systemd/system/" +git clone https://github.com/notandy/ympd.git "${ROOTFS_DIR}/root/ympd" diff --git a/stage2/04-pirate-radio/02-run-chroot.sh b/stage2/04-pirate-radio/02-run-chroot.sh index 51b98ef..aa684d4 100755 --- a/stage2/04-pirate-radio/02-run-chroot.sh +++ b/stage2/04-pirate-radio/02-run-chroot.sh @@ -1,9 +1,31 @@ #!/bin/bash -e +# pulseaudio systemctl enable pulseaudio +#pivumeter cd /root/pivumeter aclocal && libtoolize autoconf && automake --add-missing ./configure && make make install + +# mpd +cd /root/python-mpd2 +python3 setup.py install + +# physical interface +useradd -r -s /bin/false radio-interface +adduser radio-interface gpio +echo 'radio-interface ALL=(ALL) NOPASSWD: /sbin/shutdown' > /etc/sudoers.d/010_radio-interface-shutdown +chmod 0440 /etc/sudoers.d/010_radio-interface-shutdown +systemctl enable radio-interface + +# web interface +cd /root/ympd +mkdir build +cd build +cmake .. -DCMAKE_INSTALL_PREFIX:PATH=/usr +make +make install +systemctl enable ympd diff --git a/stage2/04-pirate-radio/03-run.sh b/stage2/04-pirate-radio/03-run.sh index e3360fb..28c156a 100755 --- a/stage2/04-pirate-radio/03-run.sh +++ b/stage2/04-pirate-radio/03-run.sh @@ -1,3 +1,6 @@ #!/bin/bash -e +# cleanup rm -rf "${ROOTFS_DIR}/root/pivumeter" +rm -rf "${ROOTFS_DIR}/root/python-mpd2" +rm -rf "${ROOTFS_DIR}/root/ympd" diff --git a/stage2/04-pirate-radio/files/etc/hostname b/stage2/04-pirate-radio/files/etc/hostname new file mode 100644 index 0000000..41edf49 --- /dev/null +++ b/stage2/04-pirate-radio/files/etc/hostname @@ -0,0 +1 @@ +radio diff --git a/stage2/04-pirate-radio/files/etc/hosts b/stage2/04-pirate-radio/files/etc/hosts new file mode 100644 index 0000000..0c09161 --- /dev/null +++ b/stage2/04-pirate-radio/files/etc/hosts @@ -0,0 +1,6 @@ +127.0.0.1 localhost +::1 localhost ip6-localhost ip6-loopback +ff02::1 ip6-allnodes +ff02::2 ip6-allrouters + +127.0.1.1 radio diff --git a/stage2/04-pirate-radio/files/etc/mpd.conf b/stage2/04-pirate-radio/files/etc/mpd.conf new file mode 100644 index 0000000..2296dc4 --- /dev/null +++ b/stage2/04-pirate-radio/files/etc/mpd.conf @@ -0,0 +1,425 @@ +# An example configuration file for MPD. +# Read the user manual for documentation: http://www.musicpd.org/doc/user/ +# or /usr/share/doc/mpd/user-manual.html + + +# Files and directories ####################################################### +# +# This setting controls the top directory which MPD will search to discover the +# available audio files and add them to the daemon's online database. This +# setting defaults to the XDG directory, otherwise the music directory will be +# be disabled and audio files will only be accepted over ipc socket (using +# file:// protocol) or streaming files over an accepted protocol. +# +music_directory "/var/lib/mpd/music" +# +# This setting sets the MPD internal playlist directory. The purpose of this +# directory is storage for playlists created by MPD. The server will use +# playlist files not created by the server but only if they are in the MPD +# format. This setting defaults to playlist saving being disabled. +# +playlist_directory "/var/lib/mpd/playlists" +# +# This setting sets the location of the MPD database. This file is used to +# load the database at server start up and store the database while the +# server is not up. This setting defaults to disabled which will allow +# MPD to accept files over ipc socket (using file:// protocol) or streaming +# files over an accepted protocol. +# +db_file "/var/lib/mpd/tag_cache" +# +# These settings are the locations for the daemon log files for the daemon. +# These logs are great for troubleshooting, depending on your log_level +# settings. +# +# The special value "syslog" makes MPD use the local syslog daemon. This +# setting defaults to logging to syslog, otherwise logging is disabled. +# +log_file "/var/log/mpd/mpd.log" +# +# This setting sets the location of the file which stores the process ID +# for use of mpd --kill and some init scripts. This setting is disabled by +# default and the pid file will not be stored. +# +pid_file "/run/mpd/pid" +# +# This setting sets the location of the file which contains information about +# most variables to get MPD back into the same general shape it was in before +# it was brought down. This setting is disabled by default and the server +# state will be reset on server start up. +# +state_file "/var/lib/mpd/state" +# +# The location of the sticker database. This is a database which +# manages dynamic information attached to songs. +# +sticker_file "/var/lib/mpd/sticker.sql" +# +############################################################################### + + +# General music daemon options ################################################ +# +# This setting specifies the user that MPD will run as. MPD should never run as +# root and you may use this setting to make MPD change its user ID after +# initialization. This setting is disabled by default and MPD is run as the +# current user. +# +user "mpd" +# +# This setting specifies the group that MPD will run as. If not specified +# primary group of user specified with "user" setting will be used (if set). +# This is useful if MPD needs to be a member of group such as "audio" to +# have permission to use sound card. +# +#group "nogroup" +# +# This setting sets the address for the daemon to listen on. Careful attention +# should be paid if this is assigned to anything other then the default, any. +# This setting can deny access to control of the daemon. Choose any if you want +# to have mpd listen on every address. Not effective if systemd socket +# activation is in use. +# +# For network +bind_to_address "localhost" +# +# And for Unix Socket +#bind_to_address "/run/mpd/socket" +# +# This setting is the TCP port that is desired for the daemon to get assigned +# to. +# +#port "6600" +# +# This setting controls the type of information which is logged. Available +# setting arguments are "default", "secure" or "verbose". The "verbose" setting +# argument is recommended for troubleshooting, though can quickly stretch +# available resources on limited hardware storage. +# +#log_level "default" +# +# If you have a problem with your MP3s ending abruptly it is recommended that +# you set this argument to "no" to attempt to fix the problem. If this solves +# the problem, it is highly recommended to fix the MP3 files with vbrfix +# (available as vbrfix in the debian archive), at which +# point gapless MP3 playback can be enabled. +# +#gapless_mp3_playback "yes" +# +# Setting "restore_paused" to "yes" puts MPD into pause mode instead +# of starting playback after startup. +# +#restore_paused "no" +# +# This setting enables MPD to create playlists in a format usable by other +# music players. +# +#save_absolute_paths_in_playlists "no" +# +# This setting defines a list of tag types that will be extracted during the +# audio file discovery process. The complete list of possible values can be +# found in the mpd.conf man page. +#metadata_to_use "artist,album,title,track,name,genre,date,composer,performer,disc" +# +# This setting enables automatic update of MPD's database when files in +# music_directory are changed. +# +#auto_update "yes" +# +# Limit the depth of the directories being watched, 0 means only watch +# the music directory itself. There is no limit by default. +# +#auto_update_depth "3" +# +############################################################################### + + +# Symbolic link behavior ###################################################### +# +# If this setting is set to "yes", MPD will discover audio files by following +# symbolic links outside of the configured music_directory. +# +#follow_outside_symlinks "yes" +# +# If this setting is set to "yes", MPD will discover audio files by following +# symbolic links inside of the configured music_directory. +# +#follow_inside_symlinks "yes" +# +############################################################################### + + +# Zeroconf / Avahi Service Discovery ########################################## +# +# If this setting is set to "yes", service information will be published with +# Zeroconf / Avahi. +# +#zeroconf_enabled "yes" +# +# The argument to this setting will be the Zeroconf / Avahi unique name for +# this MPD server on the network. +# +#zeroconf_name "Music Player" +# +############################################################################### + + +# Permissions ################################################################# +# +# If this setting is set, MPD will require password authorization. The password +# can setting can be specified multiple times for different password profiles. +# +#password "password@read,add,control,admin" +# +# This setting specifies the permissions a user has who has not yet logged in. +# +#default_permissions "read,add,control,admin" +# +############################################################################### + + +# Database ####################################################################### +# + +#database { +# plugin "proxy" +# host "other.mpd.host" +# port "6600" +#} + +# Input ####################################################################### +# + +input { + plugin "curl" +# proxy "proxy.isp.com:8080" +# proxy_user "user" +# proxy_password "password" +} + +# +############################################################################### + +# Audio Output ################################################################ +# +# MPD supports various audio output types, as well as playing through multiple +# audio outputs at the same time, through multiple audio_output settings +# blocks. Setting this block is optional, though the server will only attempt +# autodetection for one sound card. +# +audio_output { + type "pulse" + name "MPD" + server "127.0.0.1" +} +# +# An example of an ALSA output: +# +#audio_output { +# type "alsa" +# name "My ALSA Device" +# device "hw:0,0" # optional +# mixer_type "hardware" # optional +# mixer_device "default" # optional +# mixer_control "PCM" # optional +# mixer_index "0" # optional +#} +# +# An example of an OSS output: +# +#audio_output { +# type "oss" +# name "My OSS Device" +# device "/dev/dsp" # optional +# mixer_type "hardware" # optional +# mixer_device "/dev/mixer" # optional +# mixer_control "PCM" # optional +#} +# +# An example of a shout output (for streaming to Icecast): +# +#audio_output { +# type "shout" +# encoder "vorbis" # optional +# name "My Shout Stream" +# host "localhost" +# port "8000" +# mount "/mpd.ogg" +# password "hackme" +# quality "5.0" +# bitrate "128" +# format "44100:16:1" +# protocol "icecast2" # optional +# user "source" # optional +# description "My Stream Description" # optional +# url "http://example.com" # optional +# genre "jazz" # optional +# public "no" # optional +# timeout "2" # optional +# mixer_type "software" # optional +#} +# +# An example of a recorder output: +# +#audio_output { +# type "recorder" +# name "My recorder" +# encoder "vorbis" # optional, vorbis or lame +# path "/var/lib/mpd/recorder/mpd.ogg" +## quality "5.0" # do not define if bitrate is defined +# bitrate "128" # do not define if quality is defined +# format "44100:16:1" +#} +# +# An example of a httpd output (built-in HTTP streaming server): +# +#audio_output { +# type "httpd" +# name "My HTTP Stream" +# encoder "vorbis" # optional, vorbis or lame +# port "8000" +# bind_to_address "0.0.0.0" # optional, IPv4 or IPv6 +# quality "5.0" # do not define if bitrate is defined +# bitrate "128" # do not define if quality is defined +# format "44100:16:1" +# max_clients "0" # optional 0=no limit +#} +# +# An example of a pulseaudio output (streaming to a remote pulseaudio server) +# Please see README.Debian if you want mpd to play through the pulseaudio +# daemon started as part of your graphical desktop session! +# +#audio_output { +# type "pulse" +# name "My Pulse Output" +# server "remote_server" # optional +# sink "remote_server_sink" # optional +#} +# +# An example of a winmm output (Windows multimedia API). +# +#audio_output { +# type "winmm" +# name "My WinMM output" +# device "Digital Audio (S/PDIF) (High Definition Audio Device)" # optional +# or +# device "0" # optional +# mixer_type "hardware" # optional +#} +# +# An example of an openal output. +# +#audio_output { +# type "openal" +# name "My OpenAL output" +# device "Digital Audio (S/PDIF) (High Definition Audio Device)" # optional +#} +# +## Example "pipe" output: +# +#audio_output { +# type "pipe" +# name "my pipe" +# command "aplay -f cd 2>/dev/null" +## Or if you're want to use AudioCompress +# command "AudioCompress -m | aplay -f cd 2>/dev/null" +## Or to send raw PCM stream through PCM: +# command "nc example.org 8765" +# format "44100:16:2" +#} +# +## An example of a null output (for no audio output): +# +#audio_output { +# type "null" +# name "My Null Output" +# mixer_type "none" # optional +#} +# +# If MPD has been compiled with libsamplerate support, this setting specifies +# the sample rate converter to use. Possible values can be found in the +# mpd.conf man page or the libsamplerate documentation. By default, this is +# setting is disabled. +# +#samplerate_converter "Fastest Sinc Interpolator" +# +############################################################################### + + +# Normalization automatic volume adjustments ################################## +# +# This setting specifies the type of ReplayGain to use. This setting can have +# the argument "off", "album", "track" or "auto". "auto" is a special mode that +# chooses between "track" and "album" depending on the current state of +# random playback. If random playback is enabled then "track" mode is used. +# See for more details about ReplayGain. +# This setting is off by default. +# +#replaygain "album" +# +# This setting sets the pre-amp used for files that have ReplayGain tags. By +# default this setting is disabled. +# +#replaygain_preamp "0" +# +# This setting sets the pre-amp used for files that do NOT have ReplayGain tags. +# By default this setting is disabled. +# +#replaygain_missing_preamp "0" +# +# This setting enables or disables ReplayGain limiting. +# MPD calculates actual amplification based on the ReplayGain tags +# and replaygain_preamp / replaygain_missing_preamp setting. +# If replaygain_limit is enabled MPD will never amplify audio signal +# above its original level. If replaygain_limit is disabled such amplification +# might occur. By default this setting is enabled. +# +#replaygain_limit "yes" +# +# This setting enables on-the-fly normalization volume adjustment. This will +# result in the volume of all playing audio to be adjusted so the output has +# equal "loudness". This setting is disabled by default. +# +#volume_normalization "no" +# +############################################################################### + + +# Character Encoding ########################################################## +# +# If file or directory names do not display correctly for your locale then you +# may need to modify this setting. +# +filesystem_charset "UTF-8" +# +# This setting controls the encoding that ID3v1 tags should be converted from. +# +id3v1_encoding "UTF-8" +# +############################################################################### + + +# SIDPlay decoder ############################################################# +# +# songlength_database: +# Location of your songlengths file, as distributed with the HVSC. +# The sidplay plugin checks this for matching MD5 fingerprints. +# See http://www.c64.org/HVSC/DOCUMENTS/Songlengths.faq +# +# default_songlength: +# This is the default playing time in seconds for songs not in the +# songlength database, or in case you're not using a database. +# A value of 0 means play indefinitely. +# +# filter: +# Turns the SID filter emulation on or off. +# +#decoder { +# plugin "sidplay" +# songlength_database "/media/C64Music/DOCUMENTS/Songlengths.txt" +# default_songlength "120" +# filter "true" +#} +# +############################################################################### + diff --git a/stage2/04-pirate-radio/files/etc/systemd/system/radio-interface.service b/stage2/04-pirate-radio/files/etc/systemd/system/radio-interface.service new file mode 100644 index 0000000..2abe88f --- /dev/null +++ b/stage2/04-pirate-radio/files/etc/systemd/system/radio-interface.service @@ -0,0 +1,31 @@ +[Unit] + +# Human readable name of the unit +Description=controller for the radio buttons and LEDs + + +[Service] + +# Command to execute when the service is started +ExecStart=/usr/bin/python3 /usr/local/lib/radio-interface/interface.py + +# Disable Python's buffering of STDOUT and STDERR, so that output from the +# service shows up immediately in systemd's logs +Environment=PYTHONUNBUFFERED=1 + +# Automatically restart the service if it crashes +Restart=on-failure + +# Our service will notify systemd once it is up and running +Type=notify + +# Use a dedicated user to run our service +# User=radio-interface + + +[Install] + +# Tell systemd to automatically start this service when the system boots +# (assuming the service is enabled) +WantedBy=default.target + diff --git a/stage2/04-pirate-radio/files/etc/systemd/system/ympd.service b/stage2/04-pirate-radio/files/etc/systemd/system/ympd.service new file mode 100644 index 0000000..d01707c --- /dev/null +++ b/stage2/04-pirate-radio/files/etc/systemd/system/ympd.service @@ -0,0 +1,14 @@ +[Unit] +Description=ympd server daemon +Requires=network.target local-fs.target + +[Service] +Environment=MPD_HOST=localhost +Environment=MPD_PORT=6600 +Environment=WEB_PORT=80 +Environment=YMPD_USER=nobody +ExecStart=/usr/bin/ympd --user $YMPD_USER --webport $WEB_PORT --host $MPD_HOST --port $MPD_PORT +Type=simple + +[Install] +WantedBy=multi-user.target diff --git a/stage2/04-pirate-radio/files/interface.py b/stage2/04-pirate-radio/files/interface.py new file mode 100644 index 0000000..fc17bb9 --- /dev/null +++ b/stage2/04-pirate-radio/files/interface.py @@ -0,0 +1,102 @@ +"""This module is a systemd service that takes care of interfacing the +physical interaction devices (buttons, LEDs...) and the software of the +radio. +""" +import subprocess +import time +from contextlib import contextmanager + +import phatbeat +import systemd.daemon +from mpd import MPDClient +from mpd.base import CommandError + +HOST, PORT = 'localhost', 6600 +VOLUME_STEP = 10 + +client = MPDClient() + +@contextmanager +def connection_to_mpd(): + """Context manager to establish the connection with MPD. + + Should be used for every use of the client since the connection is + sketchy. + """ + try: + client.connect(HOST, PORT) + yield + finally: + client.close() + client.disconnect() + +# if the playlist is empty and an .m3u file has been provided then initialize +with connection_to_mpd(): + if not client.playlist(): + try: + client.load("my-playlist") + except(CommandError): + pass + +# Make sure we are not in the stop position (does not affect pause) +# and make sure we are in repeat mode to avoid falling in the stopped +# position when we hit the end of the playlist by pushing next on the +# last radio station of the playlist. +with connection_to_mpd(): + client.play() + client.repeat(1) + +# all initialization is considered done after this point and we tell +# systemd that we are ready to serve +systemd.daemon.notify('READY=1') + +@phatbeat.on(phatbeat.BTN_VOLDN) +def volume_down(pin): + """Volume down button tells pulseaudio to step down the volume.""" + command = """pactl + set-sink-volume + 0 + -{}% + """.format(VOLUME_STEP) + subprocess.run(command.split()) + +@phatbeat.on(phatbeat.BTN_VOLUP) +def volume_up(pin): + """Volume up button tells pulseaudio to step up the volume.""" + command = """pactl + set-sink-volume + 0 + +{}% + """.format(VOLUME_STEP) + subprocess.run(command.split()) + +@phatbeat.on(phatbeat.BTN_PLAYPAUSE) +def play_pause(pin): + """Play/pause button tells MPD to toggle play/plause.""" + with connection_to_mpd(): + client.pause() + +@phatbeat.on(phatbeat.BTN_FASTFWD) +def next(pin): + """Next button tells MPD to play next track.""" + with connection_to_mpd(): + client.next() + +@phatbeat.on(phatbeat.BTN_REWIND) +def previous(pin): + """Previous button tells MPD to play previous track.""" + with connection_to_mpd(): + client.previous() + +@phatbeat.on(phatbeat.BTN_ONOFF) +def shutdown(pin): + """Shutdown button tells the system to shutdown now.""" + command = """shutdown + -h now + """ + subprocess.run(command.split()) + +# maintain the module loaded for as long the the interface is needed +# without conuming resources +while True: + time.sleep(5) diff --git a/stage2/04-pirate-radio/files/pivumeter b/stage2/04-pirate-radio/files/pivumeter deleted file mode 160000 index 5e4afea..0000000 --- a/stage2/04-pirate-radio/files/pivumeter +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 5e4afea8813beeec2f81d877f3ddc9a84eaa177e