Literature clock
My literature clock project running on the Raspberry Pi and modelled by Leo.
See here for its Github page.
Automatically ripping CDs on linux
Part 2 of building a music server from scratch. See here for part 1.
-
This is a work in progress. Use at your own peril.
-
To auto-rip the cds inserted into my headless music server I’m going to use abcde and cdparanoia. Install them with
sudo apt-get install abcde lame eyed3 glyrc imagemagick cdparanoia
1 -
MusicBrainz is missing some dependencies so run
sudo apt-get install libmusicbrainz-discid-perl libwebservice-musicbrainz-perl
-
After running
abcde-musicbrainz-tool
from the command line I got an error about missing Mojo::DOM. Fix this withsudo cpan install Mojo::DOM
-
We need to a config file for abcde. This is abcde.conf. There are multiple places that this could go (see the man page), but since I have a single user setup for now I am placing this in my users home directory
/home/phil/.abcde.conf
, but I could place it anywhere else and get the program to read it with the-c [filename]
option. Placing it here means if I run abcde from the command line, this will be the default configuration. -
Edit the your .abcde.conf file to use the correct ripper and write to files to the correct place.
CDROMREADERSYNTAX=cdparanoia CDPARANOIAOPTS="--never-skip=40" OUTPUTTYPE=flac #edit OUTPUTDIR. Its the location of the output flacs to write OUTPUTDIR=/home/phil/storage/music/flac/abcde #you might need to change CDROM CDROM=/dev/sr0 EJECTCD=y CDDBMETHOD=musicbrainz GLYRC=glyrc CONVERT=convert ALBUMRARTFILE="cover.jpg" ALBUMARTTYPE="JPEG" # Make a local cache of cddb entries and then volunteer to use # these entries when and if they match the cd: CDDBCOPYLOCAL="y" CDDBLOCALDIR="$HOME/.cddb" CDDBLOCALRECURSIVE="y" CDDBUSELOCAL="y" FLAC=flac # Path to FLAC encoder # Specify the encoder to use for FLAC. In this case # flac is the only choice. FLACENCODERSYNTAX=flac # Specify the path to the selected encoder. In most cases the encoder # should be in your $PATH as I illustrate below, otherwise you will # need to specify the full path. For example: /usr/bin/flac FLAC=flac # Specify your required encoding options here. Multiple options can # be selected as '--best --another-option' etc. # Overall bitrate is about 880 kbs/s with level 8. FLACOPTS='-s -e -V -8' # Give the location of the CD identification program: CDDISCID=cd-discid # The default actions that abcde will take. ACTIONS=cddb,playlist,read,getalbumart,encode,tag,move,clean # If NOSUBMIT is set to y, then abcde will never prompt asking if you # wish to submit your edited cddb file. NOSUBMIT=n # Decide here how you want the tracks labelled for a standard 'single-artist', # multi-track encode and also for a multi-track, 'various-artist' encode: OUTPUTFORMAT='${OUTPUT}/${ARTISTFILE}-${ALBUMFILE}/${TRACKNUM}.${TRACKFILE}' VAOUTPUTFORMAT='${OUTPUT}/Various-${ALBUMFILE}/${TRACKNUM}.${ARTISTFILE}-${TRACKFILE}' # This function takes out dots preceding the album name, and removes a grab # bag of illegal characters. It allows spaces, if you do not wish spaces add # in -e 's/ /_/g' after the first sed command. mungefilename () { CDDISKID=$(cd-discid "$CDROM") FIRSTPART=$(echo $CDDISKID | cut -d' ' -f1) echo $FIRSTPART "$@" | /home/phil/dev/munger.py } MAXPROCS=2 # Run a few encoders simultaneously PADTRACKS=y # Makes tracks 01 02 not 1 2 EXTRAVERBOSE=2 # Useful for debugging INTERACTIVE=n post_read() { } #ok, now we need to set the correct ownership for the flac files. post_encode () { ARTISTFILE="$(mungefilename "$TRACKARTIST")" ALBUMFILE="$(mungefilename "$DALBUM")" if [ "$VARIOUSARTISTS" = "y" ] ; then FINDPATH="$(eval echo "$VAOUTPUTFORMAT")" else FINDPATH="$(eval echo "$OUTPUTFORMAT")" fi FINALDIR="$(dirname "$OUTPUTDIR/$FINDPATH")" C_CMD=(chown -R phil:lms "$FINALDIR") #echo "${C_CMD[@]}" >>tmp2.log "${C_CMD[@]}" }
munger.py
strips any odd unicode out of the string to make the filename safe. It can be donwnloaded from here
Most of the above is straight forwards abcde configuration. It uses cdparanoia to rip the cd, musicbrainz to find the track information and then it uses flac encoding. Themungefilename()
function removes any unwanted characters from the file name and also appends the discID number onto the directory name for any unknown album – otherwise abcde will overwrite it. Thepost_encode()
function changes the ownership of the files tophil:lms
. You will need to edit this. TODO: Currently this is placing all the temp files in/
which might be a problem. -
The ownship of the directory
/home/phil/storage/music/flac/abcde
and/home/phil/storage/music/flac/abcde/flac
will need correcting withsudo chmod -R /home/phil/storage/music/flac/abcde
-
Test the configuration by inserting a CD and ripping it from the command line.
abcde -c /home/phil/.abcde.conf
-
Ok, so how to get it to autorip when a CD is inserted. For this the udev is needed which is the Linux device manager. We need to get to trigger a command when it detects a CD is inserted. However, udev does not allow long running programmes to be run. If you try to call abcde directly you will find udev kills the process before its finished ripping. To get around this we create a new service and get udev to start the service.
-
Create a new file
/etc/systemd/system/ripper.service
with the following[Unit] Description=Auto CD ripper [Service] Type=oneshot ExecStart=/home/phil/dev/rip.sh [Install] WantedBy=multi-user.target
-
And create the
/home/phil/dev/rip.sh
file which gets run#!/bin/bash LOCKDIR=rip.lock LOGFILE=/home/phil/dev/log.txt function cleanup { if rmdir $LOCKDIR; then echo "Finished $(date)" >> $LOGFILE else echo "Failed to remove lock dir '$LOCKDIR'" >> $LOGFILE exit 1 fi } if mkdir $LOCKDIR; then trap "cleanup" EXIT echo "Acquired Lock, running" >> $LOGFILE echo "Started $(date) $$" >> $LOGFILE abcde -c /home/phil/.abcde.conf #trigger LMS rescan wget -q --spider http://localhost:9000/settings/index.html?p0=rescan echo "Stopped $(date) $$" >> $LOGFILE # optional notifications, uncomment if needed # echo "Sending IFFT webhook:">>$LOGFILE # /home/phil/dev/ifttt_send.sh "Ripper done. Please eject CD" >> $LOGFILE # send the logfile by email, you need to configure mail first for this to work # cat $LOGFILE | mail -s "Ripper log" your_email@example.com else echo "Could not create lock, already running? '$LOCKDIR'" exit 1 fi
This file basically only allows abcde to run as a single instance. It needs to be made executable with
chmod u+x /home/phil/dev/rip.sh
Thewget
command triggers the LMS rescan which looks for new media. TheLOGFILE
is really only useful to see if the script is working, you might want to set it to/dev/null
eventually.
The ifttt_send.sh used IFTT to send a notification that the process has finished to my phone. You need an IFTT account. I created a Maker Event calledripper_done
that connect to a rich text notification. The ifttt_send.sh contains:#!/bin/bash source /home/phil/dev/ifttt_key.sh CMDSTRING=("curl -H \"Content-Type: application/json\" -X POST -d '{\"value1\":\" $1\"}' https://maker.ifttt.com/trigger/ripper_done/with/key/$IFTTT_KEY") eval $CMDSTRING
ifttt_key.sh defines IFTTT_KEY which you need. It a single line
export IFTTT_KEY="YOUR KEY VALUE"
-
Start the service
sudo systemctl daemon-reload sudo systemctl enable ripper.service
Now if you place a CD in the drive you should be able to rip it by running
sudo systemctl start ripper
. The status of the ripping can be obtained withsystemctl status ripper
-
We now make a udev rule to trigger the service start when a cd is inserted. Create a file
/etc/udev/rules.d/99-cd-audio-rip.rules
with the followingSUBSYSTEM=="block",KERNEL=="sr0",ACTION=="change",RUN+="/bin/systemctl start ripper"
sr0
is the name of my CD-ROM drive.
Now add the rule withsudo udevadm control --reload
-
Now when you insert a CD it should autorip. You can always test the progress of the ripping with
systemctl status ripper
1: My apt-get version of abcde was 2.9 which has a bug and crashes if Musicbrainz returns an unknown disc. To fix it we need to update it. Remove abcde with sudo apt-get remove abcde
, download the latest version from here 2.9.2 at the time of writing. Untar it, enter the directory and run sudo make install
. Since we removed the managed version of abcde the dependencies will be marked for removal. To stop this install them sudo apt-get install vorbis-tools cd-discid fdkaac
. You might want to check for other dependencies if you have a problems with apt-cache depends abcde
.
Setting up a home music server/player on linux
For years I’ve been using Vortexbox as my music server at home. It’s basically a headless linux server configured with Logitech Music Server, an automatic CD ripper, a software player (for local sound playback) and a reasonable web interface. Vortexbox however hasn’t been updated for years. The maintainer is promising an update but I didn’t want to wait and instead set out to build my own. This is running on a HP micro-server (1.2GHz Atom) and I have Naim DAC plugged into it via USB for music.
It should be possible for anyone to install this but it is complicated and I’m not sure I’d recomend this to anyone with either no Linux experience or no desire to learn Linux.
-
Install Lubunutu – This version comes with a GUI. I could have used one of the server versions, but the GUI is handy for the intial setup. My thought process on the distro didn’t going beyond this! I’m not going to go into detail here on the install becuase there plenty of tutorials online.
-
Setup a user, my is
phil
-
We will also need ssh to remote login
sudo apt-get install openssh-server
. The rest of the set up can be done locally or now remotely via SSH. -
My server has 3 hard drives. One contains the OS, one is the music, one is for backup. The music files are going to be stored in the user home space rather than the root. So I edited fstab to mount my music drive in
/home/phil/storage/
. Your setup may well be different. My music is held in/home/phil/storage/music/flac
-
Install LMS (Logitech Media Server). It has a dependancy so run
sudo apt-get install libio-socket-ssl-perl
to install it. Download the latest version of LMS from http://www.mysqueezebox.com/. Once downloadedsudo dpkg -i logitechmediaserver_7.9.2~1530185314_amd64.deb
. You will need to change the name of the .deb file for the version you downloaded. Then runsudo apt-get -f install
and start the servicesudo service logitechmediaserver start
. You should then configure the users and group settings.sudo usermod -aG audio squeezeboxserver sudo usermod -aG lms squeezeboxserver sudo usermod -aG audio phil
-
Create a
Playlist
folder somewhere and set the file group ownership tolms
withsudo chown phil:lms -R Playlist
and maybesudo chmod -R 744 Playlist
. The music files also need to belong to thelms
group sosudo chown -R phil:lms /home/phil/storage/music/flac
-
Open a web browser and the address will be http://[ip address of your machine]:9000. Configure LMS so that it knows the location of the music and playlist folders. Rescan the LMS music library. LMS should now be running. It’s probably not a bad idea to fix the IP address of your machine. You can normally do this with your routers web interface, or by setting the network configuration of your server (the router method is normally the easiest.)
-
To add music to our folder over the home network we need samba to share a folder.
sudo apt-get install samba
, and create a samba usersudo smbpasswd -a phil
. Edit the samba configsudo vi /etc/samba/smb.conf
and add to the end[music] path = /home/phil/storage/music valid users = phil read only = no
Restart the service with
sudo service smbd restart
and test the smb.conf config is valid by runningtestparm
-
Install squeezelite player via the systems package manager(
sudo apt-get intsall squeezelite
). [Update: the repo version is rather old and seems unstable on my system. I recommend instead building from the source code. see here ].Now runsqueezelite -l
which should list the available audio devices. Runningsqueezelite
from the console will start the program. If you are like me running squeezelite from the console works – it should appear as a player under the LMS webpage. ^C kills the player.The problem here is I would need to log in and run the command every time. It’s far better to run this as a service that starts automatically on boot. The service should be installed via the package mangager but the default configuration probably does not work. I think this is becuase the default sound card option is via pulse audio and this cannot be run as root. In the output of
squeezelite -l
there is (hopefully) one option starting withhw:
, in my case it ishw:CARD=Audiophilleocom,DEV=0
. This is the direct hardware option and it is the one we want. In/etc/default/squeezelite
add the lineSL_SOUNDCARD="hw:CARD=Audiophilleocom,DEV=0"
or whatever your equivalent is. Restart the service withsudo service squeezelite restart
and hopefully it is all working. 1 -
Since the server is headless we don’t need to waste resources running the GUI. Switch to console login via
sudo systemctl set-default multi-user.target
-
Vortexbox automatically ripped CDs when inserted. See here for my version that uses abcde.
-
Since I don’t log in to the machine very often via SSH, the updates can get very far behind. I’ve therefore enabled auto-update. Install with
sudo apt-get install unattended-upgrades -y
andsudo apt-get install update-notifier-common -y
. You can then edit/etc/apt/apt.conf.d/50unattended-upgrades
as you see fit. I’d recommend enabling the email notifications. -
On site and off site backups
1: I have had a few problems with Squeezelite crashing and I am currenlty looking into this. I suspect the pulseaudio might be the problem and it might need to be disabled. Since we aren’t using the desktop, this should be ok. Do not uninstall pulseaudio as some forums suggest. It can be disabled gobally by editting /etc/pulse/client.conf
and changing the line ; autospawn = on
to autospawn = off
. Note the removal of the ;
. My system now seems stable, however, its hard to say if it was pulseaudio or rebuilding the squeezelite from source that solved the problem. If you still have problems, it might be an idea to increase the ASLA buffersize
Reskinning Max2play
Reskinning Max2play
Max2play is a great way to have an out of the box music server running on a Raspberry Pi with a touch screen. I’ve installed Max2play on a Raspberry Pi 3 and 7 inch touch screen. The only problem with it is that I would like to run other software on the Pi as well (such as control my Phillips Hue lighting). Out the box, the Pi now boots up and runs the full screen Jivelite app which controls the music. There are two options I could think of: 1. Write a plugin for Jivelite to control the Hue lights, or 2, control the lighting with a separate app and have the ability to launch jivelite manually. I went for 2 since Jivelite is written in Lua which I don’t know.
The first problem is how to launch Jivelite manually. For this I added a Jivelite icon to the desktop. I’m assuming Max2play is installed with Jivelite options and everything is working.
In the Jivelite plugin settings, disable autostart. In the Settings/Reboot tab, enable Autostart desktop (the desktop is normally started with the jivelite plugin so we need to enable it here).
In the Pi’s file manager go to Edit/Preferences – enable ‘Open files with Single click’ – it’s not easy double clicking with the touch screen. You might also want to increase the icon sizes whilst your there. These setting affect the desktop as well.
SSH into the Raspberry pi – either from the terminal or via the web plugin you can install. Go to the desktop folder and create a desktop launch shortcut. We will start by making one to launch jivelite. So create a text file with nano jivelite.desktop
and add
[Desktop Entry] Type=Application Icon=/home/pi/music.png <edit this to point to your own icon> Name=Jivelite Comment=Start the Jivelite music player Exec=/opt/jivelite/jivelite/bin/jivelite
Save the file and that’s it. You should be now be able to launch jivelite from the desktop icon. The quit button does not quit the application (it seems to stop the music), so you have to quit from the menu options on Jivelite. (There appears to be a patch file that creates this behavior but I’ll investigate that at a latter date.)
To autostart at login, make a symbolic link to the .desktop file and place it in ~/.config/autostart
You may want to disable the screensaver which blanks the screen after 10 minutes as is. Remove the @xscreensaver -no-splash line from /etc/xdg/lxsession/LXDE/autostart and from ~/.config/lxsession/LXDE/autostart Stopping the screensaver server has no effect. I’m not sure what causes the screen to blank when running the GUI. It might be power saving in X. To disable the screensaver, the easiest method is to install a screensaver client and configure that not to run.
sudo apt-get install xscreensaver
After that’s completed there will be a screensaver option in the LXDE GUI menu. Run that and disable the screensaver from there.