# GDAM Developer Documentation

Dave
Benson

## Introduction

This document assumes you have basic experience with GDAM as a user. Please see the user's documentation.

The GDAM source code is divided into a few major directories:

- `common/` contains various libraries which are general enough to use in the client and the server.

  - gdam-protocol.h defines the constants of the client-server protocol.

  - gdamarg.h defines a system for generically setting and getting object parameters. It is mechanism we use to, for example, set a gain filter's volume, both within a process, and over the client-server channel.

  - gdambuffer.h contains a simple FIFO buffer, used all over.

  - gdammathfunction.h is a little less important: it is a c-style arithmetic expression parser.

  - gdamplugin.h takes care of instantiating a GtkObject from a type name. (whether it is a builtin to the process, or a plugin)

  - gdammodule.h takes care of loading plugin libraries and any libraries they depend on.

  - gdamsample.h defines a sample-type and a fixed-point math type, GdamFixed.

  - gdamsampleconverter.h contains code to convert between any two sample types.

  - gdamsearchpath.h searches a colon-separated path for a certain file.

  - gdamwaitpid.h registering functions to get called when a child process exits.

- server/ contains all the rest of the code for the server and its plugins.

- client/ contains generic client code for the gdam protocol. You make a GdamChannel which is your connection to the server, then you funnel GdamRequest across it: the GdamRequest structure contains pointers to function to call when you get the response. the server and its plugins.

- component/ defines client-side models of the server-side sources. These use the GdamArg system to implement a model-view pattern.

- skin/ are views on the GdamModel (from the component directory).

- cli/ contains the implementation of the command-line client.

- gdam123/ contains the implementation of `gdam123`, which is a more-powerful `mpg123` clone.

### The Architecture

Here is the topmost view of how it all fits together.

- i/o contention management implemented on top of glib `source' notion.

- OO-architecture in C done via glib.

- general data message passing framework.

- setting arguments between the client and server using the `GdamArg' class.

#### The Objects in the Architecture

There are three main classes, under which we've developed largely parallel class hierarchies:

GdasSource

  the server-side object which actually renders PCM data.

GdamModel

  the client-side object which represents the current state of the server-side object, but which contains no user-interface.

GdamView

  (and its primary class, `GdamSkin`) are gtk+/glade classes to render the object to the user, and the to allow the user to alter the object.

##### The GtkObject and GdamArg system

Gtk+ 1.2 provides a fairly general object system which we have augmented in a number of GDAM specific ways.

We use: GtkObject and GtkObjectClass as our fundamental types. We define a number of abstract object types from GtkObject: GdasSource, GdamModel, GdamView, GdamServerObject.

GdamArg was originally conceived as an efficient argument system which featured callback hooks to trap when arguments were changed.

Later, "functions" were added to accomodate complicate client requests conveniently.

Also the .xml files which define the look-and-feel of GDAM's principal GUI use the argument system extensively in order to minimize the number of special purpose commands.

##### The Server.

The GdamServer encapsulates a listening socket. It contains a GdamAuthenticator which is used to grant privileges to an accepted connection, a GdamConnection.

The GdamConnections send and receive messages whose first 32-bits are the length of the packet (including the length field itself). The next 32-bits is the packet type, as enumerated in gdam-protocol.h.

The client always sends `request' packets; the server always sends exactly one `response' (which may indicate success or failure). The server may also send events to the client (the client must `subscribe' to the events...)

