<!doctype book PUBLIC "-//OASIS//DTD DocBook V3.1//EN">

<book>

<!-- Title information -->

<bookinfo>
  <title>GDAM Developer Documentation</title>
  <author><FirstName>Dave</FirstName> <Surname>Benson</Surname></author>
</bookinfo>

<chapter><title>Introduction</title>

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

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

<itemizedlist>
        <listitem><para>
	<filename>common/</filename> contains various libraries which are 
	general enough to use in the client and the server.

	<itemizedlist>
		<listitem><para>
		gdam-protocol.h defines the constants of the
		client-server protocol.
		</para></listitem>

		<listitem><para>
		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.
		</para></listitem>

		<listitem><para>
		gdambuffer.h contains a simple FIFO buffer,
		used all over.
		</para></listitem>

		<listitem><para>
		gdammathfunction.h is a little less important:
		it is a c-style arithmetic expression parser.
		</para></listitem>

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

		<listitem><para>
		gdammodule.h takes care of loading plugin libraries
		and any libraries they depend on.
		</para></listitem>

		<listitem><para>
		gdamsample.h defines a sample-type and a fixed-point
		math type, GdamFixed.
		</para></listitem>

		<listitem><para>
		gdamsampleconverter.h contains code to convert
		between any two sample types.
		</para></listitem>

		<listitem><para>
		gdamsearchpath.h searches a colon-separated path
		for a certain file.
		</para></listitem>

		<listitem><para>
		gdamwaitpid.h registering functions to get
		called when a child process exits.
		</para></listitem>
	</itemizedlist>
	</para>
	</listitem>

	<listitem>
	<para>
	server/ contains all the rest of the code for
	the server and its plugins.
	</para>
	</listitem>

	<listitem>
	<para>
	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.
	</para>
	</listitem>

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

	<listitem>
	<para>
	skin/ are views on the GdamModel (from the component directory).
	</para>
	</listitem>

	<listitem>
	<para>
	cli/ contains the implementation of the command-line client.
	</para>
	</listitem>

	<listitem>
	<para>
	gdam123/ contains the implementation of <command>gdam123</command>,
	which is a more-powerful <command>mpg123</command> clone.
	</para>
	</listitem>
</itemizedlist>


<sect1><title>The Architecture</title>
<para>
Here is the topmost view of how it all fits together.
</para><para>
<itemizedlist>
	<listitem><para>i/o contention management implemented on top of
	  glib `source' notion.</para></listitem>
	<listitem><para>OO-architecture in C done via glib.</para></listitem>
	<listitem><para>general data message passing
	  framework.</para></listitem>
	<listitem><para>setting arguments between the client and
	  server using the `GdamArg' class.</para></listitem>
</itemizedlist>

<sect1><title>The Objects in the Architecture</title>
<para>
There are three main classes, under which we've developed largely
parallel class hierarchies:
<glosslist>
        <glossentry>
	<glossterm>GdasSource</glossterm>
	<glossdef><para>
	the server-side object which actually
	renders PCM data.
	</para></glossdef>
        </glossentry>

        <glossentry>
	<glossterm>GdamModel</glossterm>
	<glossdef><para>
	the client-side object which represents
	the current state of the server-side object, but
	which contains no user-interface.
	</para></glossdef>
        </glossentry>

        <glossentry>
	<glossterm>GdamView</glossterm>
	<glossdef><para>
	(and its primary class, <classname>GdamSkin</classname>)
	are gtk+/glade classes to render the object to the user,
	and the to allow the user to alter the object.
	</para></glossdef>
        </glossentry>
</glosslist>
</para>

<sect1><title>The GtkObject and GdamArg system</title>
<para>
  Gtk+ 1.2 provides a fairly general object system which we
  have augmented in a number of GDAM specific ways.
</para>
<para>
  We use: GtkObject and GtkObjectClass as our fundamental types.
  We define a number of abstract object types from GtkObject:
  GdasSource, GdamModel, GdamView, GdamServerObject.
</para>
<para>
  GdamArg was originally conceived as an efficient argument system
  which featured callback hooks to trap when arguments were changed.
</para>
<para>
  Later, "functions" were added to accomodate complicate client requests
  conveniently.
</para>
<para>
  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.
</para>
</sect1>

<chapter><title>The Server.</title>
<para>
  The GdamServer encapsulates a listening socket.
  It contains a GdamAuthenticator which is used to grant
  privileges to an accepted connection, a GdamConnection.

</para><para>
  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.

</para><para>
  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...)

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

</para><para>
  Here is a rough type hierarchy:

<itemizedlist>
 <listitem><para>GdasSource - the base source</para>
 <itemizedlist>
  <listitem><para>GdasFilter - all sources which filter from a single source</para>
  <itemizedlist>
   <listitem><para>GdasResample - a resampling filter.</para></listitem>
   <listitem><para>GdasGain - a revolumizing filter.</para></listitem>
   <listitem><para>GdasEcho - an FIR/IIR filter.</para></listitem>
  </itemizedlist>
  </listitem>

  <listitem><para>GdasMix - a mixer.</para>
  <itemizedlist>
   <listitem><para>GdasModulator - a modulator.</para></listitem>
  </itemizedlist>
  </listitem>
  <listitem><para>GdasCache - cached buffer/looped buffer.</para></listitem>
  <listitem><para>GdasWavetable - a wavetable.</para></listitem>
  <listitem><para>GdasSequencer - a sequencer.</para></listitem>
 </itemizedlist>
 <listitem><para>GdamCacheBuffer - raw sound data</para></listitem>
