In this section we come to description of our client-server architecture. What we are looking for is not a new application but rather a strategy that allows the different kernels to communicate and work together. To accomplish this we have based the architecture of JavaMusic on the work by Anselm Baird-Smith [BS95].
The first part of Baird-Smith's work focuses on the dynamic and distributed personalization of applications. We will give a simple example as an introduction. Consider an editor which connects itself from a remote computer to an application whose graphical interface we want to personalize. The focused application incorporates a communication kernel through which the editor can connect itself. Once the communication is established the editor can change the appearance of the application (e.g. window color) and its behavior (e.g. mouse click). This concept of distributed personalization is worked out first by defining the concept of Resource and second by the definition of a communication protocol between the application and the editor.
In the following sections, we will call the editor the client and the application the server.
The Resources of an application are defined as the objects which the application developer has made accessible and editable such that the end user can personalize the application.
A Resource has a name, a value, and an identification number. This identification number is unique such that at any given time there exists a bijection between the set of identification numbers and the set of Resources.
The Resources are structured hierarchically into a tree structure: a Resource can have any number of children, and one parent.
If we want to establish a communication between the client and the server a communication protocol must be defined. The primitives currently found in the protocol include setting and retrieving the value, requesting the statistics, and obtaining the list of children of a resource. The protocol also includes a notification mechanism which informs the clients of the operations performed on a Resource. To the operations defined by Baird-Smith, we have added the creation and deletion of Resources.
In JavaMusic every instance of SoundProcess, Texture, VirtualInstrument, or Parameter is stored as a Resource and can be created and manipulated by clients that connect themselves to JavaMusic. The functionality offered by JavaMusic has become minimal. The application reduces to a server, concerned only with the management of the Resources and notifying the clients of any change. Examples of clients that will connect to the server are CAC environments and synthesis kernels. The question we will concern ourself with next is how a CAC environment can call a synthesis kernel and ask to synthesize a SoundObject. How does a CAC environment even know what clients are connected, and what services they provide?
We have adopted the following solution. Clients can create a Resource which includes a reference to themselves. This Resource can have children describing the services the client assumes. We have defined a class Service for this description. This class holds the name of the service as well as the type of arguments needed and the type of result returned by the service.
We will call a client that settles itself as a Resource and publishes a number of Services a Provider. A client can now inspect the available Resources and search for the appropriate Provider and Service. To make use of a service, the client sends the Provider a Request. A Request is an object containing the name and arguments for the service. On completion the Provider returns the Request, including the result of the service, to the client.
This modular architecture provides the means of communication between different parts of an application without the need of knowing each other's interface before hand. New Providers and new Services can be added easily using the dynamic instantiating Java offers. What Providers are inserted into the environment, and what Services they implement is open to the user. The environment becomes a collection of specialized Providers, each dealing with one specific aspect of composition [Opp96].
Providers which we need in particular are editors for Textures, SoundProcesses, and VirtualInstruments, CAC environments, and synthesis kernels. Some of these, such as the editor for Textures, we will need to create ourself. Others, such as the synthesis kernels, can be based on preexisting software. In the next paragraphs we comment on some of the currently existing Providers.
We have made a wrapper class that abstract the Common Lisp environment. This environment attains its importance because of the CAC environments such as PatchWork, OpenMusic [Ass96] and Common Music, which are written in the Common Lisp language.
Communication between JavaMusic and Common Lisp is established over a TCP/IP connection, and enabled in both directions. Services in the JavaMusic environment can be called from within the Common Lisp environment, and clients, in their turn, can request the evaluation of a lisp expression.
Most synthesis kernel were developed in the ANSI C language on Unix machines and have a command line interface. We compile these libraries as shared libraries. Java has the facility to declare methods as native. This specifier determines that the method is written in C and is implemented in a shared library. Using this facility we create a wrapper class which calls the main function of the synthesis kernel. We are currently using CSound [Ver86].
The Player is a Provider which offers to synthesize a SoundObject. It does this with the help of the available synthesis kernels and a Scheduler for every kernel. The Scheduler converts the VirtualInstrument and the Parameters to a description understood by the kernel before asking the kernel to synthesize the SoundObject. If a user want to provide a new synthesis kernel, he also has to provide the associated Scheduler.