MC Foo - Architecture



MC Foo is implemented in Python, heavily using the Twisted framework.

We will use existing Ogg/MP3 libraries as backend, and will never touch file contents or decompression ourselves. Where Python-accessible free libraries are not available, a suitable players will be used in batch mode. (That is mpg321, for now. Anyone know of a free Python MP3 library?)

The rest of this document is obsolete, and will be rewritten. Dj is a Twisted "tap" now, and forks only to run mpg321 -- as soon as a suitable free Python-accessible MP3 decoding is found, it will be replaced.


It may be useful to keep this picture open in another window while reading this.


dj is a separate program running on a sound-enabled machine. It listens on a network socket for incoming connections. Sockets are the primary way of controlling the server.

The server itself manages the queue. Most of the things that can be splitted off to separate programs, will be. This includes just about anything that does not need both read and write access to the queue.

Keeping the playqueue from draining

pick-a-song is executed by the server and left running. It uses stdin and stdout to communicate with the server. On stdin, it receives the list of active profiles (on one line, separated by spaces). The server sends this list whenever the queue starts to drain. On stdout, it writes 0..n song paths. The server can not rely on the number of songs returned by pick-a-song. If pick-a-song exits, the server will start a new one.

Making permanent profile changes

remember-profiles is executed by the server whenever it wishes to make the current, adapted, profile permanent. This can happen e.g. once per minute or when requested. It is given 1..n profile names on the command line, and the changed preferences on stdin. remember-profiles reports error by its exit status. The protocol used on stdin needs to be defined. remember-profiles splits the preferences evenly between all listed profiles.

Caching a song to faster media

Caching is specific to the media backend; there will be file-cache and http-cache.

backend-cache is executed by the server and left running. It uses stdin and stdout to communicate with the server. On stdin, it receives a song path. It starts an asynchronous copy of the song to faster media, if deemed necessary. On stdout, it writes the song paths of succesfully cached songs. If backend-cache exits, the server will start a new one. Needs more information on stdin?

Play the song

turntable is executed by the server and left running. It uses stdin and stdout to communicate with the server. On stdin, it receives commands (specify what commands and the format) , on stdout it gives responses to these commands (specify) . It can e.g. pause the music, skip to next song, fast forward, etc. If turntable exits, the server will start a new one.

List all (or only available) songs

list-songs gives the client programs a way of finding out what songs have been added to the player. It is not clear yet whether it is useful to implement this as a separate server, a child executed by the server with fd passing (will close the connection), pipe the data through the server, or what. Also consider static files and sendfile(). think

Administrative Utilities

Create a new group of songs

Create a new wad of songs, e.g. from a CD full of mp3's. Use ID3 tags, standard filenames, etc for obtaining information. We probably need different utils for different storage types. think

Initialize a new profile

Create a new, empty, preference profile. May be as simple as touch profilename

User administration

Access control, authentication, profiles.. think

End-User Utilities

Most end user utilities really should be modular, but due to user interface requirements, may end up in one big executable. We'll try to provide simple command line versions of everything as well. Maybe even a WWW interface, though there we will probably use Perl. tcpclient? Authentication?

Request a song

Connect to the server with sockets and request a song.

Activate/disactivate a read profile

Select what profiles are used for selecting the songs

Activate/disactivate a writable profile for user X

Select what profiles are changed when user X expresses his preferences

Skip to next song/Fast Forward/etc

Simple, very operational, control of playing. Preferably with Gnome panel and lirc interfaces. How to do fast forward and reverse well? How do we control the low level player, e.g. mpg123?


The player should learn what songs are liked and what are not. For this, we will use the notion of profile. A profile is a set of song-related preference information. Profiles can include other profiles without limits.

There is one active profile that is used to determine what songs will be played. This is called the current read profile. The profile itself is a pseudo profile that only contains other profiles.

There is one active write profile per user. This means preference hints from different users can be stored in different profiles. This is also a pseudo profile, only containing other profiles. The preferences are stored evenly in these subprofiles.

For example: current read profile includes "classical", "user A" and "user B", "evenings". Current write profile for user A includes "user A", current write profile for user B includes "user B" and "classical".

Picking random songs with a bias

Describe the new method here

Miscellanous thoughts

Volume balancing (make different recording levels as loud when playing): Save it always to profile "_volume"? Update as a batch run? Use master volume for user volume, PCM volume for balancing?

"Style" of songs (ID3 Genre is related, but not the same), assigning preferences to changes from song A to song B, marking songs as "intro"/"speech"..

Access control: PAM? SSL? Do we need encryption, or just auth?

Last Modified 02-24-2002 12:19.