Add MPD with its corresponding services.
This commit is contained in:
parent
92373e8d27
commit
06ce146fd8
1
.gitattributes
vendored
Normal file
1
.gitattributes
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
README.md merge=ours
|
3
.gitmodules
vendored
3
.gitmodules
vendored
|
@ -1,3 +0,0 @@
|
||||||
[submodule "stage2/04-pirate-radio/files/pivumeter"]
|
|
||||||
path = stage2/04-pirate-radio/files/pivumeter
|
|
||||||
url = https://github.com//pivumeter
|
|
66
README.md
66
README.md
|
@ -1,41 +1,41 @@
|
||||||
# Piradio
|
# 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
|
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.
|
||||||
Piradio specifically implements the internet radio project described here: https://github.com/pimoroni/phat-beat/tree/master/projects/vlc-radio
|
- 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
|
||||||
## motivation
|
- LEDs are used as a vumeter
|
||||||
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.
|
|
||||||
|
|
||||||
## how to create the image
|
## how to create the image
|
||||||
- First clone this repository with `git clone --recursive git@github.com:pirateradiohack/PiRadio.git`.
|
- First clone this repository with `git clone 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: If you create a file called `my-playlist.m3u` with your own list of internet radio streams, it will be installed.
|
||||||
- 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.
|
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.
|
- 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 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/`
|
- 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.
|
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
|
## 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`
|
`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`)
|
(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.
|
Those settings are recommended by the RaspberryPi instructions.
|
||||||
|
|
||||||
## controlling your radio via web interface
|
## 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
|
## 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.
|
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.
|
and configure your wifi. You can also optionally configure your own radio streams playlist.
|
||||||
|
|
||||||
The files to edit are:
|
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 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.
|
You are safe to flash the image.
|
||||||
- after flashing your operating system probably automounts the partitions.
|
- 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.
|
||||||
|
|
|
@ -10,3 +10,11 @@ automake
|
||||||
libtool
|
libtool
|
||||||
libasound2-dev
|
libasound2-dev
|
||||||
libfftw3-dev
|
libfftw3-dev
|
||||||
|
mpd
|
||||||
|
mpc
|
||||||
|
ncmpcpp
|
||||||
|
python3-setuptools
|
||||||
|
python3-systemd
|
||||||
|
cmake
|
||||||
|
libmpdclient-dev
|
||||||
|
libssl-dev
|
||||||
|
|
|
@ -1,10 +1,30 @@
|
||||||
#!/bin/bash -e
|
#!/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
|
# pulseaudio
|
||||||
install -v -m 644 files/etc/systemd/system/pulseaudio.service "${ROOTFS_DIR}/etc/systemd/system/"
|
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/client.conf "${ROOTFS_DIR}/etc/pulse/"
|
||||||
install -v -m 644 files/etc/pulse/default.pa "${ROOTFS_DIR}/etc/pulse/"
|
install -v -m 644 files/etc/pulse/default.pa "${ROOTFS_DIR}/etc/pulse/"
|
||||||
|
|
||||||
# pivumeter
|
# pivumeter
|
||||||
cp -rf files/pivumeter "${ROOTFS_DIR}/root/"
|
git clone https://github.com/pimoroni/pivumeter.git "${ROOTFS_DIR}/root/pivumeter"
|
||||||
install -v -m 644 files/pivumeter/dependencies/etc/asound.conf "${ROOTFS_DIR}/etc/"
|
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"
|
||||||
|
|
|
@ -1,9 +1,31 @@
|
||||||
#!/bin/bash -e
|
#!/bin/bash -e
|
||||||
|
|
||||||
|
# pulseaudio
|
||||||
systemctl enable pulseaudio
|
systemctl enable pulseaudio
|
||||||
|
|
||||||
|
#pivumeter
|
||||||
cd /root/pivumeter
|
cd /root/pivumeter
|
||||||
aclocal && libtoolize
|
aclocal && libtoolize
|
||||||
autoconf && automake --add-missing
|
autoconf && automake --add-missing
|
||||||
./configure && make
|
./configure && make
|
||||||
make install
|
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
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
#!/bin/bash -e
|
#!/bin/bash -e
|
||||||
|
|
||||||
|
# cleanup
|
||||||
rm -rf "${ROOTFS_DIR}/root/pivumeter"
|
rm -rf "${ROOTFS_DIR}/root/pivumeter"
|
||||||
|
rm -rf "${ROOTFS_DIR}/root/python-mpd2"
|
||||||
|
rm -rf "${ROOTFS_DIR}/root/ympd"
|
||||||
|
|
1
stage2/04-pirate-radio/files/etc/hostname
Normal file
1
stage2/04-pirate-radio/files/etc/hostname
Normal file
|
@ -0,0 +1 @@
|
||||||
|
radio
|
6
stage2/04-pirate-radio/files/etc/hosts
Normal file
6
stage2/04-pirate-radio/files/etc/hosts
Normal file
|
@ -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
|
425
stage2/04-pirate-radio/files/etc/mpd.conf
Normal file
425
stage2/04-pirate-radio/files/etc/mpd.conf
Normal file
|
@ -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 <http://www.replaygain.org> 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"
|
||||||
|
#}
|
||||||
|
#
|
||||||
|
###############################################################################
|
||||||
|
|
|
@ -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
|
||||||
|
|
14
stage2/04-pirate-radio/files/etc/systemd/system/ympd.service
Normal file
14
stage2/04-pirate-radio/files/etc/systemd/system/ympd.service
Normal file
|
@ -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
|
102
stage2/04-pirate-radio/files/interface.py
Normal file
102
stage2/04-pirate-radio/files/interface.py
Normal file
|
@ -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)
|
|
@ -1 +0,0 @@
|
||||||
Subproject commit 5e4afea8813beeec2f81d877f3ddc9a84eaa177e
|
|
Loading…
Reference in New Issue
Block a user