A cross-platform Web-based audio player
kmedia is an audio player with a Web interface. More technically, it is an HTTP server that wraps the Xine media player and a tag indexing and seach engine. It is designed to work identically (or, at least, as identically as possible) on modern Windows platforms (using MinGW) and on Linux. It should be possible to build the application on any platform on which Xine can be built, but only Linux and MinGW have been tested. Part of the cross-platform design philosophy is that both Windows and Linux versions are built from the same code base, give or take a few lines here or there, and using compatible build tools (gcc, GNU make). The intention is to reduce maintenance hassles by developing essentially for a single platform.
kmediad is intended for multi-room audio applications, although it can be used as an ordinary music player. The Xine engine can handle media types other than audio, and possible future directions of kmediad might include, for example, video support.
-Supports all the audio formats that Xine supports -- MP3, FLAC, OGG, AC3, AAC, etc
-Simple browser interface
-Indexes music collections by tag
-Displays album cover art
-Low system requirements -- can run as a background process
-Near-identical operation on Windows and Linux
-Implemented entirely in ANSI-standard C, using an object-oriented model developed specifically for this project.
-Can be made to run as a Windows service (with some fiddling).
kmediad is designed to run more-or-less identically on modern Linux platorms and on Windows 7. The source bundle contains binaries for Windows, and it should not be necessary to build the program from source. With Linux it probably will be necessary to build, which means that you'll need a full C development toolchain and a bunch of libraries (see below).
There are no specific hardware requirements. The Xine engine will use a lot of memory if it is available, but the program should cope with as little as 15Mb available. Normal audio playback is not heavy on CPU or other resources. Consequently, kmediad is designed to be run continuously as a background process.
The indexing of a media collection is pretty strenuous on the CPU and disks. But this need only be done as required, and the server will operate while an index is being rebuilt.
The diagram below shows how kmediad fits between the Web browser, the media database, and the Xine engine.
The sqlite database engine maintains an index of all the media content in the server's scope. kmediad builds this index by scanning the media directory and all its subdirectories recursively, and extracting tags from files that it recognizes. The server also allows the media directories to be examined by the browser directly, to support collections which cannot be indexed because, for example, the files are not properly tagged. However, much of the useful functionality of kmediad does rely on being able to create a good index.
All actual playback operations are delegated to the Xine engine. kmediad uses Xine rather than some other media engine for two reasons. First, its API is entirely platform-neutral. It is easy to include it in both Windows and Linux code. Second, Xine is actually developed in the form of a library, with no user interface. It is better suited to being integrated into another application than, say, mplayer is, although mplayer is a capable application in its own right. On the Windows platform kmediad could, in principle, make use of the platform's built-in media services, but this would make the whole application platform-specific to a high degree.
Xine does have a number of limitations which kmediad has to work around. It's unicode support, for example, is somewhat erratic.
kmediad deals with ID3V2 and FLAC tag extraction operations using its own code, specifically developed for this project. Although there are open-source libraries available for this function, they either (a) don't build properly on both Windows and Linux platorms, or (b) require C++ or languages other than plain C, or (c) have shoddy unicode support.
The server handles four types of HTTP request:
-Control and status requests. These requests have URLs of the form
-Requests for HTML content that is generated dynamically by the kmediad application. These requests all take the form
/gui_XXX? followed optionally by a search expression.
-Requests for static content found in the media directory and its subdirectories. These requests all have the form
/media/path/to/file. These requests are mostly intended for the delivery to the browser of album cover art, and will result in a default image being delivered if the path does not correspond to a file.
-Requests for ordinary static content that forms part of an HTML page -- images, stylesheets, etc. These requests are directed to files in the program's own document root directory. These requests have URLs that do not match any of the other patterns.
Probably most requests on the server will result in database searches of some kind. On the whole, we don't want the browser to make requests that result in direct SQL queries on the database. This isn't necessarily a security concern -- kmediad is not intended to be used in hostile environment, but rather a matter of decoupling the HTML interface from the database implementation. So all requests on the server are parsed into a neutral search syntax, and then rendered into SQL as required. The search syntax is intended to be broadly human-readable, so that other types of query can easily be added to the application. So, for example, a request URL might have this form:
kmediad is intended to build under Linux, and MinGW for Windows. There are some specific hacks in the code to support those particular platforms, and making it work elsewhere could be difficult. The code contains pieces mercilessly hacked out of other projects, notably Xine and MicroHTTPD. Again, some of these sources have been munged to work in this new context. Because of the difficulty of building Xine on MinGW, the source bundle contains a binary version of the Xine libraries and matching headers.
kmediad is designed to build using MingGW and Msys. Using Msys allows us to use the same Makefiles for the Linux and Windows versions. The source bundle contains binaries of all the external dependencies the program requires, in the directories
include. To build the complete binary bundle:
c:> PATH=PATH%;/path/to/MinGW/bin;/path/to/Msys/bin make clean make bundle
This will construct a bundle under
deploy/win32 which can then be packaged up and installed, or just run in place. There is a
.suf file which can be used with Windows Setup Factory to build an installer for the program, using the files generated under deploy/win32.
To build a debug version just set
On Linux, external dependencies should present no problem, and binary versions are not bundled. You'll need to obtain those dependencices before building, along with the usual gcc build tools. In practice, it's likely that the Xine engine run time and development packages will be the only thing not installed by default on a modern Linux distribution. On Fedora, you should be able to get this by running:
# yum install xine-lib-devel
You might also want to
yum install xine-lib-extras-freeworld to get the export-restricted bits.
There are no library directory locations hard-coded in the Makefiles, but you might have to add them if your dependencies are installed in hard-to-find places.
To build on Linux:
% make clean % make bundle --or-- % make clean % DEBUG=1 make bundle
On Linux you can install the program by running
make install, which will copy the binaries to a suitable location under
/usr/share. This also creates an init script
Please note that there is a lot of ugliness in the way the build system works, in order to support both Linux and Windows from the same files. As a build system for open-source components, Windows is very under-developed compared to Linux, and some of the ugliness is necessary to remove the need for autotools and all that stuff.
Setting DEBUG=1 builds a version of kmediad with symbol tables intact for attaching a debugger. This version also produces copious console output. The Windows debug version will pop up a dosbox to put its console output in, even if run from the Explorer -- that is just an interesting consequence of the way Windows works. This will happen whether or not the program actually produces any output. On Windows, the Xine player is built with copious debug output, so running the debug version of the server is not recommended for normal use -- it's quite slow.
kmediad is relocatable, that is, so long as the directory structure built by the Makefile remains consistent, it doesn't matter where it is installed -- either on Windows or Linux. The program works out where its data files, etc., are from where its binary is located.
make bundle should build the complete directory tree under
deploy/Linux, and this bundle can simply be copied to a suitable directory under
c: Files or
/usr/share, as appropriate. Or just run directly out of the build area.
However, a simple installation can be done by running
make install on Linux, and a Windows installer can be built using Setup Factory using the
.suf file in the distribution.
Just delete the program's files. On Windows, you can uninstall via the Control Panel if you installed using the installer. kmediad does not fiddle with the Windows registry, or create any files other than as described in this document, so it can always safely be unistalled by deletion.
To start the server on Linux:
% cd [deploy_location] % ./kmediad &
On Windows you can also use the command-line:
c:> cd [deploy_location] c:> kmediad
Or just navigate to the install location with the Explorer and double-click
kmediad has no user interface. What little configuration it requires can be done through the Web browser or by editing the simple configuration file. However, by default the Windows version will pop up a small informational window to indicate that it is running -- but even this minimal user interface can be disabled from the configuration file. If you do disable the user interface, you can stop the server using the browser interface, or just by killing the process from the task manager.
kmediad does not need to run as an administrator, and doing so is probably not advisable. It does, of course, need to be run by a user who has at least read access to the place where media files are stored, and write access if you want to use the indexing and cover art extraction features. However, the indexing operation could, in principle, be done separately as a more privileged user than the one who runs the server for ordinary operation -- in day-to-day operation the server does not need, or benefit from, write access to any file, except its own configuration file.
The default browser URL is
http://[host]:30000/. At present, the port number can only be changed from 30000 by editing the program's configuration file (see below). The first time you point a browser at kmediad, you'll be told that no media directory is configured. Follow the link to the 'Server configuration' page to set it. This directory, of course, is as it is seen on the server, not the client.
The next step in most cases will be to index the media collection. This will build a database of tags in the files, making is possible to sort and search by album, composer, etc. You can start this process from the Web interface, or at the command line:
% kmediad -r
kmediad is not intended to run as a Windows service. It can operate perfectly well as part of a desktop session, and needs no special priveleges. However, one good reason to install it as a service is to allow it to operate even when nobody is logged in to the host computer.
kmediad has no built-in support for service operation. However, with some fiddling it can be made to operate as a service using Microsoft's
srvany utility. Although the process is awkward, and might be risky in inexpert hands, at least it needs to be done only once on a given machine. Here is an outline of the procedure, nearly all of which needs to be done whilst logged in as an administrator. The following description assumes that kmediad is installed in subdirectory
kevin's media server of the
Program Files directory (which is the default when using the bundled Windows installer on a 32-bit platform).
1. Obtain and install the Windows Resource Kit tools bundle from Microsoft's support Web site. This is typically a file called
rktools.exe. You'll need to accept the various dire incompatibility warnings on modern Windows versions.
2. Install a skeleton service by running the following at the DOS prompt:
c:> .exe kmediad .exe
inserting the full path to the install location of the RK tools.
3. Using the registry editor, find the new item
HKEY_LOCAL_MACHINE. Insert a new subkey called 'Parameters'.
4. Under Parameters insert two new string values:
Application c: files's media server\kmediad5\kmediad.exe AppParameters -p 30000 -f c:
inserting the correct location of the media directory.
5. Test the service using the Services Control Panel applet (In the Control Panel, under Administrative Tools). You might want to set the service to 'manual' startup until you're sure everything is working correctly.
You'll notice that, when running as a service, the HTTP port number and media directory need to be specified as command-line switches. This is because the service will not have access to a configuration file (unless, perhaps, you configure it to run as a specific user). In addition, you won't get any visual feedback that the service is running -- although this is as expected for a Windows service. Another niggle is that, when running as a service, the Windows mixer won't display the name of the program -- it will appear as 'Name not available'.
The default location of the main configuration file is
$HOME/.kmediad5/kmediad5.ini on Linux, and
c:\[user].ini on Windows. This file is written the first time the server is run, and can then be edited using any text editor. There are some settings in the configuration file which can only be changed by editing, notably the HTTP port number.
There is a specific configuration file for the Xine engine, a [install_location]/xine_config. The format of this file is described in the Xine documentatiton.
The settings in the configuration file are as follows.
port -- the HTTP port.
mediadir -- the top level directory containing media.
randomlimit -- the maximum number of items that will be added to the playlist when the user clicks on one of the random selection links.
searchlimit -- the maximum number of items that will be displayed in each section (album, track, etc) in a simple search operation.
playlistlimit -- the largest allowable playlist size.
In principle, kmediad will play any audio file that the Xine engine will play. However, in order to make the user interface responsive and predictable, it will only display files with well-known extension: .mp3, .ogg, .flac, .m4a, .aac, etc. Depending on the version of the Xine libraries installed (Linux only), it isn't necessarily the case that all of these will play. In particular, many Linux distributions ship a version of Xine that lacks MP3 support.
The indexing system currently only supports MP3 and FLAC files, and will only examine files whose names end in .mp3 and .flac.
kmediad works best when the audio collection is properly indexed. Without indexing it should still be possible to browse a collection by directories and files, but there will be little in the way of search capabilities. Of course, to index the collection it needs to be tagged, and indexing does through all the deficiencies in tagging into sharp relief.
The index file is created in the root of the selected media directory, and will normally be called
kmediad_index.sqlite. Yes, it's an ordinary sqlite database file, and it can be manipulated using other sqlite tools if required.
While the index is being built, kmediad will work on a new file called
kmediad_index.sqlite.new. When the indexing operation has successfully completed, the old index will be overwritten with the new. Therefore, it is safe to stop the indexing process mid-way, and if it should fail or crash the old index should still be available. If the index process does not complete for any reason, you'll probably have to delete the
.new file manually. The indexing process creates a file
kmedia_index.status whilst it is in progress. This file acts as a lock to prevent multiple clients trying to start an index operation concurrently. If kmediad crashes or is stopped during indexing, it might be necessary to delete this file manually.
The index file location is read from the kmediad configuration file, so indexing will not work at all until kmediad has been run at least once and the media directory configured.
The index can be created through the Web interface (on the Setup|Server configuration page). The Web interface should report indexing progress as it happens. The only obvious way to tell that indexing has finished is that index progress stops being reported.
An index can also be generated by running "kmediad -r" at the command line, even on Windows platforms. This command could, in principle, be run as a different user from the one who runs the kmediad server, if you want to restrict write access to the filesystem from the kmediad server. However, kmediad reads the location of the index from the configuration file, which in turn is determined by the user ID. So some administrative steps would be necessary to make sure that, if different user accounts are used, they have compatible kmediad configuration files.
Indexing a collection can take a considerable time, which is why tracking it from within a Web browser is so problematic.
While indexing the collection, kmediad will try to extract cover art from MP3 files. It will write a file 'cover.jpg' (or some other name appropriate to the image type) in the directory containing the file. The program will not overwrite any file when it does this, and it won't complain if the directory is not writeable. This approach to cover art extraction really works only if there is one album per folder. In fact, all of kmediad's cover art support makes this assumption to some extent. If there are files from different albums in the same directory, then the cover art file extracted from the first file that has cover art will become the picture for all albums which have a file in that directory.
At present, kmediad will attempt to read tags only from FLAC and MP3 files, and within MP3 files only ID3V2 tags (v2.2 to 2.4) are supported. There don't seem to be enough ID3V1 tags left in circulation to test support for these. kmediad reads and indexes artist, album, performer, composer, genre, and year tags. In principle, FLAC tags are not constrained to use particular names, but in practice tagging software does seem to use consistent names. But if your artist tags, for example, are not called 'artist' or 'Artist' or 'ARTIST', kmediad will probably not see them. kmediad has only very limited ability to cope with broken ID3V2 tags. I have seen all manner of badly-written tags -- tags that claim to be UTF8 but are in fact UTF16, tags that claim one byte ordering then use another, and so on. kmediad should correctly process all properly-written tags, regardless of encoding. Badly-written tags should not break it, but they might well display badly.
When displaying lists of albums, kmediad will present a graphical representation of the album if it can find one. It won't try to read pictures from MP3 files at runtime, because it's much more efficient to have this extraction done at indexing time (as described above). Consequently, any images that are presented will be found in the same directory structure as the media files themselves.
Nothing in kmediad demands that albums names are unique. The chances of finding two albums in the same collection called 'Greatest Hits' are probably quite high. In addition, nothing forces tracks in a particular album to have the same artist or composer. There is, in fact, nothing in the tagging protocols that provides a way to identify an album uniquely, unless you actually adopt a convention that makes it so.
What this means is that if you're not very self-disciplined about tagging and directory layout, kmediad's cover art support will be pretty useless. The way cover art files are located is as follows.
kmediad finds the first track in the index that has the specific album name. It then finds where that track is located on the filesystem, and looks in that directory for the files
cover.jpg. If there is no such file, it looks in the parent directory, and then that directory's parent directory, until it gets to the top of the directory tree. Consequently, fallback cover art files can be provided for whole sections of the directory tree if necessary.
If a specific album (i.e., a group of files sharing the same album tag) is distributed across different directories, then it's unpredictable which directory will be used as the source of the cover art (because the order of files in the index is not constrained in any particular way). Thus kmediad deals with cover art best if there is at most one album in each directory, and no album spans more than one directory. But no other feature of kmediad cares much about directory layout.
kmediad is intended to be able to run unobtrusively and harmlessly in the background when not in use. To that end some effort has been taken to minimise disk activity, allowing systems that support disk spin-down to continue to do so.
Of course, the disk that contains the media being played will have to spin up, at least some of the time. But a properly-configured system will realize when the disk is not in use and put it into a low-power state.
At least, that's the principle. In practice, it's dificult to predict how specific disks and drivers will behave, particularly on the Windows platform. It's impossible to be certain that kmediad will not cause the disk containing the media files to spin up unnecessarily.
The server takes some time to start up -- a few seconds, perhaps longer if hard disks have to spin up. It will not respond correctly to requests during that time, even though it appears to be running.
Because it is designed to run in the background all the time, kmediad will not initialize the Xine playback engine until it is actually required. Thus the first time a track is played after startup it may take some time for anything to seem to happen. If you're running the debug version with console output it's actually pretty obvious what's going on, but at the browser all you'll see is a delay. On some systems this might be for ten seconds or so, particularly if disks have to spin up as well (see below).
The playback engine buffers files extensively, to reduce the amount of time the disks have to be spinning. So if your media is stored on a different disk to the operating system, the disk might actually spin down during playback. This is a feature, not a bug -- spinning a disk uselessly is a waste of energy, as well as a source of noise pollution. The complication is that some Web browsers will only wait for a short time from a response from the server, particular when it's a background request. kmedia makes extensive use of background requests for tasks like updating the playback position. This means that sometimes the browser will not be updated very quickly, or you might see 'timeout' messages from time to time.
For simplicity, there is no limitation on the amount of information that is returned when listing the collection by album, composer, file, etc. If you have ten thousand albums, all will be listed on the same page. Search results are limited, to thirty results each in albums, tracks, and composers.
There is no straightforward way to change the HTTP port from the default value of 30000 on the Windows platform. Doing it through the browser is tricky because, of course, it will break communication. The only way to change the port at present is to start the server and then stop it, which causes the configuration file to be written. Then edit the 'port=' line in that file and restart.
kmediad does not handle symlinks, because they don't work in a unix-like way on the Windows platform. So the files and directories in the media directory tree must be actual files and directories, not links to files or directories elsewhere.
File sizes are likely to be reported wrongly if over 2Gb. They should still play, however.
The Xine engine reports some file playback durations wrongly. I suspect that this is particularly an issue for variable bit-rate MP3 files.
kmediad will open the audio driver when it is first asked to play something, and will keep it open thereafter. Since all modern audio drivers allow multiplexing this should not be a problem. However, it does mean that the 'busy' light on your soundcard might flash (if it has one). This behaviour is a way to work around memory leaks in the Xine engine, and can not easily be changed.
Neither the Linux nor Windows implementations will cope very cleanly with the presence of multiple audio devices. By default, the Linux implementation will use the ALSA driver, and let ALSA choose the hardware. The Windows implementation specifies DirectSound, with the same result. These behaviours can be changed by modifying
xine_config. On the Linux platform, it is sometimes easier to override ALSA's selection by setting the ALSA_CARD environment variable to indicate the appropriate soundcard. This still doesn't cope with a situation where the cards get numbered differently at boot time -- but that's a system issue, not a kmediad problem as such.