How does bliss work?
WARNING: techie post!
bliss is built to achieve my goal of fully automated, rule based, music management that can run on a home server. It is designed as always-on, background server software (or a daemon) that is capable of recognising additions and updates to a music library so that the library can be assessed against a set of rules and the rules enforced automatically. This is a technical post that describes how bliss is built to achieve these goals.
bliss is split into six separate pieces that perform specific tasks. The storage layer reads the filesystem and changes to the filesystem and communicates this to the tag index. The tag index builds an index of what data is stored in which music file. When the tag index recognises new albums, artists or similar, it tells the music model. The music model stores the albums and their compliancy. When the music model has noticed an album change, it passes the album to policies which encode the rules you configure within the bliss UI. The policies respond back to the music model with whether the album is compliant. They also take action to try to make the album compliant. The bliss web UI plugs into the previous layers to show you what is happening within bliss. Finally, the runtime plugs all the parts above together, and starts bliss running.
All of these layers run in a Java VM which is why Java must be installed for bliss to work. Running in a Java VM is convenient for development, because it means most of the code is inherently cross platform and I only need to build bliss once. Only a few aspects of bliss have to be written for specific platforms (more on this later).
Here's more detail on how each module discussed above works.
The storage layer is concerned with informing bliss what music files exist and their contents. The storage layer informs bliss when files change and provides a way to read the contents of music files so they can be organised later. bliss needs to be able to cope with new files being copied into the music directory, new music files being ripped from CD into the directory, music files being edited by another program and similar operations.
This is one of the few platform specific parts to bliss. This has to be platform specific ( until Java 7 is released) because the way in which bliss listens for filesystem changes is different on different operating systems. bliss uses ReadDirectoryChangesW on Windows and iNotify on Linux and (to be released soon) FSEvents on the Mac. These tools are abstracted behind an API called JNotify. I had to hack JNotify a little for the Mac, because JNotify keeps a record of all files being watched in memory. For large collections, this is an unaccceptable load. I hacked it to use JDBM (more on JDBM later) to store the file paths.
The music files themselves are read with an excellent API called JAudioTagger written, mainly, by the same guy that wrote the equally excellent tagger Jaikoz. This allows bliss to find out the album for a particular music file, extract or insert album art, and more.
The tag index records what is stored where in your music library. This is important for fast operation. For instance, if a bliss rule needs to know all albums by an artist, it can be answered instantly from the tag index rather than searching through your entire collection. The tag index is stored on your hard disk using JDBM.
The music model stores all albums, artists and similar 'domain level' music concepts, with their compliancy. More than any other layer, the music model is represented in the bliss web UI. Like the tag index it is stored on hard disk using JDBM.
Policies are what assess your music collection against your rules and attempt to fix any problems. If they can't fix a problem, they provide manual responses that can be chosen in the UI. The cover art policy is an example of a policy. It checks that art exists and is stored in the correct way.
The bliss web UI is totally separate to the previous layers, and is not required for bliss to run. The web UI is written in Scala using the Lift web framework. It runs inside the bliss process using an embedded Jetty server.
The runtime is not especially interesting, it is merely the first part of bliss that is started and so it plumbs all the layers above together. It also starts a debug web server which can be used to gather extra information about how bliss is working.
I hope this overview of how bliss works was interesting. If you have any more questions, fire away and maybe I can update this post for other interested readers