How to build a tiny Linux MP3 Player System using Buildroot
Do you have an old spare computer that is rotting somewhere in your attic/cellar? Why not recycle it into a MP3 jukebox! 🙂
An old rig (Pentium 1/2/3-class) with 64Megs of RAM and USB connector will do!
No Harddisk required, a CDROM drive is optional in case that booting from USB doesn’t work.
We will design our (minimalistic but fully automated) Linux system so that a screen and a network interface aren’t even required.
Our very simple MP3 player system will be designed according to the following lines :
USB flash drive, with 2 partitions :
- One SYSTEM partition, EXT2 formatted.
- One data partition, labelled MYMUSIC, FAT or EXT2 formatted (preferably FAT if you want to copy files from window$ computers). The mp3 files will be stored in this partition.
We want to be able to boot directly from the USB flash drive (or with a CD if the computer can’t)
Ou Linux system will automatically mount the MYMUSIC partition (in READ ONLY mode for safety!)
The Playlist will be generated by searching mp3 files on the whole partition.
The soundcard is initialized
Basically, just turn on the computer with the USB flash drive plugged in/Boot CD inserted, wait a few seconds, and enjoy your music!
Requirement for the buildroot host system
You may want to have a look at my other how to in order to get started.
You’ll also need :
– a full development system. On Ubuntu/Debian this means the following packages : build-essential, ncurses-dev, bison, flex
– qemu (optional)
If you already have Buildroot installed on your host system, it is strongly advised to delete your old output directory.
PART I – Creating our tiny Linux kernel
Configuration of Buildroot before compilation/system generation :
# cd <your buildroot home> && make menuconfig
[X] Enable large file (files > 2 GB) support
[X] Enable WCHAR support
Package Selection for the target —>
Audio and video libraries and applications —>
ALSA utils selection —>
Hardware handling —>
(Without udev, soundcard support didn’t work for me)
[X] Linux Kernel
Defconfig name : i386
Target filesystem options —>
[X] iso image (optional, only if you want to burn on a CD)
[X] initramfs for initial ramdisk of linux kernel
Linux Kernel configuration
# make linux-menuconfig
Include all the sound drivers for maximum compatibility (kernel size won’t suffer much!)
Device drivers —>
Sound card support —>
Advanced Linux Sound Architecture —>
PCI sound devices —>
<*> Intel/SiS/nVidia/AMD/ALi AC97 Controller
Next, we need to configure BusyBox for our embedded system, but Buildroot currently has a limitation : you must first compile the whole thing, so :
then configure BusyBox
# make busybox-menuconfig
Linux System Utilities —>
[X] Support specifying devices by label or UUID
Miscellaneous Utilities —>
We also need to adapt our root filesystem (the rootfs that will be included in our kernel, via initramfs) :
# cd <your buildroot home>/output/target
Create mnt/music (the mount point we will use to mount our MYMUSIC partition to)
# mkdir mnt/music
Accordingly, modify the etc/fstab file by issuing the command :
# echo "LABEL=MYMUSIC /mnt/music auto ro,noauto 0 0" >>etc/fstab
“auto” tells that the filesystem will be automatically recognized.
the “noauto” value, tells that the entry is not mounted by the mount -a command
(optional) Generate a keymap for our system (ex. for our French readers 🙂
# sudo busybox dumpkmap >etc/fr.kmap
And add the following lines to the etc/init.d/rcS (our own startup code) :
# MYMUSIC volume label MYMUSIC="MYMUSIC" # Mount point MYMUSIC_MNT="/mnt/music"
# load your keymap (optional) loadkmap </etc/fr.kmap clear
echo -e -n "\nInitializing soundcard : " # a beep will be played if alsactl init fails # TODO : add better error handling alsactl init || beep
echo -e "\nMounting Music folder... " # dirty trick here : # trying to mount the MYMUSIC partition # we have to add a delay (10 secs max should be enough) for the usb device to be available! i=1 while [ $i -le 10 ] do # if mount failed, wait 1 sec, else get out of loop (break) mount LABEL=$MYMUSIC && break echo "Waiting..." sleep 1; i=$(( $i + 1 )) done
# check if partition successfully mounted if grep -qs $MYMUSIC_MNT /proc/mounts then echo -e -n "\nMusic folder mounted (Read-only)!\nGenerating playlist : " # scan all folders for *.mp3 files on the volume and sort them alphabetically find $MYMUSIC_MNT -iname "*.mp3" | sort >/tmp/playlist.txt echo -e "OK" cd $MYMUSIC_MNT # endless loop (you may want to remove it) while true do echo -e "Starting music player (press h for help)\n" mpg123 -v -C -@ /tmp/playlist.txt clear done # never reached! echo -e "\nEnd of playlist!" else # no music partition found/mounted # play 3 beeps here to signal the failure beep beep beep echo -e "\nCouldn't mount your music folder!" echo -e "\nPlease make sure that your music partition : " echo -e " - is a valid formatted volume and is labelled $MYMUSIC" echo -e " - doesn't contain filesystem errors" echo -e "\nYou can shut down the system now or manually login and check your device." fi # to reset your system: you can use the SysRq keys : Alt+PrintScreen+b
(Optional) When generating an iso as well, you’ll have to modify the grub bootloader menu.lst file (because it would boot the first harddisk by default, not the CD!) :
# nano <buildroot>/fs/iso9660/menu.lst
default 1 timeout 3 color yellow/green white/blue
title Hard Drive (first partition) rootnoverify (hd0) chainloader +1
title Fredo's TinyLinuxMP3Player (plug your USB drive & boot CD!) kernel /kernel initrd /initrd
Ok, now it’s time to generate our tiny Linux kernel :
# cd <your buildroot home> && make
The generated kernel file (named bzImage) is well under 10Megs! And the iso is about ~14Megs.
It’s possible to test our system right away, using qemu
# qemu -kernel output/images/bzImage -soundhw all
(or with the iso)
# qemu -cdrom output/images/rootfs.iso9660 -soundhw all
Part II – Creating our bootable USB flash drive
Display all the drives to see which device is our USB drive :
# fdisk -l
Partition the drive :
WARNING! EVERYTHING ON YOUR DRIVE WILL BE LOST! AND PLEASE SELECT THE CORRECT DEVICE!
Adapt “/dev/sdX” to your own case.
# fdisk /dev/sdX
<last cylinder>+16M # 16Megs should be enough, increase it if needed.
6 <FAT16> or 83 <Linux> depending on what you prefer
(You may unplug and plug the drive again)
Next, we format the partitions / create the filesystems with the correct volume labels :
For the SYSTEM partition
# mkfs -t ext2 -L SYSTEM /dev/sdX1
For the MYMUSIC partition
# mkfs -t vfat -n MYMUSIC /dev/sdX2
or, if you’d rather use EXT2
# mkfs -t ext2 -L MYMUSIC /dev/sdX2
Finally, let’s make the drive bootable, by installing the EXTLINUX (part of the SYSLINUX package) bootloader :
# cat /usr/lib/syslinux/mbr.bin >/dev/sdX
# mkdir /mnt/usb
# mount /dev/sdX1 /mnt/usb/
# extlinux --install /mnt/usb
# cat >/mnt/usb/extlinux.conf <<EOF
> DEFAULT linux
> PROMPT 0
> LABEL linux
> SAY TINY LINUX JUKEBOX NOW BOOTING!
> KERNEL bzImage
> APPEND quiet # comment this line for debug
More kernel boot options (for the APPEND line)
Last thing, we need to copy our kernel on the drive!
# cp <your buildroot home>/output/images/bzImage /mnt/usb/
(Optional) As for the iso file (output/images/rootfs.iso9660) just burn it to a blank cdrom
Now, let’s unmount the drive :
# cd && umount /mnt/usb
PART III – Playback time!
Copy some mp3 files on the MYMUSIC partition, and boot 🙂
Press the ‘h’ key for MPG123’s help screen.
IDEAS FOR IMPROVEMENTS :
– change video mode for better display (vga=xxx )
– optimize kernel size by removing unused features
PROBLEMS ENCOUNTERED :
– BusyBox’s beep command does not produce any sound
Solution : TODO
– Certain mp3 files can’t be played
Solution : your usb flash drive might be corrupted! Re-format/try another one.
– Only mp3 files are played! No OGG, no WMV, no ….
Solution : in this version, we use the MPG123 player. You’ll need to adapt the system to use another one (hint: MPLAYER).