[ anders ]
[ resume ]
[ choppers ]
[ projects ]
[ netatalk ]
[ route66 ]
[ webgallery ]
[ mockMarket ]
[ merits ]
[ dailyBulletin ]
[ panacea ]
[ words ]
[ pictures ]
[ movies ]
[ contact ]
MaximumLinux Article: Route66: database driven car mp3 player
By Anders Brownworth
Now where would this world be if you couldn't drive around town running Linux in your trunk listening to thousands of mp3 files?
Imagine, if you would, building a Linux machine that runs on the power of a cigarette lighter and drives a serial controlled display module and a small keypad in your dash. The sound would feed through your existing stereo giving you high quality sound from hours and hours of your mp3 collection. Now imagine that this mp3 player could learn your preferences in music, playing a mix with more of the music you like and less of the music that you don't.
I got to thinking about this, and started a project called "route66". In this article we will see how route66 works and how to install it!
The Thought Process:
The way I see it, if you're going to play mp3 files in your car, you might as well use a computer. And if you are putting a computer in your car, you probably want to run Linux on it. And if you have all of that, you might as well run a database. After all, Winamp play lists leave much to be desired!
Why run a database for an mp3 player? Well if you think about it, over the course of the life of your car stereo, you make lots of selections and listen to thousands of hours of music. Wouldn't it be nice to have some software that would learn from these selections and pick more of the music you really like from the archive? With a database, you can record this information and use it. After a while, the system should be able to choose the music you would have picked so you can keep your eyes where they belong when you are driving: on the road!
Everything should be simple to use yet give you the option to go hard-core if you really wanted to. You should have the option to manually set everything under the sun for every track to clearly define how songs are picked and played. And the database should be able to remember this information on a per user basis because there is usually more than one person wanting to use the car.
After looking at websites for various hardware manufacturers, I settled on an "SBC" or single board computer that was mounted in a 1.75 inch high 1U rack mount case complete with a 133Mhz Pentium, sound card and even a 12 volt DC power supply that could take electricity from my car power system. I chose a 20 gig hard drive and 64 megs of RAM for the setup and used a PCI sound card. The SBC can come with Ethernet and USB, however my plan was to run a radio LAN so there would be no wires needed for adding music to the archive.
This is by no means required; just about any old computer would work in a car. You might even use a 12 volt DC to 120 volt AC power inverter with an second hand computer to power your setup.
The real trick was to find a display that could run a reasonable distance from the Linux machine. I settled on a Matrix-Orbital VFD (vacuum florescent display) with the optional keypad. It is driven via a 9 pin serial port and offers good readability in direct sunlight and a simple API.
After I had all the hardware lined up, I was ready to start developing. I decided to use Perl because of how quickly you can prototype applications in it and because Perl is my native language. :) Initially I had chosen PostgreSQL as a database, but I migrated to MySQL mostly for speed reasons. Only one problem remained. How was I going to play an mp3 file with perl?
After listening at length to all of the mp3 players out there, splay, which just happens to be a Linux player, turned out to be the clear winner. (if you want to hear how obnoxiously superior it is, set up a simple A/B test with Winamp and splay. The difference is night and day with the same mp3 file.) The problem was that splay was coded in C++ and we were developing in Perl, however we were able to develop a wrapper package in C++ that exported the critical functions to Perl using a program called SWIG. In a nutshell, SWIG takes routines written in one language (C++ for instance) and exports the glue logic necessary to call those routines from another language, in this case Perl.
One of the most interesting projects in the open-source world today is MySQL. It's more than worth your time to start hacking around with MySQL because I can guarantee you that within a week of playing around with it, you will discover more than one project based on MySQL that would be well worth your time to pursue. There are already many large projects that can use MySQL such as PHP and even ez-mlm, a popular mailing list manager based on qmail.
MySQL is a relational database that uses SQL (Structured Query Language) to store and retrieve data. For instance, MySQL can be used to store text and pictures for a website, or numbers representing your checkbook, or in this case, information about all of the mp3 files on your computer. Paul Dubois wrote an excellent book called (curiously enough) "MySQL" which I can't recommend highly enough. If you are interested in getting to know more about MySQL, it is absolutely essential.
Since this project was started, many great ideas have come forth. A friend of mine was developing a front end for route66 that runs on a Palm Pilot and uses infra-red to communicate. The idea is a good one, especially because there are no visible marks of the system in your car, so a would-be thief wouldn't notice anything. A similar idea would be to forget the display entirely and use voice commands and simulated voice promptings. Currently, speech synthesis on Linux is quite good. It would be quite simple for the computer to cancel the currently playing mp3 file and "hear" your voice through the music. This approach offers the best solution in terms of keeping your eyes on the road! Some people are experimenting with cd-rom drives directly mounted in the dash of their car for loading mp3 files, while others advocate ripping CDs into mp3 files while you drive!
Route66 is a fairly young project. Adding support for various different displays would require quite a bit of hacking. Several people are looking into voice command support which would also require heavy modifications.
The latest idea that I am giving some thought to is a home version of route66. Allwell Computer ***** url here ***** has recently released a "set top box" computer for $300 that has RCA outputs, Ethernet and a 266 Coppermine CPU with 32 megs of RAM that has almost everything you would need for a home version of route66. It has no fans, so it doesn't make any noise, and if it weren't for the hard drive (which must be purchased separately) it wouldn't have any moving parts at all! The system does, however, support "disk on chip" which is a solid state disk that can be used for Linux. Offloading the mp3 storage to another machine via nfs over the Ethernet would mean that you could have a box with no moving parts. Outside of this, the most interesting thing I have found with these boxes is that they can optionally come with SPDIF interfaces. (I have one of these babies on order) SPDIF stands for Sony / Phillips digital interface which allows you to transfer digital audio data between devices instead of using analog through RCA cables. The big deal here is that if your home (or car) system supports SPDIF inputs, you can off-load the delicate digital to analog conversion from that $19.95 sound card they give you in that unshielded computer to a real piece of high quality audio gear! Sound quality is sure to take a noticeable quantum leap!
Another idea stems from a side effect of the set top box. The computer comes with Composite and S-Video outputs that can be used instead of SVGA, so we could develop a full-screen display module for route66 that would run through a TV and be controlled with the included wireless keyboard. The same would be true (although a bit less practical with the keyboard) if you were to use the set top box in a car with a standard car television screen.
Powering the system also brings up a few interesting ideas. I have spent a little time looking into serial power modules and delayed shutdown circuits. It is essentially the same thing as what you would find in an uninterruptible power supply. A serial port monitors the "accessory" power in the car to see when the driver pulls the key out of the ignition. When this happens, a pre-defined shutdown time, say 10 minutes, elapses and the system is cleanly shut down and powered off. This approach requires external hardware that is arguably the duplicate of much of the hardware in an ATX power system.
A wireless network card would make for a very cool way to insert data into your route66 setup. One of the big ideas with route66 is to implement a database syncing feature where you might have a home version of route66, and an installation in your car. After inserting a bunch of music into your home installation, you turn your car system on and the latest music gets automatically downloaded. Then you drive around for a while listening to the music setting preferences, and when you come back in range of your home system's wireless network, all your preference information gets automatically uploaded to your home system!
At this point, these ideas are still in the planning stage and most of them require a significant amount of software support before they become feasible. Discussions on these topics usually take place on the route66 email list. To sign up, send a blank email to: firstname.lastname@example.org then send posts to: email@example.com. To unsubscribe, send a blank email to: firstname.lastname@example.org
Can you do this?
As projects go, route66 is no walk in the park. You should have quite some familiarity with Linux and hardware before you start tinkering around with this. Many people ask me what distribution of Linux they should use and if I could suggest exact hardware specifications. I am fairly agnostic about these things. Use what you know and what you are comfortable with. Common sense in these areas goes quite a long way.
In particular, you need to be comfortable setting up a Linux machine and getting around in the shell. It would be good to know a bit about databases, but this isn't necessary. Installing mysql and setting up your database is fairly straightforward. The package also requires a few perl modules such as DBI and DBD for database access and MP3-Info for ID3 tag reading. Familiarity with setup and configuration of the apache webserver is also very helpful.
If you feel fairly confident and you check out with the above list, you can embark on the voyage of setting up route66.
What you need to get this working:
route66 source code
http://www.perl.com/ (You probably already have it.)
perl::DBD for mysql
The SWIG package <- only needed to recompile the playerlib
Source code to splay <- only needed to recompile the playerlib
A serial port display (matrix orbital 4x20) <- only for external control
http://www.matrix-orbital.com/ you can now use the console instead)
Apache (or other webserver) <- for webedit database administration
http://www.apache.org/ <- you probably already have it
MP3-Info <- perl module for webedit to read ID3 tags
Install MySQL and set the database up to start on system boot and exit at shutdown. You will have to follow the MySQL installation documents for instructions on how to get MySQL up and running. Many of the popular distributions contain MySQL installations pre-configured which should be fine for route66.
Make sure you have Perl 5 installed (I'd be surprised if your distribution didn't already have it) and install, perl::DBI and perl::DBD for MySQL. Installing Perl modules is probably the easiest thing you will ever do. The boiler plate instructions are as follows:
perl Makefile.pl make make test make installAfter installing the DBD, (database driver) make sure that you can access MySQL through Perl. Don't run a "make install" unless all tests passed.
Once you have MySQL up and running, you will want to create a database called route66 and set up the schema. In the following example, I create a new database, show you a few essential things and then inject the schema. (eyore is the name of my Linux machine.)
eyore ~> mysql mysql -u root ... mysql> show databases; mysql> drop database route66; mysql> create database route66; mysql> use mysql; mysql> grant all privileges on route66.* to route66@localhost identified by 'route66'; mysql> flush privileges; mysql> select user, host, password from user; +---------+-----------+------------------+ | user | host | password | +---------+-----------+------------------+ | root | localhost | 2b783ab49bba4c1z | | root | eyore | 2b783ab49bba4c1z | | route66 | localhost | 3c894bc50ccb5d0a | +---------+-----------+------------------+ 3 rows in set (0.01 sec) mysql> \q Bye eyore ~> mysql -u route66 -proute66 route66 < database/schema.sql ... eyore ~> mysql -u route66 -proute66 route66 ... mysql> show tables; ... mysql> \q Bye. eyore ~>Now we have a database called route66 with all of the tables and some data as described in the schema.sql file.
Let's go over permissions briefly as shown in the table above. User "root" is allowed to access the database with a password from the localhost. (also called eyore) The user "route66" is allowed to connect from the localhost if they are using "route66" as a password. Obviously this is a little insecure, but the machine will be running in the car, so there's not much danger of being hacked. You can change passwords with the following command, but you will have to update the Database.pm file if you do:
mysql> update user set password=password('secret') where user='root'; mysql> flush privileges;Now user "root" has the password "secret". Do a select user, password from user; and see how the password is encrypted by the special MySQL password() function.
Included with the schema comes one record of data which is essentially the database version number. You can check that by selecting it:
mysql> select version from versions; +----------+ | versions | +----------+ | 0.6.0 | +----------+ 1 row in set (0.0 sec) mysql>As of this article, database version number 0.6.0 is the most current.
Default values for user, contributor and filesystem have been included in the schema.sql import you just did, however, you are going to want to add your filesystem name. The concept here is that you can have one database for more than one filesystem. For instance, you might choose to use a CD-ROM with route66 so you would use different filesystem names for each of your CD-ROMs. When the player does selects from the database, it will only ask for matches on the current filesystem.
To add a filesystem, run the database/add_filesystem script and make a note of the filesystemid that it spits out. You will need this id when you add music to the archive. (it's just a setting in the webedit route66 database editing web application.
eyore database/> ./add_filesystem what's the name of the filesystem? eyore.imaginemedia.com eyore.imaginemedia.com filesystemid = 2 done. eyore database/> ./add_contributor what's the contributor? Anders Anders contributorid = 2 done. eyore database/>Note: Contributors are not users! You have to add a user to the database as well. Contributors are the people (or servers) that contribute music to the system. A user is someone who uses the system and sets preferences.
Adding a user is as simple as running the software and going to "add user" in the options menu. or you could just use the add_user script in the same way as above.
Now we need to start inserting records into this database. Let's start by adding a few genres to the database:
eyore database/> ./add_genre what's the genre? Reggae genreid = 1 Done. eyore database/>Once you have a few genres set up, (such as rock, classical, reggae, jazz) you will want to start adding songs to the database. To do this, we will setup and use the webedit front-end.
Install the Apache webserver. (You probably already have it. Most distributions do)
Make sure the DirectoryIndex line in the httpd.conf file has index.cgi listed. (Something like this: DirectoryIndex index.html index.cgi);
Make a link from your document root directory (htdocs) to the webedit directory in the route66 source tree. If your route66 source lived in /usr/local/src/route66 and your docroot was /home/www/
ln -s /usr/local/src/route66/webedit /home/www/webeditWill make the url http://localhost/webedit/ be the administration tool. (replace localhost with your server's name)
Next, lets install the MP3::Info package so webedit will be able to read mp3 tag information from the files we are going to insert.
cd MP3-Info-0.80/ perl Makefile.pl make make test make install <- as rootNow we can start adding music! Fire up a web browser and hit your webedit directory. If all goes well, you should see the welcome page. Go to "insert" and type a filesystem path to where some of your mp3s reside. (note: Don't point it to the root of your 50 gig mp3 directory, or the program will take forever and probably crash your browser waiting for all the data to come back!) Webedit will find all the mp3 files under that directory tree and check your database to see if any of them are already inserted. If a track is not inserted, you will see an "insert" link that will open another window and let you enter the meta information about each track. The ID3 tag info is displayed if present. Several choices for each path are displayed below each field gleaned from various locations. To use one of them, just click it. If artists and albums don't already exist, the system will create them for you. Go through your directories and insert the tracks that you want in the system.
There is also an edit function to allow you to edit the song's meta Information. No delete facility exists yet as the application is still quite young.
Next you will need to edit the file Settings.pm for your configuration / liking.
Set the serial port to the port where your display connected. Usually this is something like /dev/ttyS0 or /dev/ttyS1. The software will configure this port to the default communications parameters for Matrix Orbital displays.
Next, set the up / down / forward / backward keys that you have attached to your display. They are conveniently named $up_key, $down_key ... etc. You'll see what I'm talking about. Set $display_type to be "lcd", "vfd", or "console" depending on what you have. ( "console" avoids the serial display requirement and uses your monitor as display - thanks to Michael Kidd ) The LCDs and VFDs have different character sets, so this setting picks the appropriate character set.
If you want to use the program "display" that accepts either "off" or "on" as an argument, you will need to set the serial port in there as well. I decided not to have any dependency with this file so it works everywhere even if you don't have Display.pm installed.
To finish your installation, you will want to set route66 to launch directly after boot because in a car, you aren't going to want to have a monitor and keyboard handy to login and launch the application. Shutdown is handled with a yes / no question on the serial display when you go to exit the application.
How it Works:
The over-riding idea here was "keep it simple, stupid" so I opted for 4 buttons of control organized in an up / down / right / left configuration. Essentially you navigate up and down through a menu and enter and exit menus with the right and left keys.
When you launch route66, serial port, sound system and database initialization occurs and you are shown the main menu. From here you can enter the select menu that lets you choose music by several broad categories such as artist, album and genre. Going back to the main menu, you can enter the play subsystem. Now here's where it really gets interesting!
The play screen gives you a small one-line menu at the bottom of the screen. Using the up / down arrows, you can navigate this menu and change options with the right / left keys. There are currently two options that can be set here. Many mp3 files vary wildly in their relative volume, so volume ( "vol" ) may be set on a per track basis. Changes here are global, meaning that there is one relative volume setting for each track regardless of the user. The other optional setting is the user's preference ( "pref" ) for the track. This is stored on a per track per user basis so one user can set preferences that are different than another. The concept here is as you build up preferences, the system will be able to play a more intelligent random set of music based on your preferences. If you really don't like "I'm Free" by the Rolling Stones, but you really like "Beast of Burden", then "Beast of Burden" will show up more in a random set than "I'm Free".
So how do you set the user? Moving back to the main menu, (you will find an "exit" in the "play" submenu) you can go into "options". Here you can select the current user from a list of users, add a user or set various display options. Note: some things don't work in this menu yet.
Moving on through the main menu options, you will see a radio option which is used to set up a "pass-through" if you have another source plugged into the line in. The last option, which should be fairly self-explanatory, lets you exit the application but asks you if you would like to start a system shutdown. Obviously route66 would have to be run as root in order to make this work.
Behind the scenes, route66 is essentially a giant perl script with a custom library compiled with SWIG. It constantly polls the keyboard for input and breaks away to do screen updates every tenth of a second or so. During play, route66 fills the play buffer and waits for it to empty before doing screen updates. I depend on the fact that the splay library wrapper holds the perl script up to keep the song time display somewhat realistic. More recently, Michael Kidd has hacked mpg123 into route66 instead of splay so he could get song title scrolling working. As of this writing, this code hasn't been merged into the main code tree.
If you are brave enough to attempt this crazy project, sign up to the email list and let us know about your success and suggestions! We are looking for people interested in developing some of the side projects such as speech recognition and alternate display support. If you feel that you can lend a hand, please drop us a note!
Best of luck with your route66 setup!
Jeremy Wohl - C++ splay wrapper code
Michael Kidd - console display code - scrolling song title - various other tweaks