</itemizedlist>

<para>
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.
</para>

<sect1><title>Server Commands</title>
 <para>
 We will itemize these commands based on their
 name in the GdamMessageType enum, but with the GDAM_MESSAGE_ prefix removed.
 </para>
 <para>
 TODO: finish this!!!
 </para>
</sect1>

</chapter>

<chapter><title>The Client.</title>
<sect1><title>Client Design</title>
<para>
  The client is divided into UI-independant section, the Components,
  and several UI-specific libraries/programs.
<para>
  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).
</para>


<sect1><title>The Argument Architecture.</title>
<para>
  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.
</para>

<sect1><title>Input Devices</title>
<para>
  We use these terms when talking about input devices:
</para>
<para>

<glosslist>

<glossentry><glossterm>device</glossterm>
<glossdef><para>
a physical or virtual input device
</para></glossdef>
</glossentry>

<glossentry><glossterm>event</glossterm>
<glossdef><para>
the physical change of a device state
</para></glossdef>
</glossentry>

<glossentry><glossterm>trap</glossterm>
<glossdef><para>
a particular type of event
</para></glossdef>
</glossentry>

<glossentry><glossterm>hook</glossterm>
<glossdef><para>
a function which is attached to a trap, that is invoked 
</para></glossdef>

</glosslist>


<para>
  All client-side input devices will derive from
  GdamInputDevice.  Currently the hierarchy is:
</para>
<para>
<itemizedlist>
 <listitem><para>GdamInputDevice - for any device</para>
 <itemizedlist>
  <listitem><para>GdamInputDeviceFile - for devices which use a file descriptor</para>
  <itemizedlist>
   <listitem><para>GdamMidiDevice - for devices which speak midi</para></listitem>
   <listitem><para>GdamPs2Keyboard - auxillary ps/2 keyboard</para></listitem>
   <listitem><para>GdamRangeFinder - a pasco range finder</para></listitem>
  </itemizedlist>
  </listitem>
 </itemizedlist>
 </listitem>
</itemizedlist>
</para>

<para>
  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:
</para>

<para>
<itemizedlist>
 <listitem><para>GdamInputEvent</para>
 <itemizedlist>
  <listitem><para>GdamInputEventRange - floating point w/ min/max</para>
  <itemizedlist>
   <listitem><para>GdamMidiParameter - example...</para>
  </itemizedlist>
  </listitem>
  <listitem><para>GdamInputEventInt - discretely valued events</para></listitem>
 </itemizedlist>
 </listitem>
</itemizedlist>
</para>

<para>
  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:
</para><para>
<screen>
      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);
      };
</screen>
</para><para>




<sect1><title>Writing Server Sources (GdasSource-derived classes)</title>
<sect2><title>Fixed-Point</title>
<para>
</para>
<sect1><title>Writing a GdasSource</title>
<para>
This is how you write a server-side plugin.
</para>
<para>
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.
</para>
<para>
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.
</para>
<para>
Here are the "member functions" you must write:
</para>
<para>
<screen>
	int *_read(GdasSource*, GdamSample* buffer, int num_read)
</screen>

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

</para>
<para>
<screen>
        gboolean *_is_ready_to_read(GdasSource*);
</screen>

	      Whether the source has data that can be read.
</para>
<para>
<screen>
	void *_miss_data(GdasSource*, int num_samples_read);
</screen>
	      If a source was unavailable but data was needed,
	      this function will be called to indicate the
	      number of samples missed.
</para>
<para>
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.
</para>
<para>
Here are the rules these function must obey
to be polite sources:
<itemizedlist>
	<listitem><para> if a source is ready_to_read, a subsequent read
	  call must return at least 1 sample.</para></listitem>
	<listitem><para> 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)</para></listitem>
</itemizedlist>
</para>
<para>
Also note it is often easier to derive from a similar
source.
</para><para>
In particular sources which acquire their sources from
another are usually much easier to implement as
derivers of GdasFilter.
</para><para>
To get started run:
<userinput>
	build/skeleton YourNewSource GdamBaseClass
</userinput>

For example:
<userinput>
	build/skeleton MyNeatFilter GdasFilter
</userinput>
Or
<userinput>
	build/skeleton MyNeatSynthesize GdasSource
</userinput>
</para>
<para>
Then I recommend cutting and pasting the member functions
from elsewhere (GdasGain is pretty simple).
</para>

<para>
Then try it out in the cli:
</para>
<para>
(For a filter)
</para>
<para>
<userinput>
	source mp3 GdamMp3 filename "some_mp3.mp3"
	source filter MyNeatFilter filtered $mp3 my_filters_param 40
	add $filter
</userinput>
</para>

<para>
(For a synthesizer)
<userinput>
	source synth MyNeatSynthesize param1 454
	add $synth
</userinput>
</para><para>
Debug away!
</para>


<sect1><title>Adding to MiniNetwork</title>
<para>
It is relatively easy to make a mininetwork node.
They are simpler than sources because:
<itemizedlist>
<listitem><para>they are one-to-one; the always input and output the same
amount of data, and they never block.</para></listitem>
<listitem><para>they using doubles instead of fixed-point.</para></listitem>
</itemizedlist>
</para><para>
TODO: write this!
</para>

<sect1><title>Writing Client Models (GdamModel-derived classes)</title>
<para>
WRITE ME.
</para>

<sect1><title>Writing Skin Classes (GdamSkin-derived classes)</title>
<para>
WRITE ME.
</para>
	
</chapter>
</book>