The elements which process sound are called `sources'; they derive from the GdasSource class.

Here is a rough type hierarchy:

- GdasSource - the base source

  - GdasFilter - all sources which filter from a single source

    - GdasResample - a resampling filter.

    - GdasGain - a revolumizing filter.

    - GdasEcho - an FIR/IIR filter.

  - GdasMix - a mixer.

    - GdasModulator - a modulator.

  - GdasCache - cached buffer/looped buffer.

  - GdasWavetable - a wavetable.

  - GdasSequencer - a sequencer.

- GdamCacheBuffer - raw sound data

Historical note: the change from GdamSource to GdasSource was around the year 2000. Occasionally one may run into a old-fashioned GdamSource reference (note that all GdamSource-derived classes were renamed, that's why the change was so massive.) This change was done because there were many server and model classes of the same name.

###### Server Commands

We will itemize these commands based on their name in the GdamMessageType enum, but with the GDAM_MESSAGE_ prefix removed.

TODO: finish this!!!

##### The Client.

###### Client Design

The client is divided into UI-independant section, the Components, and several UI-specific libraries/programs.

The components wrap the source_ids allocated by the servers to make convenient common manipulations, and to retain higher-level structure about the source (eg beat information, or the names of buffers instead of just their identifiers).

###### The Argument Architecture.

Arguments are typed, named values that are registered with the class instance. They provide an easy way to channel parameters "across the pipe" from the client to the server in a fairly general way.

###### Input Devices

We use these terms when talking about input devices:

device

  a physical or virtual input device

event

  the physical change of a device state

trap

  a particular type of event

hook

  a function which is attached to a trap, that is invoked

All client-side input devices will derive from GdamInputDevice. Currently the hierarchy is:

- GdamInputDevice - for any device

  - GdamInputDeviceFile - for devices which use a file descriptor

    - GdamMidiDevice - for devices which speak midi

    - GdamPs2Keyboard - auxillary ps/2 keyboard

    - GdamRangeFinder - a pasco range finder

Every device emits GdamInputEvents when an input action occurs, ie a button is pressed or a know is turned. InputEvents also have a type-hierarchy; it looks like:

- GdamInputEvent

  - GdamInputEventRange - floating point w/ min/max

    - GdamMidiParameter - example...

  - GdamInputEventInt - discretely valued events

You may create new event types by registering them with gdam_input_event_type_get_unique. They must have ways to convert to strings, convert to/from name/value pairs, and a way to strip the event of random information:

          struct _GdamInputEventTypeInfo
          {
    	const char           *event_type_name;
    	char               *(*stringify)     (GdamInputEvent *input_event);
    	unsigned            (*hash)          (GdamInputEvent *input_event);
    	gboolean            (*equal)         (GdamInputEvent *input_event1,
    					      GdamInputEvent *input_event2);
    	GHashTable         *(*to_keyvalues)  (GdamInputEvent *input_event);
    	GdamInputEvent     *(*from_keyvalues)(int             type,
    					      GHashTable     *table);
    	GdamInputEvent     *(*canonicalize)  (GdamInputEvent *input_event);
    	void                (*destroy)       (GdamInputEvent *input_event);
          };

###### Writing Server Sources (GdasSource-derived classes)

###### Fixed-Point

###### Writing a GdasSource

This is how you write a server-side plugin.

Writing a source is almost as easy as using a source, except that using a source tends to be rather forgiving, when writing a source you generally have to give that forgiveness.

Of course, using a source may not be a trivial matter, unless you are fluent in the gtk ways. Try Havoc Pennington's GGAD book.

Here are the "member functions" you must write:

    	int *_read(GdasSource*, GdamSample* buffer, int num_read)

A function to read a certain number of samples from a subsource. It returns the number of samples read.

            gboolean *_is_ready_to_read(GdasSource*);

Whether the source has data that can be read.

    	void *_miss_data(GdasSource*, int num_samples_read);

If a source was unavailable but data was needed, this function will be called to indicate the number of samples missed.

You will also want to register GdamArg get/set functions: that is, arguments. This is how to client can configure and initialize the source. We'll get to it in a moment.

Here are the rules these function must obey to be polite sources:

- if a source is ready_to_read, a subsequent read call must return at least 1 sample.

- if a source returns less than was requested it should not be possible to read more from the source (i.e. ready_to_read should return FALSE)

Also note it is often easier to derive from a similar source.

In particular sources which acquire their sources from another are usually much easier to implement as derivers of GdasFilter.

To get started run: `build/skeleton YourNewSource GdamBaseClass`

For example: `build/skeleton MyNeatFilter GdasFilter` Or `build/skeleton MyNeatSynthesize GdasSource`

Then I recommend cutting and pasting the member functions from elsewhere (GdasGain is pretty simple).

Then try it out in the cli:

(For a filter)

`source mp3 GdamMp3 filename "some_mp3.mp3" source filter MyNeatFilter filtered $mp3 my_filters_param 40 add $filter`

(For a synthesizer) `source synth MyNeatSynthesize param1 454 add $synth`

Debug away!

###### Adding to MiniNetwork

It is relatively easy to make a mininetwork node. They are simpler than sources because:

- they are one-to-one; the always input and output the same amount of data, and they never block.

- they using doubles instead of fixed-point.

TODO: write this!

###### Writing Client Models (GdamModel-derived classes)

WRITE ME.

###### Writing Skin Classes (GdamSkin-derived classes)

WRITE ME.