Discographer – An Automated Disc-Jockey
Contents
- Introduction
- Requirements
- Data Structure
- Basic Operation
- Configuration
- Setting Up
- Menu System
- Miscellaneous
Introduction
The original rationale for the Discographer (herein after referred to as "Disco"), was to make the playing of music in a party atmosphere somewhat easier. Anyone who has tried to select tracks with the aid of a CD album cover, will testify that under typical disco lighting conditions and with pink printing on a paisley background, the task is near impossible. Also, even given twin CD players, the cueing of the next track at the right time demands one`s full attention. The software design presented here aims to solve these issues by storing the music on a computer, together with a database to allow easy sorting and scheduling. In extremis, Disco will continue to serve uninterrupted music even in the absence of a DJ.
At the outset, it was decided that the music would stored as WAV files. Although WAV files take up a lot of space (about 10 times as much as MP3s), the main benefit is that the format is the same as that stored on a physical CD, so no encryption or decryption is required. When this project was first conceived, hard-disk storage was limited and therefore expensive. So whilst the track-listings of all CD albums were referenced in the database, only a limited number of the actual media (WAV) files were stored on disk. If an off-line track was selected, the system would issue a "retrieve request", so that the missing WAV file could be "ripped" and subsequently played. Now that hard-disk storage has become much more plentiful, it is quite feasible to keep everything on-line.
In order to generate the database entries for a newly added CD, the system is able to interrogate the GnuDB (formerly FreeDB) online database via an internet connection.
Requirements
The system operates on a client-server model, using TCP/IP protocols. The target operating system is Linux (more or less any flavour), and the server will run quite happily on a Raspberry pi. A basic knowledge of Linux is therefore assumed.
The user interface deploys the curses
package, to give a simple, but easily readable operations window. Because the program makes no use of any specific windowing system (e.g. X-Windows), a simple text-based terminal client program can be used (for example, via "ssh" or "putty") to access the server remotely. The server machine will normally be run "headless", that is, without an attached screen.
A CD-ROM drive is obviously needed, although this can be attached to another computer running the local version of the disco server, as will explained later (see Local Operation Mode). Also CD writing capabilities are required if you want to make your own backup copies of an album.
The external command cdparanoia
is needed in order to "rip" albums from CD; and cdrdao
is required in order to write CDs.
If it is desired to run a local server on another computer, the Network File System (NFS) must be configured, to allow the database files to be mounted remotely.
To interface with the audio hardware, the pulseaudio
sound server must be installed.
If it is desired to compile the software from source, the following additional libraries are required:
- libncurses5-dev (curses development libraries)
- libpulse-dev (pulseaudio development libraries)
Data Structure
The database is simply a flat-file list of albums, held as plain text files in the sub-folder "Data". Each file consists of 3 records for each track on the album, containing the artist, the track title and sundry information such as the track length, last played time, etc. The first set of 3 records describes the album itself. Each file name is of the form: cdAAAA
, where AAAA
is the album number in decimal (e.g. cd0001, cd1785, etc.). Within each file, the Nth triplet corresponds to the 2-digit track number, where track 00 refers to the album itself. The subfolder "Media" holds the actual WAV files, and these are named AAAA_TT.wav
, where AAAA
is the album number, and TT
the track number (e.g. 0746_12.wav).
There are additional subfolders, such as: "PlayLists" (which holds pre-constructed, saved (off-line), play-lists which can be plugged-in to the running system), "History" (records of past play-lists), "Logs" (archived log-files) and "Local" (which contains data relating to CDs ripped locally with the aid of GnuDB). There is, optionally, a folder called "Links," which contains the data for any tracks which are linked together in sequence (see track-linking, section 8.1).
A file called history.hst
holds the history of tracks played in the current session, and the file disco.log
records events such as CD ripping and also any errors encountered. There is also a file called disco.cfg
, which contains the parameters controlling the behaviour of both the server process and also any local client commands.
Basic Operation
Once the software is installed, the necessary folders created, and the configuration file altered to suit the local environment, the master server process can be started in the background by typing discoserver --start
. This sets the ball rolling, and a track will be selected and played. The operation will then continue, selecting successive tracks depending on the playing mode determined from the configuration file (more details of this, later). To schedule additional tracks, type disco
to log in to the play-list screen. The database can then be searched by typing s
; and from the list which will appear, tracks can be added to the current play list by typing a
. Unwanted tracks can be removed from the play list by typing x
, and a track can be faded out and skipped if it is already playing, by typing Control-F
. This is about all you need to know to run an automated music player. Full details of other features are given in the following sections.
Configuration
Configuration data is held in a file called disco.cfg
. This is a plain text file, and can be edited to reflect local preferences. It consists of name-value pairs. Comments are introduced with a hash (#) symbol. A sample configuration file disco.cfg.sample
is provided as a starting-point, the contents of which are discussed in detail, below.
Setting Up
See the document Getting Started for full details.
Create a folder (the working directory) in some convenient location. If you have downloaded the pre-compiled version appropriate to your system, simply unzip the file into that folder. This will create the two binaries discoserver
and disco
, the configuration file disco.cfg
, and also the necessary sub-folders (Media, Data, PlayLists, History, Links, Local, Logs, and Reports).
Type discoserver --start
and then disco
, and an empty window will appear. There will be, as yet, no database files, so place a commercial CD in the drive. After a short time, the window will display the track-listing (assuming that there is an internet connection, and that GnuDB recognizes the CD in question). Sometimes, there will be more than one match for the CD on GnuDB; press the right or left arrow keys to review the next or previous match.
Press F9
to add the CD to the database, followed by the F10
key to rip the tracks and bring them on-line. The ripping process can be monitored by tailing the file disco.log
. When the ripping is complete, the outcome can be checked by typing CTRL-W
, to assure the integrity of the WAV files.
The procedure can now be repeated with other CDs, to build up a reasonable selection of artists and tracks.
Sometimes, a GnuDB listing will contain errors; these can be corrected by typing e
for edit, and altering the faulty entry. The Up and down arrows work as normal: Page Down
selects the next track and Page Up
the previous one. Track 0 refers to the album itself, so that the album artist and/or the title can be changed. The escape key finishes the edit, and you will be asked to confirm the changes.
Occasionally, GnuDB can find no information at all, and the listing will then appear as a sequence of "Track nn – Unknown" entries. Again, one could use the editor to fill in the details, but a better plan is to import a track listing by selecting: "Maintenance –Imports—Plain text import". Suitable track listings can often be obtained from web sites such as "discogs" (albeit involving some massaging of the data). The format for the imported text file must be: "Artist - Title" (N.B. a single space either side of the hyphen (-). There are other import options available, such as XMCD.
Menu System
General
Each menu consists of a number of options, with a movable highlight. The highlight can be moved up and down by use of the arrow keys (↑ and ↓), and the highlight wraps around at the top and bottom of the options (an exception being when a playlist is displayed). Pressing ENTER
on an option will cause some action to be performed, (e.g. a new menu or display of extra information). The ESCAPE
key will cause a return to the previous level, or the cancellation of the current action.
In navigating menus, pressing a letter key will cause the highlight to jump to the first option with that initial letter. This does not apply to play-lists.
The F1
key will display a brief help screen in most menus. Also, there is usually a line at the foot of the screen giving reminders of the most commonly used keys.
When the disco
command is first invoked, the menu displayed will be the current play-list (possibly with only a single entry). Pressing escape here will display the main menu (see below).
PlayList Menu
Assuming that there is more than one entry, u
will move an item up the list, d
moves it down the list, and t
will push the item to the top of the list. Note, however, that the top item (the currently playing track) cannot be moved or displaced. The following also applies to other track-listings, such as saved (offline) play-lists, and reports.
s
will display a dialogue to search for an artist and/or a track title; anda
will add an item found to the current playlist.l
will display the full track-list for the album to which the item belongs.a
will prompt for an album number and display the track-list for that album.h
will display the history of tracks played recently.e
allows editing of the item.m
displays more tracks by the current artist.r
will randomize (shuffle) the play-list.c
will clear the play-list, with the option of saving it under another name.k
will keep the play-list, saving it under another name.f
(favourite) will add the track to a nominated saved (offline) play-list.p
will show a menu of saved play-lists, and a chosen one can be appended to the current play-list.x
will delete an item from the current play-list (not the top item, though).Control-F
will fade out and skip the currently-playing track.
Other control characters are as follows:
Control-P
will pause the music, and if repeated will resume the playing.Control-S
will add the track to the short-list, andControl-D
will remove it.Control-N
will cause the track to be unavailable for automatic selection.Control-O
will force a track offline by removing the WAV file.Control-U
will add a track to the "unplayable list", without off-lining it.Control-T
will totalize the playing times of all tracks on the list.Control-R
presents a re-sort menu offering several different sort orders.Control-V
reverses the current sort-order.Control-A
(local server only) starts/stops a local audio stream to play the current track.Control-L
(local server only) plays/stops the track under the cursor in a local audio stream.Control-G
(master server only) Go: starts the music playing.Control-E
(master server only) End: stops the music at the end of the currently playing track.Control-K
will kill (cancel) any outstanding retrieve operation.Control-I
will check a track for integrity (detect glitches, etc.).Control-W
will check the integrity of a whole album.
(The utility of some of the above controls will depend upon the context and current menu).
The following function keys are mostly universal:
F1
: Display a brief help screenF2
: Start a new search. Find a specified string within the current listing.F3
: Find the next matching string.F4
: Print to a specified file.F5
: Re-acquire the database and return to the current listing.F6
: Browse to the first entry in a list (Control-Page Up or Control-Home).F7
: Browse to the last entry in a list (Control-Page Down or Control-End).F8
: Apply various actions to all items in a list via a menu (see below).F9
: Add an album to the database (usually with a GnuDB-derived play-list).F10
: Bring on line any items in the play-list that are currently off-line.F11
: (Linux command) Go full-screen display (not very useful).F12
: No effect.
The F8
apply menu has the following options:
- Add all tracks to the current playlist
- Put all tracks on a specified (saved) playlist
- Remove all tracks from normal Selection
- Put all tracks on the short-list
- Remove all tracks from the short-list
- Edit all artist strings: This will replace a specified string by an alternative string in all artist names (case sensitive).
- Edit all title strings: As above, but for all title strings.
- Force all tracks off-line: Extreme caution is advised, as there is no undo option, and the WAV files are deleted immediately.
Main Menu
The main menu is reached by pressing the escape key whilst the current play-list is being displayed. There are 10 options, the first 6 of which set the playing mode of the program (the initial mode is set by the PLAYING_MODE token in the configuration file).
Console Mode:
This is intended for use in a live DJ environment (possibly with a directly connected terminal), and can be programmed to offer password protection. In this mode, automatic track selections are made from the short-list only.
Jukebox Mode:
This is for unattended operation, track selections again being from the short-list.
Random Mode:
Here tracks are selected randomly from the entire database.
Mixed Mode:
In this mode, short-list tracks and random tracks alternate.
Playlist Mode:
The user is prompted to choose a saved play-list, from which tracks can then be selected.
Play-mixed Mode:
Again the user chooses an offline play-list, but random selections will alternate with those from the chosen list.
Local Audio:
(Local server only) start or stop local streaming of the currently-playing track. See section 8.2 for details.
Maintenance:
This brings up the maintenance menu. This can be protected by defining the token "PASSWORD" in the configuration file (see below).
Shutdown/Reboot:
Menu to stop or reboot the server and/or the programs (password protection optional).
Help:
Displays a brief summary of the controls; also accessible via the F1 key.
Note: the password protection offered by the "PASSWORD" token in disco.cfg, is not intended to be very secure, since the configuration file is in plain text; the intention is to prevent curious bystanders from causing problems on the disco console by idly pressing keys. To turn this feature off, either set PASSWORD to blank, or remove it altogether. When in use, the password protection applies to Console Mode, Maintenance, and Shutdown and Re-boot options.
Maintenance Menu
This consists of some 15 options, concerning routine maintenance of the system.
Album Tracklist:
Displays the track listing for the last-remembered album.
Report Generator:
Brings up the report generator menu.
Imports:
Displays the track list imports menu.
Back Up Album To CD:
Writes an album to a CD (requires "cdrdao").
Artist/Title Search (Case Sensitive):
Special search respecting alphabetic case and leading and trailing spaces.
Global search (Case Sensitive):
As above, but the search is everywhere in the database.
Edit Album:
Invokes the editor on the specified album. Note that only the artist, title and track time may edited directly.
Delete Album:
Deletes an album – use with care (There is no undo option, and the associated WAV files are deleted immediately).
Correct "Various Artists" Format:
Attempts to normalize contents of compilation albums. These often have "various" for the artist field, and combine artist and track in the title field, or vice versa.
Transpose Artist & Title:
Corrects a faulty GnuDB or other listing where the track title is shown before the artist name, instead of the reverse.
Capitalize Artist & Title:
Ensures that each word in artist and in track begins with a capital letter.
Capitalize (Lower-case First):
As above, but convert all items to lower-case first (some GnuDB entries are all in upper-case).
Capitalize ALL Artists & Titles:
Performs the capitalization on the whole database – use with caution.
Recalculate Track Timings For Album:
Recalculates the track times for an album from the sizes of the WAV files.
Refresh Database:
Re-reads the whole database into memory, as in the initial start-up sequence (this is also available by typing F5).
Report Generator
Compiles a list of all albums in the database in numerical order, with sorting options. It shows the total time and also the number of tracks.
Lists all tracks in the database, sorted by artist, with or without duplicates.
Lists all tracks in the database, sorted by track title, with or without duplicates.
Lists tracks on the short-list (denoted as status '.
' on the track list).
Tracks not on the short-list.
Tracks which are not normally selected automatically.
List of tracks not actually on-line (denoted as status '-
' on the track
list)
Tracks deemed unplayable by reason of being too short, too long, or
containing bad language, amongst other problems (Status '-
' on the track
list).
Searches through the database looking for tracks with fewer than a specified number of unique tracks, with a view to transferring these tracks to another compilation (more details later). This can take a very long time to run.
This will reset all the played counts in the whole database. Use wisely.
This is a check that all the tracks in each saved play-list are, in fact, playable.
Scans the database, and compiles a browsable list of monaural tracks.
Performs a duplicate check on a specified album.
Runs a WAV integrity check on all albums. This will cause a lot of network traffic, and should not be run on a local server.
Presents a list of the last 58 archived history files. Note that history files (and log files) are archived each time discoserver starts, and at 02:00 hours each day.
As an adjunct to the report generator, there is also a printing menu which will dump the current listing to a file. All output will be written to the "Reports" subfolder in the working directory. Press F4
and the following options will be available (this should work in almost any context):
Output is of the form: "Artist – Title"
Output more or less as shown on-screen.
Conventional comma-separated listing, with optional index numbers.
Imports Menu
This has a number of options to assist in creating and editing new albums.
This will take a folder containing WAV files listed in the format "Artist – Title.wav", and create a new album entry in the database, optionally writing it to a CD. See the configuration file for naming conventions.
The XMCD format, as originally employed by FreeDB and subsequently by GnuDB.
This will import a file in the format "Artist – Title" to overwrite an existing album listing (useful when GnuDB produces no result).
Miscellaneous
Track Linking
Sometimes it is desirable to be able to play certain tracks as a linked group. In particular, if the database is used for classical, as opposed to rock/pop music, a suite of small pieces or a symphony, might benefit from being played in the intended sequence. In order to link tracks, press q
when the desired first item is displayed. The program will display whether the track is linked, and if not, will ask if this is to be made the head of a new chain. If the track is already part of a linked chain, the whole chain will be displayed, and the user will be given the opportunity to add to the chain, or possibly delete it. Assuming that a track has been made the head of a new chain, then pressing q
on further tracks will present the opportunity to continue adding them, and other tracks to the chain. The data pertaining to the linked tracks is held in the sub-folder "Links". If a member of a chain other than the head item is auto-selected, the program will replace that track with the track at the head of the chain, and append all the other linked tracks to the play-list, thus ensuring the tracks are played in the correct order. Note that this only applies to tracks automatically selected: tracks added manually are played as normal, and no account is taken of any existing links for those tracks.
Local Operation Mode
In this mode, discoserver acts in a subservient role to a master server running on a different machine, but sharing the database. When combined with a local disco client, it has the following uses: it can employ the CD drive on the local machine to read and write CDs (especially useful if the master server does not possess a CD drive, or it is inconveniently located). It can stream the currently-playing track from the master server over the network and play it on the local sound-card (with Control-A ), and also preview tracks locally, independently of the playing track (using Control-L).
The local mode is facilitated by setting the SERVER_MODE token in the configuration file (disco.cfg) to "Local". Note that in order for the local mode to work correctly, the discoserver program running on the local server must have root privileges: this is because it is necessary for the program to mount the database files from the server via NFS, and only root can do this. The database folders Data, Media, and PlayLists should be exported from the master server by editing the file "/etc/exports". Of the other folders, Logs, History, Local and Reports, the local server will use its own local copies.
The --start
parameter to discoserver may be omitted, as this is not relevant to a local server, which takes no part in the scheduling of tracks, although tracks can still be added or deleted manually.
Since the local server does not schedule or play tracks by itself, all of the items from PLAYING_MODE downwards in the configuration file are irrelevant.
To preview (play) tracks in local mode, press Control-L
. A new window will appear, showing the artist and title of the track, the elapsed time, and instructions for skipping to and fro. The escape key will stop the operation. Note that tracks played in this mode, are not pre-processed in any way and are therefore effectively played "raw".
Standalone Mode
In this operational mode, the local discoserver process does not run, and the disco
client program connects only to the master server. This is equivalent, in practice, to running a disco client on the master machine via a terminal server such as putty
or via ssh
, except that audio streaming services are now available, and tracks may be played locally (using Control-A or Control-L as described in the previous section).
As with Local Server Mode, most of the entries in the configuration file have no significance in stand-alone mode.
Command Line
The disco
command supports a command-line interface (CLI). This is of use for building-into scripts, such as, for instance cron
, but one may find other uses. Here are some of the more useful commands:
--skip
Fade out current track and play the next one.
--stop
Stop the master server at end of the current track.
--stop-local
Shutdown the locally-running disco service.
--playlist
Display the current playlist.
--playlist-search
Display a list of saved (offline) playlists.
--playlist-use <playlist>
Append specified playlist to the current playlist.
--playlist-add <aaaa/tt>
Add specified numerical album/track to the current playlist.
--playlist-del <aaaa/tt>
Delete album/track numbers from the current playlist.
--shortlist <aaaa/tt>
Add album/track numbers to the short-list
--shortlist-del <aaaa/tt>
Remove album/track numbers from the short-list
--search --artist --title
Search for artist and/or title.
--album
Show only album details
--history
Display history of recently played tracks.
--audio
Start the local audio stream.
--audio-off
Stop the local audio stream.
--mode
Display the current playing mode
--mode <playing_mode>
Change the playing mode.
--mode <playing_mode> --playlist <playlist name>
Set the playlist to be used with playing mode "playlist" or "play-mixed" modes.
--help
A brief summary of commands is displayed.
As a reminder, playing modes are: Console, Jukebox, Random, Mixed, Playlist or Play-Mixed.
For the search command, one may specify --artist <name>
or --title <string>
, or both; partial names are accepted, and alphabetic case is ignored. The optional argument --album
, will restrict the output to just the album details.
The output for play-lists and search results is in CSV format, as follows:
album_no/track_no,"Artist","Title",Track-Time,"Album Title",online,shortlist
where album_no
is 4 digits, track_no
is 2 digits, and track_time
is mins:secs. Online is Y
or N
. If the track is on the shortlist Y
is shown, or else N
. Some examples:
0797/19,"Sister Sledge","Thinking Of You",03:57,"Hits 93 Vol 3",Y,N
1247/11,"Led Zeppelin","The Wanton Song",03:59,"Physical Graffiti",Y,N
0304/12,"Supergrass","Sun Hits The Sky",03:38,"Now 37 - CD 2",Y,Y
If the command -- album
is also given, the output refers to the album alone, in the format:
Disc-ID,Album_no,"Artist","Title",Total-Time, No_of_tracks
Where Disc-ID is the 8-digit hex number as used by GnuDB and total-time is the length of the album in mins:secs. Examples:
D512570E,1247,"Led Zeppelin","Physical Graffiti",78:10,14
45110E14,0109,"Various Artists","The Greatest Hits Of 1981",71:24,20
C211600F,2356,"Various Artists","Nothin' But The Blues - CD 2",73:23,15
The output from --history
is in the format:
album_no/track_no,"Artist","Title",Track-Time,Date-played @ Time_played
Examples:
1738/05,"Brendan Benson","Alternative to Love",04:31,23/02/23 @ 17:05:38
0839/13,"Status Quo","Tongue Tied",04:21,23/02/23 @ 17:10:05
2568/02,"Depeche Mode","Enjoy The Silence (Extract Fr",03:45,23/02/23 @ 17:13:56
Note that in this instance, the artist and/or title may be truncated so as to fit on a line.
Implementation Notes
Track Selection
Regardless of the operation mode (Jukebox, Playlist, Random, etc.), tracks are selected in a pseudo-random fashion. A time-out is set initially, and tracks which have been played within that time, are rejected, and a count incremented. If no candidate tracks are found when the count expires, the timeout is halved, the counter reset, and the process repeats. For modes which involve a (saved) play-list, a linked-list of the contents is constructed, and the counter is set to the number of tracks found in the play-list. In the case of a short-list mode, a linked-list is compiled of all items on the shortlist, and the counter set to the total found. If the mode is "Random", tracks are selected at random from the whole database. Also, should the time-out reach zero in all the other modes, a random track will be chosen. This algorithm is designed to ensure that music will always be available, and that adjacent repeats of a given track are unlikely. To supplement the latter aim, a check is made that a given artist has not been played within the last up to 10 plays (although this restriction will only apply if a sufficient variety of artists exists in the database).
In addition to the currently playing track, a secondary track is selected to be the "pending" (next-to-play) track. Track selection takes place in a background job, and so does not interfere with the normal running of the discoserver process.
Track Preparation
Once a track is selected, a preparation job is run in the background. The purpose of this is to find the true start and end of a track ( i.e. to discard leading and trailing silence) and to find the average (actually RMS) level of the track. This is to produce a scale factor, in an attempt to level-out the loudness variations amongst tracks. Also it is determined during this process whether the track is monaural, rather than stereo. The track start time, end time, scale factor and mono/stereo status are stored as part of the track data for subsequent use by the player process.
Player Process
When a track becomes the current playing track, the player process runs in the background. Samples are read from the WAV file in blocks of 4410 samples, which represents 1/10 of a second of sound. The samples are multiplied by the compression level (if not set to 1), and the scale factor adjusted to ensure that the samples do not exceed the maximum peak level (just short of the maximum 32767 samples). This is to avoid possible problems with some digital to analogue converters. If the track is marked as monaural, one channel is sightly delayed to provide some ambience for a pseudo-stereo effects. Finally, the block of scaled samples is written to a pulseaudio stream and thence to the sound-card. Note that the compression, if used, is an upward dynamic compression, meaning that quieter sounds are amplified.
Back to top