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


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

<toc>

<chapter id="gdamchapter"><title>GDAM</title>

<sect1 id="gdamintro"><title>Introduction</title>
<para>
<application>GDAM</application> is <quote>Geoff and Dave's Audio Mixer</quote>
<para>
<application>GDAM</application> is a digital dj mixing software package. 
It aims to be a powerful, professional-quality music mixing and remixing 
system, suitable for live performance. It was conceived on some beautiful 
summer morning (in 1998), and developed with drive and enthusiasm that seemed 
completely unnatural. Nearly two years later, we have achieved many of our 
goals; yet, development remains as hectic. Here is a list of features: 

<itemizedlist>
	<listitem><para>
                client-server architecture based around glib 
	</para></listitem>
	<listitem><para>
                streaming and mixing of any number of mp3 files 
	</para></listitem>
	<listitem><para>
                dynamic filter insertion and removal 
	</para></listitem>
	<listitem><para>
                multiple sound device support 
	</para></listitem>
	<listitem><para>
                plugin support 
	</para></listitem>
	<listitem><para>
                cacheing / playing loops 
	</para></listitem>
	<listitem><para>
                contiguous queueing - plays albums without gaps between songs, regardless of output buffer size 
	</para></listitem>
	<listitem><para>
                dj turntable-style interface 
	</para></listitem>
	<listitem><para>
                assisted beat matching 
	</para></listitem>
	<listitem><para>
                waveform viewer / beat calculator 
	</para></listitem>
	<listitem><para>
                sequencer 
	</para></listitem>
	<listitem><para>
                record from any point in the stream, to disk or another process 
	</para></listitem>
	<listitem><para>
                gtk gui's, with simple skin support 
	</para></listitem>
	<listitem><para>
                flexible command-line interface 
	</para></listitem>
	<listitem><para>
                <command>gdam123</command> - an <command>mpg123</command> clone that talks to a gdam server 
	</para></listitem>
	<listitem><para>
                hardware input support (midi and other) 
	</para></listitem>
	<listitem><para>
                support to use <acronym>LADSPA</acronym> plugins 
	</para></listitem>
	<listitem><para>
                support to create <acronym>LADSPA</acronym> plugins graphically 
	</para></listitem>
	<listitem><para>
                online help
	</para></listitem>
</itemizedlist>


</para> 

<sect1 id="gdamprogs"><title>The Programs in GDAM</title>

<para>
GDAM is an audio server, a client library, and a few powerful,
extensible clients.
</para>

<glosslist>
       <glossentry>
       <glossterm>
       gdam-server
       </glossterm>
       <glossdef>
       <para>The server does all of the audio processing and sound device
       		handling.  It can accept connections from multiple clients,
		optionally from remote computers.</para>
       </glossdef>
       </glossentry>

       <glossentry>
       <glossterm>
       gdam-launcher
       </glossterm>
       <glossdef>
       <para>The graphical frontend, <command>gdam-launcher</command> 
	       creates gui components from xml description files.</para>
       </glossdef>
       </glossentry>

       <glossentry>
       <glossterm>
       gdamcli
       </glossterm>
       <glossdef>
       <para>This simple command line interface to the gdam server allows
       		inspection and manipulation of sound sources attached to a 
		given sound device.  It is useful for scripting and 
		debugging.  </para>
       </glossdef>
       </glossentry>

       <glossentry>
       <glossterm>
       gdam123
       </glossterm>
       <glossdef>
       <para>This is a command line mp3 playlist frontend.  It emulates 
	       <command>mpg123</command>'s <option>-z</option> and 
	       <option>^C</option> handling, and offers a healthy
		set of vi key bindings for interactive control and playlist
		manipulation.</para>
       </glossdef>
       </glossentry>
</glosslist>

<para>
In general you just run one <command>gdam-server</command>, 
but you may connect many clients (<command>gdam-launcher</command>, 
<command>gdamcli</command>, and <command>gdam123</command>) 
to it.  The server opens multiple sound devices, moves streams between devices, 
and does all sound processing.   Clients connect to a server on 
<option>localhost:6003</option> by default, but the 
<option>--gdam-server</option> option allows clients to
connect to a different host and port.  Clients connect to the
default sound device unless the <option>--device</option> argument is given.  
Clients which use can use more than one device 
(ie <command>gdam-launcher</command>) accept several 
<option>--device</option> args.

<sect1 id="importantfiles"><title>Important Files</title>

<para>
These files are used to customize the behavior and appearance of gdam.
</para>

<para>

<glosslist>
  <glossentry>
    <glossterm>
    server.config
    </glossterm>
  <glossdef>
    <para>
      server config file, contains information about 
      available sound devices.  Usually in 
      <filename>/usr/local/lib/gdam/</filename>
      or similar default location.  Can be specified
      with <option>--config <replaceable>configfile</replaceable></option>
      when starting the server.
    </para>
  </glossdef>
  </glossentry>

  <glossentry>
    <glossterm>
      default.rc
    </glossterm>
    <glossdef>
      <para>
	gtk rc file used to control colors and fonts in
	gui components.  Usually in <filename>/etc/gdam/skin/</filename>
	or <filename>~/.gdam</filename>.  Can be specified with the
	<option>--rcfile</option> flag when starting 
	<command>gdam-launcher</command>.
      </para>
    </glossdef>
  </glossentry>

  <glossentry>
    <glossterm>
      launcher.xml
    </glossterm>
    <glossdef>
      <para>
	when <command>gdam-launcher</command> starts, it creates an initial skin
	from this xml file.  The skin defined by 
	<filename>launcher.xml</filename> is a panel of buttons 
	to launch skins of other types and built from other xml 
	files.  This file is usually in <filename>/etc/gdam/skin</filename>, 
	and the other xml files referenced are there or in subdirectories.  
	If an xml file is given as an argument to 
	<command>gdam-launcher</command>, the 
	initial skin will be built from that file.
      </para>
    </glossdef>
  </glossentry>

  <glossentry>
    <glossterm>
      song.database
    </glossterm>
    <glossdef>
      <para>
	xml database of song information: filenames, tempo
	and phase data, loop descriptions and other
	user-specified info.  This information is used by client
	programs (<command>gdam-launcher</command>, 
	<command>gdam123</command>).  Can be specified to 
	most clients with the <option>--database</option> flag.
      </para>
    </glossdef>
  </glossentry>

  <glossentry>
    <glossterm>
      gdam123rc
    </glossterm>
    <glossdef>
      <para>
	file of ex-style <command>gdam123</command> commands, parsed 
	on startup.  Usually in <filename>~/.gdam/</filename>  Used to 
	set initial volume, mp3 file buffer size, etc.
      </para>
    </glossdef>
  </glossentry>

  <glossentry>
    <glossterm>
      input.devices
    </glossterm>
    <glossdef>
    <para>
    describes hardware input devices (midi controllers, etc)
    Usually in <filename>~/.gdam/</filename>.  This file is
    currently only used by client programs.
    </para>
    </glossdef>
  </glossentry>
</glosslist>
</chapter>




<chapter id="installing"><title>Installing GDAM</title>

<sect1 id="dependencies"><title>Dependencies</title>

<para>
    GDAM requires that a number of programs and libraries are 
    installed on your computer.  The exact dependencies vary
    between distributions and platforms.  Pre-compiled 
    <filename>.rpm</filename> and <filename>.deb</filename> 
    packages require fewer libraries than compiling from source.

<para>
    In  order  to  decode  mp3  files you  need  a  fairly  fast
    processor-  maybe a  486 can  decode  a single  mp3 but  for
    serious mixing you'll definitely  need something faster (any
    pentium  should do  nicely). The  faster the  processor, the
    more simultaneous mp3 streams you'll be able to decode.
<para>
    For any  of it,  <filename>gtk+ 1.2.5</filename>  or higher 
    is required.  Even the server  requires  it.  
     Skins are created 
    at run time from libglade xml description files.  You'll need 
    the following:
<itemizedlist>
	<listitem><para><filename>libglade
	</filename></para></listitem>
	<listitem><para><filename>libxml
	</filename></para></listitem>
</itemizedlist>
<para>
    Recent Redhat <filename>libxml</filename> rpm's have required the
    following gnome libs:
<itemizedlist>
	<listitem><para><filename>gnome-core
	</filename></para></listitem>
	<listitem><para><filename>gnome-libs
	</filename></para></listitem>
	<listitem><para><filename>gnome-audio
	</filename></para></listitem>
</itemizedlist>
</para>


<para>
    <command>Mpg123</command> is used for decoding mp3 data, so you must have it installed.

<para>
    If compiling from cvs source, the <filename>sgmltools-lite</filename> 
    package is required to generate documentation.  This is available from
    <ulink url="http://sgmltools-lite.sourceforge.net/">
    the sgmltools-lite project</ulink>.  In addition, people compiling 
    from source (cvs or tarball) will need the header files from the following 
    packages: 
<itemizedlist>
	<listitem><para><filename>libglade-devel
	</filename></para></listitem>
	<listitem><para><filename>libxml-devel
	</filename></para></listitem>
</itemizedlist>
<para>
    Recent Redhat <filename>libxml-devel</filename> rpm's have required the
    following gnome libs:
<itemizedlist>
	<listitem><para><filename>gnome-core-devel 
	</filename></para></listitem>
	<listitem><para><filename>gnome-libs-devel
	</filename></para></listitem>
	<listitem><para><filename>gnome-audio-extra
	</filename></para></listitem>
</itemizedlist>
</para>
    
<para>
    Recent RPM packages are available on our web page, 
    <ulink url="http://www.ffem.org/gdam/">gdam.org</ulink>.
</para>



<sect1 id="quickinstall"><title>Quick Installation Guide</title>

<sect2 id="precompiled"><title>Installing From Precompiled Packages</title>
<para>
if you have an <filename>.rpm</filename> package, run the following as root:
<screen>
% rpm --install <replaceable>packagefile.rpm</replaceable>
</screen>

<para>
if you have a <filename>.deb</filename> package, run the following as root:
<screen>
% dpkg --install <replaceable>packagefile.deb</replaceable>
</screen>
</para>


<sect2 id="compiled"><title>Installing From Compiled Source</title>
<para>
If you have compiled from source (see 'Compiling from Source'), you 
can install by doing the following as root:
<screen>
% make install
% ldconfig 
</screen>
<para>
If you use <option>--prefix</option> to the <command>./configure</command>
script, you may not need to be root: but you may need to set
the <envar>LD_LIBRARY_PATH</envar> to include <filename>lib</filename> and
<envar>PATH</envar> environment
to include <filename>bin</filename>.
</para>
<para>
If you don't even want to <userinput>make install</userinput> you can
just add <filename>gdam/lib</filename> to your <envar>LD_LIBRARY_PATH</envar>.
Then run the client and server separately.
</para>

<sect2 id="running"><title>Running Gdam</title>
<para>
If you have fully installed gdam onto your system,
the server should automatically be launched when
you run <command>gdam-launcher</command>, so 
it is a one step process.
</para>
<para>
Often it is easier to run the client and server separately:
<itemizedlist>
	<listitem><para>if something is going wrong,
	</para></listitem>
	<listitem><para>you want to specific command line flags to the server,
	</para></listitem>
	<listitem><para>you want to connect multiple clients to the server,
	</para></listitem>
	<listitem><para>or you want the server to keep running after the client
	has detached.
	</para></listitem>
</itemizedlist>
In that case it is recommended to use two separate terminal
windows to run the commands.
In the first window:

<screen>% gdam-server --config /etc/gdam/server.config</screen>

Sometimes the <option>--debug</option> flag will print out useful
information, especially if things aren't going well.
</para><para>
In the second window,
<screen>% gdam-launcher</screen>
It should pop up, using the first window's server.
</para>



<sect1 id="compiling"><title>Compiling GDAM from Source</title>
<para>
    We recommend that each time you compile GDAM, you use a fresh
    copy of the source code.  The reason for this is that many 
    configuration options are stored in files such as 
    <filename>config.cache</filename> and it is therefore
    possible that the makefiles don't match your current 
    system configuration.  (This can happen if you install a
    package after running configure). Check out a new copy from cvs,
    or re-unzip the tarball or (faster) delete the config.cache.
<para>
    We use  <acronym>GNU</acronym> automake for  building our programs.  This 
    means that  once  you have  the  tarball,  the following  standard
    procedure should apply:
</para>
<screen>
	% ./configure
	% make
	% make install
</screen>

<sect2 id="cvscompiling"><title>Compiling GDAM from CVS Source</title>
<para>
    If you have the cvs version, run <filename>./autogen.sh</filename> 
    instead of <filename>./configure</filename>.  This will install gdam in    
    <filename>/usr/local/lib/gdam/</filename>, 
    <filename>/usr/local/bin/gdam*</filename>.    If you specify the option
    <option>--prefix=/usr</option> to <filename>./configure</filename> it will
    install in <filename>/usr</filename> instead.
</para>
</sect2>

<sect2 id="freebsdcompiling"><title>Compiling on FreeBSD</title>
<para>
    The version of gcc most commonly distributed with FreeBSD, 2.95.2 19991024,
    will not compile GDAM.  To work around this, upgrade to 
    <command>egcc</command>.  If you have not already done so, install ports by
    running <command>/stand/sysinstall</command>.  Then move to 
    <filename>/ports/lang/gcc-devel/</filename> and 
    <command>make install</command>.
</para>
<para>
    When configuring GDAM, you need to specify the proper path to the
    <command>gtk-config</command> command, and to use <command>egcc</command>.
    Your command will probably be:
</para>
<screen>
	% GTK_CONFIG=/usr/X11R6/bin/gtk12-config CC=egcc ./configure
</screen>
<para>
    Now, use gmake to build:
</para>
<screen>
	% gmake; gmake install
</screen>
</sect2>

<sect2 id="compilinglibraries"><title>Libraries</title>
<para>
    In order for your system to know were the libs are installed, 
    you might need to do the following:
</para>
<screen>
	% ldconfig
</screen>

<para>
    If you still get errors about missing libraries running gdam:
<orderedlist>
 <listitem>
  <para>
        Make sure that <filename>/etc/ld.so.conf</filename> contains
          the relevant <filename>/usr/*/lib</filename> directory.
  </para>
 </listitem>

 <listitem>
  <para>
        Alternately,  to use GDAM without installing it, set the  
	<envar>LD_LIBRARY_PATH</envar> environment variable to  
	include the directory where the libraries reside.  You
        should   modify   your   shell  startup   script   or
        <filename>/etc/profile</filename> if you are going to 
	run gdam frequently.
  </para>
 </listitem>
</orderedlist>
</sect2>



<sect1 id="serverconfigfile"><title>Configuring the Server Config File</title>

<para>
    The default server config file should work for most people
    using OSS or ALSA with OSS emulation.  Nevertheless, many
    will want to edit the file to tune device options, select
    default devices, or enable native ALSA support. The file
    is  fairly  self-explanatory, it will most likely have been 
    installed in <filename>/usr/local/lib/gdam/server.config</filename>. 
    It contains a list of device types (OSS,ALSA), a list of specific 
    devices, and some global server options.  An abbreviated
    example follows:

<screen> 

#    GDAM Server Config File
#
# This is the default server config file that should
# be shipped with distributions.
#
# Please delete this comment when you edit it!
#


#
# define the types of output devices available.
#   
DeviceType      "plugin"        "oss"
#DeviceType      "plugin"        "alsa"


#
#  If you have OSS or ALSA + OSS compatability, use these.
#  Some devices need the 'fork' option to keep from hanging.
#
#Device   "oss"   "/dev/dsp"   "numfragments=3:logfragsize=12:fork"
Device    "oss"   "/dev/dsp"
Device    "oss"   "/dev/dsp1"
Device    "oss"   "/dev/dsp2"


#
# ALSA Devices [if you have sys/asoundlib.h installed.]
#
#  appending '#n' to a device name causes gdam to use subdevice n, 
#  if possible.   otherwise, the first available subchannel is used.  
#  You probably don't want entries for both specific subdevices and 
#  the general device, it may conflict.
#
#Device  "alsa"  "/dev/snd/pcmC0D0"   "numfragments=3:logfragsize=12"
#Device  "alsa"  "/dev/snd/pcmC0D0#0" "numfragments=3:logfragsize=12"
#Device  "alsa"  "/dev/snd/pcmC0D0#1" "numfragments=3:logfragsize=12"
#Device  "alsa"  "/dev/snd/pcmC0D1"   "numfragments=3:logfragsize=12"


# Don't allow mpg123 to swallow all the cpu from us...
ExternalPriorityDrop   "7"

#
# If server is run as root, change to this user and group for safety.
#
IfRoot User     "nobody"
IfRoot Group    "audio"

#
# Files to store log info and pid
#
LogFile         "/var/log/gdam.log"
PidFile         "/var/run/gdam.pid"

#
# Whether to run in daemon mode  
# (runs in background with different permissions)
#
Daemon          "no"

#
# If you specify `no' then anyone can connect.  Else, only 
# localhost connections are accepted.
#
BindLocalhost   "yes"


Debug           "no"

#DispatchLog     "dispatch.log"
#Microphone "/dev/dsp1"
#TcpSocket	"6005"		"punk"

</screen> 

<glosslist>
 <glossentry>
  <glossterm>ExternalPriorityDrop</glossterm>
  <glossdef><para>
   This causes the GdasExternal class to renice the child process
   the specified number of steps.
  </para></glossdef>
 </glossentry>
</glosslist>
    
<para>
    There are a few device options you may wish to try out:
<para>
  <glosslist>
    <glossentry>
    <glossterm>bits=[8|16]</glossterm>
    <glossdef><para>How many bits per sample for the sound device.</para>
    </glossdef>
    </glossentry>
  
    <glossentry>
    <glossterm>mono</glossterm>
    <glossdef><para>Monophonic aka one-channel sound.</para>
    </glossdef>
    </glossentry>
  
    <glossentry>
    <glossterm>stereo</glossterm>
    <glossdef><para>Stereo aka two-channel sound.</para>
    </glossdef>
    </glossentry>
    <glossentry>
    <glossterm>rate</glossterm>
    <glossdef><para>Sampling rate of the device in samples per second.</para>
    </glossdef>
    </glossentry>
    <glossentry>
    <glossterm>fork</glossterm>
    <glossdef><para>Fork the device into its own process.  This is necessary 
    if your sound device doesn't support "polling".  If clents hang, timers
    stuck at 0:00, this might be the answer.  </para>
    </glossdef>
    </glossentry>
    <glossentry>
    <glossterm>wrong_endian</glossterm>
    <glossdef><para>Swap byte order of sound for this device.  If you hear 
    static, try this option.  </para>
    </glossdef>
    </glossentry>
    <glossentry>
    <glossterm>logfragsize</glossterm>
    <glossdef><para>Log base 2 of the size of a single audio buffer
    fragment.  Larger sizes increase latency but protect against dropout.
    </para>
    </glossdef>
    </glossentry>
    <glossentry>
    <glossterm>numfragments</glossterm>
    <glossdef><para>Number of audio buffer fragments to circle through.
    Larger numbers increase latency but protect against dropout.
    </para>
    </glossdef>
    </glossentry>
    <glossentry>
    <glossterm>no_ioctls</glossterm>
    <glossdef><para>Don't attempt to send the device the normal ioctls,
    which may fail on some devices spuriously, but is mostly useful
    if the "device" is really just a fifo.</para>
    </glossdef>
    </glossentry>
  </glosslist>
</para> 
  


<sect1 id="permissions"><title>Setting Up Permissions</title>
<para>
Gdam can be run in many modes, the best one for you
depends on how you want to use it.
<itemizedlist>
  <listitem>
    <para>
      if you always use gdam through <command>gdam-launcher</command>
      then it should be completely secure to run it
      in <option>secure</option> mode, letting it run the server
      for you.
    </para>
    <para>
      Serious users will find the convenience of having multiple
      client connections very valuable;  we really intend this
      more as a "demo" mode, for playing with few security worries.
    </para>
  </listitem>
  <listitem>
    <para>
      If you run gdam on a network where you don't trust
      the computers directly connected to you (for example,
      if you are on the internet and don't have a firewall),
      you can add <userinput>Bind Localhost</userinput>to the config 
      file to prevent other computers from connecting.
    </para>
  </listitem>
  <listitem>
    <para>
      if you more-or-less trust the computers in your network
      you can probably run gdam without <userinput>Bind Localhost</userinput>
      fairly safely.   Make certain that <command>gdam-server</command>
      ddrops priviledges from root.  (use <command>ps</command>)
    </para>
  </listitem>
</itemizedlist>
If gdam works for you "out of the box" there is probably
little reason to configure it to behave more securely,
although we recommend always running <command>gdam-server</command>
behind a firewall.  (We have designed it to be secure in
many sensible ways - but there is a lot of auditting
to do.  Currently, lack of strong authentication is the biggest problem.)
</para>
<para>
If you wish to run gdam realtime you will have to run it as root.
This is also a situation you must consider if you run
<command>gdam-server</command> from an initscript.
</para>
<para>
If you add <userinput>Username</userinput> and <userinput>Group</userinput> 
tags to the configuration file and run it as root, 
<command>gdam-server</command> drops to that identity 
<emphasis>before</emphasis> opening the audio devices.  This 
means that the user or group must have
unix permission to open sound devices.
Either 
<orderedlist>
 <listitem>
  <para>
   the audio device must be owned and writable
   by the specified Username.
  </para>
 </listitem>

 <listitem>
  <para>
   the audio device must be owned and writable
   by the specified Group.
  </para>
 </listitem>
</orderedlist>
<para>
If you don't know what to do, we recommend
making your audio devices readable and writable
by a group "audio" (which you may have to create
using the <command>addgroup</command> or <command>groupadd</command>
or by editting <filename>/etc/group</filename> directly.
This boils down to:
<screen>
    % addgroup audio          
    	    # may complain if the group exists.
    % chgrp audio /dev/dsp*   
    % chmod 660 /dev/dsp*
	    # alsa users should add /dev/snd/pcm*
</screen>


<sect1 id="festival"><title>Setting Up Festival</title>
<para>gdam can be used with the freely-available
<ulink url="http://www.cstr.ed.ac.uk/projects/festival.html">
festival speech generation package</ulink>, which was
made at the University of Edinburgh.
</para>
<para>
   First install festival and a voice or two from either packages
   or source code from the link above.
</para>
<para>
   Then copy the <command>text2wave</command> script
   from the example directory onto your path.
   Make sure it is marked as executable, using 
   <command>chmod +x</command>.  For my debian system,
   the following suffices:
</para>
<screen>
% zcat /usr/share/doc/festival/examples/text2wave.gz $gt; /usr/local/bin/text2wave
% chmod +x /usr/local/bin/text2wave
</screen>
<para>
  You'll also need to install one or more of the voices.  As of writing,
  package names for festival voices include:
<orderedlist>
 <listitem> <para>
   festvox-kallpc16k
  </para> </listitem>
 <listitem> <para>
   festvox-kallpc8k
  </para> </listitem>
 <listitem> <para>
   festvox-kdlpc16k
  </para> </listitem>
 <listitem> <para>
   festvox-rablpc16k
  </para> </listitem>
</orderedlist>
</para>
<para>
   When you run <command>gdam-launcher</command> just specify
   <option>--define festival</option>.
</para>


<sect1 id="nosoundcard"><title>Computers Without Soundcards</title>
<para>
    While most users will have a soundcard present, it is possible
    to run both the server and the clients on computers without
    sound cards.
<para>
    Wherever the server runs, it requires a device to draw
    data from it.  ALSA provides a dummy driver which mimics
    /dev/dsp, but produces no sound.  User running in this mode
    will most likely add a recording output so that audio
    data can be saved to disk or sent to icecast server.
</para>


<sect1 id="twosoundcards"><title>Computers With Multiple Soundcards</title>
<sect2 id="twosoundcardlinux"><title>Installing Multiple Soundcards On A Linux System</title>
<para>
     With the standard kernel code, this can be tricky.  You'll
     probably compile sound support as modules, and insert the
     cards one at a time with any necessary parameters.
<para>
     With the commercial OSS drivers from
     <ulink url="http://www.opensound.com/">4front technology</ulink>,
     I had no problem getting several cards to work at once.  Their
     configuration utility autodetected and installed all three
     of my sound cards.  Many cheap and a few professional cards are
     supported.  A basic license costs $20, certain cards require
     more expensive options.
<para>
     <ulink url="http://alsa-project.org/">The ALSA project</ulink> has
     developed a free set of drivers meant as a powerful alternative to the 
     standard kernel drivers.  Many cards are supported, and the system is
     designed to support multiple cards without conflict.  
</para>

<sect2 id="twosoundcardgdam"><title>Supporting Multiple Soundcards In GDAM</title>
<para>
     Make sure all of your available devices are listed in the server.config
     file.  Any client can be run with the <userinput>--device</userinput>
     flag to change the default sound device.  The 
     <command>gdam-launcher</command> program accepts multiple 
     <userinput>--device</userinput> flags, and can switch a
     source from one device to another.  If no <userinput>--device</userinput>
     flags are given, most clients will use the value of the 
     <envar>GDAM_DEVICE</envar> environment variable.  
     <command>gdam-launcher</command> will use both <envar>GDAM_DEVICE</envar>
     and <envar>GDAM_DEVICE2</envar> if not given other soundcards
     on the command line.
</para>

<sect2 id="fourchannelsoundcard"><title>Supporting Four-Channel or "Surround" Soundcards In GDAM</title>
<para>
     An alternative to multiple sound cards is a four-channel sound
     card.  I get great performance from my Trident 4DWave sound card,
     which features seperate front and rear stereo outputs.  SoundBlaster
     Live cards also offer four channels of audio output.  A benefit
     of cardlike this over two seperate soundcards is that the timing of 
     two channels, and the devices which feed them, is identical... they 
     will not drift or be read from at different times.  
<para>
     Four-Channel soundcards offer seperate front and rear stereo outputs.
     This is usually accomplished by having multiple "subdevices" for
     writing audio data to the soundcard.  Hardware mixing controls
     determine whether each subdevice sends sound to the front outputs,
     the rear outputs, or both.  The mixer controls are reset each time a 
     subdevice is opened, so i have to set the mixer controls each time i 
     restart the gdam server.
<para>
     In order to use front and rear outputs of a card such as the 4DWave
     or the Soundblaster Live, you need drivers which support the card's 
     internal mixing controls.  The ALSA drivers, version 0.5 and higher,
     support these controls and the following instructions apply to alsa
     drivers.  I am unaware whether the kernel OSS drivers or the commercial
     OSS drivers export these mixer controls... if so, a similar process
     should allow output.
<para>
     After installing ALSA drivers, add entries to the server.config file
     which describe specific subdevices on your four-channel soundcard.
</para>
<screen>
# ALSA Devices [if you have sys/asoundlib.h installed.]
#
#  appending '#n' to a device name causes gdam to use subdevice n, 
#  if possible.   otherwise, the first available subchannel is used.  
#  You probably don't want entries for both specific subdevices and 
#  the general device, it may conflict.
#
#Device  "alsa"  "/dev/snd/pcmC0D0"   "numfragments=3:logfragsize=12"
Device  "alsa"  "/dev/snd/pcmC0D0#0" "numfragments=3:logfragsize=12"
Device  "alsa"  "/dev/snd/pcmC0D0#1" "numfragments=3:logfragsize=12"
</screen>
<para>
     Once the GDAM server knows about subdevices, GDAM clients need to be told
     to use them.  Run <command>gdam-launcher</command> with multiple 
     <userinput>--device</userinput> flags, or set the 
     <envar>GDAM_DEVICE</envar> and <envar>GDAM_DEVICE2</envar> 
     environment variables.
</para>
<screen>
% GDAM_DEVICE=/dev/snd/pcmC0D0#0 GDAM_DEVICE2=/dev/snd/pcmC0D0#1 gdam-launcher
</screen>
<para>
     The mixing controls on your soundcard need to be set each time the
     subdevice is opened (i.e. when <command>gdam-server</command> is run.)
     I use <command>alsactl</command> and <command>gamix</command> to change 
     these settings.  Each time an ALSA driver opens a subdevice, new controls
     are made available to set that device's volume to the front and rear 
     outputs.  In <command>alsactl</command>, these controls are named "PCM 
     Front Volume" and "PCM Reverb Volume" for each subdevice.  
     <command>gamix</command> presents front/rear/pan controls for each 
     subdevice under headings such as "PCM Playback" and "PCM Playback 1".  
     Whichever method you use,
     set subdevice 0 to full volume on the front channel / zero volume
     on the rear, and set subdevice 1 to zero volume on the front channel / 
     full volume on the rear.

<inlinemediaobject>
<imageobject>
<imagedata fileref="@image_path@/gamixfourout.jpeg" format="jpg">
</imageobject>
<textobject>
<phrase> Screenshot of gamix </phrase> 
</textobject>
</inlinemediaobject>

<para>
     Once you are pleased with the soundcard settings, use 
     <command>alsactl -f ~/fourout.ctl store</command> to save soundcard 
     settings.  After restarting <command>gdam-server</command> and 
     <command>gdam-launcher</command>, you can restore the setting with
     <command>alsactl -f ~/fourout.ctl restore</command>
</para>


<chapter id="gdamserver">
<title><command>gdam-server</command>: Audio Processing Server</title>

<sect1 id="runningserver"><title>Running <command>gdam-server</command></title>
<para>
<command>gdam-server</command> is responsible for all of GDAM's audio
processing.  For any GDAM client program to work, it must have a
gdam server available.  Properly installed distributions will automatically
start the <command>gdam-server</command> when a client is run.  When the
server is automatically started, it does not accept connections from 
other clients.   For this reason, it is usually desireable to run the
<command>gdam-server</command> as a seperate process.  By default all
clients attach to <userinput>localhost:6060</userinput>, but that can
be changed by giving them the <option>--gdam-server</option> flag.
The client and server need not be on the same computer, but the server 
needs to have access to the audio files and devices. 
</para>

<para>
<cmdsynopsis>
	<command>gdam-server</command>
	<arg>--port <replaceable>port_number</replaceable></arg>
	<arg>--config <replaceable>config_file</replaceable></arg>
	<arg>--realtime</arg>
</cmdsynopsis>
</para>


<sect1 id="recordingserver"><title>Recording Sound from the <command>gdam-server</command></title>

<para>
  Server support is in place for recording sound output by
  the gdam server to a given device.  The sound can be written
  directly to disk, or sent to another process (i.e. an mp3 
  encoding process on some machine).   
</para>


<sect2 id="recordingservercli"><title>Starting and Stopping Recording with <command>gdamcli</command></title>
<para>
  The long way to do this 
  is to use the <command>gdamcli</command> program to start and stop the 
  recording.  You do this:

<screen>
	% ./gdamcli [--device /dev/dsp?]

	          #  Print out the mixer's information.  The `parent'
		  #     is always the recording filter.
	gdam-cli&gt; ls -a $mixer
	source 1.
	  arg 0: mixed =&gt; []
	  arg 1: parent =&gt; 2
	  arg 2: terminates =&gt; 0
	  arg 3: paused =&gt; 0
	  arg 4: mode =&gt; eternal
	  arg 5: parent_device =&gt; 0
	  arg 6: position =&gt; 182272L
	  arg 7: subsources =&gt; []

		# The number after `call' should be the parent number.
		
	gdam-cli&gt; call 2 add_output connect your_host:your_port_number

	  arg 0: output_id =&gt; 1
	
		# So now it'll be connecting/recording on your host.
</screen>
<para>
  And to stop it:
<screen>
	gdam-cli&gt; call 2 remove_output output_id 1

		# will stop it (use the output_id it gives you)

		# You can record to multiple computers this way.

		# Finally, instead of `connect' you can say `file'
		# which will make the server write the raw sound data
		# to a local file.
</screen>
  So if you set up something to record at that port, you're ready to go.
</para>



<sect2 id="recordserverscript"><title>Starting and Stopping Recording with <command>record-mp3</command> and <command>record-stop</command></title>

<para>
  The <filename>cli/record-mp3</filename> script attempts to automate this,
  as its first argument it takes the host and port to tells the gdam 
  server to connect to host:port as specified as the argument to the script.
  The <filename>cli/record-stop</filename> scripts removes the output
  which record-mp3 adds.
</para>



<sect2 id="recordservergui"><title>Recording from within the GUI</title>
<para>
  The gdam-launcher pops up single turntables with an entry at the 
  bottom for a recording location.  Format is 'host:port'.  Pressing
  the <GuiButton>Record</GuiButton> button will cause the entire mix being 
  sent to the first sound device (the value of the first 
  <userinput>--device</userinput> flag, or the <envar>GDAM_DEVICE</envar> 
  environment variable, or <filename>/dev/dsp</filename> by default) 
  to be mirrored to the given host.  While it is recording, the button 
  will remain depressed.  Press it again to stop the recording. 
</para>




<sect2 id="recordtarget"><title>Setting Up Something to Record</title>
<para>
  We have used <command>gogo</command> to encode mp3 data, and with some 
  success, but it seemed a bit unstable.  <command>lame</command> isn't 
  quite as fast, but it hasn't crashed yet.  Try the following
  line in your <filename>inetd.conf</filename>:

<screen>
	6060 stream tcp nowait nobody.audio /usr/sbin/tcpd /usr/local/sbin/run-lame
</screen>

  And the following 3-line shell script as 
  <filename>/usr/local/sbin/run-lame</filename>:

<screen>
	#! /bin/sh
	DATE=`date +%d-%b-%Y-%H:%M:%S`
	/usr/local/bin/lame -r -x -m s - /mnt/18/lame/l-$DATE.mp3 &gt; /tmp/lame.log.$DATE 2&gt;&1
</screen>

  Alternately, use <filename>/usr/local/sbin/run-gogo</filename>:

<screen>
	#! /bin/sh
	DATE=`date +%d-%b-%Y-%H:%M:%S`
	/usr/bin/gogo stdin /mnt/18/gogo/$DATE.mp3 -offset 0 &gt; /tmp/gogo.log.$DATE 2&gt;&1
</screen>

  And you have to accept that this is probably a security
  hole if you are outside a firewall :)  See the appendix for
  more security info.

</para>



<sect2 id="icecast"><title>Icecast / Shoutcast</title>

<para>
  If you want to talk to a Shoutcast server, here
  is an untested alternate script that can be run from inet.d
  by Scott Manley (aka Szyzyg) <email>spm@star.arm.ac.uk</email>.

<screen>
	#! /bin/sh
	DATE=`date +%d-%b-%Y-%H:%M:%S`
	mkfifo /tmp/mp3pipe
	echo "password" &gt; /tmp/shoutheaders
	echo "icy-name: Test" &gt;&gt; /tmp/shoutheaders
	echo "icy-genre: Mixed" &gt;&gt; /tmp/shoutheaders
	echo "" &gt;&gt; /tmp/shoutheaders
	/usr/bin/lame - - &gt; /tmp/mp3pipe &
	cat /tmp/shoutheaders /tmp/mp3pipe | nc localhost 8000 
</screen>
  Should suffice to have it bounce off to an mp3 encoding server...
  As a note, <command>icecast</command> has broken support for piping in 
  raw audio data which could be used live.  Alternately, I hacked the 
  <command>shout</command> utility
  to support streaming a file which was growing in size.  This was
  sufficient to manage a live broadcast. 
<para>
  Further <command>icecast</command> utilities to come...
</para>
  
</chapter>





<chapter id="gdamlauncher"><title><command>gdam-launcher</command>: GDAM's GUI</title>

<sect1 id="runninglauncher"><title>Running <command>gdam-launcher</command></title>

<para>
    The <command>gdam-launcher</command> is the primary gui for gdam.
    When it is run, it brings up a panel of buttons,
    each of which will launcher a virtual "component".
    In order to nicely color the widgets, <command>gdam-launcher</command>
    looks for a gtk rcfile <filename>default.rc</filename> in, among other 
    places, <filename>~/.gdam</filename>; a system default is provided.
</para>

<cmdsynopsis>
	<command>gdam-launcher</command>
	<arg>--gdam-server <replaceable>host:port</replaceable></arg>
	<arg>--device <replaceable>device</replaceable></arg>
	<arg>--rcfile <replaceable>rcfile</replaceable></arg>
	<arg>--rcpath <replaceable>rcpath</replaceable></arg>
	<arg>--database <replaceable>songdb</replaceable></arg>
	<arg>--define <replaceable>variable</replaceable></arg>
	<arg>--mp3buffer <replaceable>mp3_file_buffer_size_in_seconds</replaceable></arg>
</cmdsynopsis>


<sect1 id="launchercomponents"><title>Available Components</title>

<glosslist>
       <glossentry>
       <glossterm>
       Turntable
       </glossterm>
       <glossdef>
       <para>
	an mp3-player with resampling and synching capabilities,
	wrapped in a filter stack.
       </para>
       </glossdef>
       </glossentry>

       <glossentry>
       <glossterm>
       Wheels
       </glossterm>
       <glossdef>
       <para>
	two turntables and a crossfader	
       </para>
       </glossdef>
       </glossentry>

       <glossentry>
       <glossterm>
       Wavetable
       </glossterm>
       <glossdef>
       <para>
        a looping resampling buffer, for "wavetable" 
	synthesis or looping sound cut from a song
       </para>
       </glossdef>
       </glossentry>

       <glossentry>
       <glossterm>
       Buffer Editor
       </glossterm>
       <glossdef>
       <para>
	a sample editor
       </para>
       </glossdef>
       </glossentry>


       <glossentry>
       <glossterm>
       Sequencer
       </glossterm>
       <glossdef>
       <para>
        sequence many short samples, at different
	gain levels and resample rates
       </para>
       </glossdef>
       </glossentry>

       <glossentry>
       <glossterm>
       Beat Calculator
       </glossterm>
       <glossdef>
       <para>
        a tool to help determine the beat information
        which describes a song.
       </para>
       </glossdef>
       </glossentry>
</glosslist>



<sect1 id="hotkeys"><title>Skin Hotkeys</title>

<para>
<firstterm>Hotkeys</firstterm> refer to key bindings which 
are attached to one window, and respond to the normal keyboard
when that window has focus (unless a text-entry widget is activated.)
Before version 0.933 hotkey bindings were defined in the xml
skin files, and could only be changed by editing the skin xml file.
As of version 0.933, hotkey bindings are part of the input binding
file format (also xml)  and are stored outside the skin files.  
The skin file <filename>wheel-mp3.xml</filename> references 
a file of bindings, <filename>wheelshotkeys.xml</filename>.  To 
extend or change the hotkey bindings, a user can copy the binding
file into <filename>~/.gdam/skins/</filename> and edit it.  Their
copy of the file will be found whenever a skin file references it.
<para>
The binding file format is described elsewhere.  All of our hotkeys
are defined using the gdam_packer_trap_key_press handler.  Example Handler:
<screen>
        gdam_packer_trap_key_press:e:tt1:gdam_skin_arg_int:play_or_synch:-1
</screen>
Translation: The 'e' key applies to named child 'tt1' (the turntable).
When 'e' is pressed the argument 'play_or_synch' is set to a value of -1.
(If the turntable is playing, the value of -1 stops it.  If the turntable 
is stopped, -1 seeks to the first beat).
<para>
Example Handler:
<screen>
	gdam_packer_trap_key_press:q:tt1:gdam_skin_arg_double:seek_by_bars:-2
</screen>
Translation: The 'q' keys sets the turntable's 'seek_by_bars' arg to -2.
(This seeks the position backwards by two bars.)
</para>




<sect1 id="turntable"><title>The Turntable</title>

<sect2 id="turntableoverview"><title>Turntable Overview</title>

<para>One of the basic gdam gui components us the turntable.  The turntable 
embodies the ability to start, stop, seek, and change the speed of a sound.  A 
turntable contains a sound-producing source (ie an mp3 player) which it 
controls.  If available, a turntable makes use of beat information about the 
sound it is controlling.  In addition, the turntable offers drag-n-drop 
functionality to coordinate between songs.

<para>

The default turntable, containing an mp3 player, looks something like this:
<para>

<inlinemediaobject>
<imageobject>
<imagedata fileref="@image_path@/turntable.jpeg" format="jpg">
</imageobject>
<textobject>
<phrase> Screenshot of the Turntable </phrase> 
</textobject>
</inlinemediaobject>

<inlinemediaobject>
<imageobject>
<imagedata fileref="@image_path@/turntable.jpg" format="jpg">
</imageobject>
<textobject>
<phrase> Screenshot of the Turntable </phrase> 
</textobject>
</inlinemediaobject>

<inlinemediaobject>
<imageobject>
<imagedata fileref="@image_path@/bluetoneturntable.jpg" format="jpg">
</imageobject>
<textobject>
<phrase> Screenshot of the Turntable </phrase> 
</textobject>
</inlinemediaobject>

<para>
    To use the turntable, a song must first be loaded.  Drag and drop a 
    filename from the song selector onto the filename entry box.[*]  
    Alternatively, use the <guibutton>=&gt;</guibutton> (import) button to load the currently
    selected song.  When the song is dropped, the turntable loads 
    information about it from the song database.  If known, the song's 
    position will automatically be set to the location of the first beat.  
    
</para>
<para>
    	[*] Initially the song database will be empty, making the
            song selector empty.  Please see Section V, Song Database.
</para>
<para>
    The middle two buttons on the top row stop and start the song playing.  
    The <guibutton>&gt;</guibutton>-style buttons nudge the song a small amount.  They are useful 
    for aligning songs which are slightly out of sync.  The <guibutton>&gt;|</guibutton> style
    buttons seek the song an even bar, based on bpm information
    from the song database.  These buttons are useful to move around
    within the song while staying on beat.  The <guibutton>anchor</guibutton> 
    button will
    set the turntable to be the lead source.  This means that if it
    is playing, other songs can sync to it.  To sync a running turntable 
    to the lead source, press its play button a second time.

</para><para>
    Turntables can resample their songs to match any tempo.  To cause
    one turntable to resample its song to match another song's tempo,
    drag and drop the desired tempo from one turntable's bpm label to the
    other turntable's resampling area.  Double clicking a turntable's 
    bpm label will cause it to match to the lead (anchored) component. 
    By checking the <guibutton>1/2</guibutton> button in the resampling area, the turntable 
    treats its song as if it was half the normal speed.  This allows one 
    to sync an 80 bpm song to a 160 bpm one, without extensive resampling.  
</para>

<para>
In addition to the iconated buttons, there are a number of other displays and controls:
<para>
<inlinemediaobject>
<imageobject>
<imagedata fileref="@image_path@/annottt.jpeg" format="jpg">
</imageobject>
<textobject>
<phrase> Annotated Screenshot of the Turntable </phrase> 
</textobject>
</inlinemediaobject>
<para>

<sect2 id="turntablebuttons"><title>Buttons</title>

<glosslist>

       <glossentry>
       <glossterm>
<inlinemediaobject>
<imageobject>
<imagedata fileref="@image_path@/play.jpeg" format="jpg">
</imageobject>
<textobject>
<phrase> Play Button </phrase> 
</textobject>
</inlinemediaobject>
       </glossterm>
       <glossdef>
       <para>
Without Modifier - Starts the song playing.  If the song is already playing, 
		synchronize this song with the lead song.  Both songs 
		must have beat information in the song database for this
	        to work.
       <para>
With <keycap>CONTROL</keycap> pressed - Starts the song in sync with a different, playing song.  Both
	      	songs must have beat information in the song database for this
	      	to work.
	</para>
       </glossdef>
       </glossentry>


       <glossentry>
       <glossterm>
<inlinemediaobject>
<imageobject>
<imagedata fileref="@image_path@/stop.jpeg" format="jpg">
</imageobject>
<textobject>
<phrase> Stop Button </phrase> 
</textobject>
</inlinemediaobject>
       </glossterm>
       <glossdef>
       <para>
Without Modifier - Stops the song.  If the song is not playing, seeks to the
		first beat.
	</para>
       </glossdef>
       </glossentry>


       <glossentry>
       <glossterm>
<inlinemediaobject>
<imageobject>
<imagedata fileref="@image_path@/nudgeb.jpeg" format="jpg">
</imageobject>
<textobject>
<phrase> Nudge Back Button </phrase> 
</textobject>
</inlinemediaobject>
       </glossterm>
       <glossdef>
       <para>
Without Modifier - Nudges the song back a tiny amount (1/200 sec)  Useful
		for aligning songs which aren't quite playing in time.
	</para>
       </glossdef>
       </glossentry>


       <glossentry>
       <glossterm>
<inlinemediaobject>
<imageobject>
<imagedata fileref="@image_path@/nudgebb.jpeg" format="jpg">
</imageobject>
<textobject>
<phrase> Nudge Back Back Button </phrase> 
</textobject>
</inlinemediaobject>
       </glossterm>
       <glossdef>
       <para>
Without Modifier - Nudges the song back a small amount (1/20 sec)
	</para>
       </glossdef>
       </glossentry>

       <glossentry>
       <glossterm>
<inlinemediaobject>
<imageobject>
<imagedata fileref="@image_path@/nudgef.jpeg"  format="jpg">
</imageobject>
<textobject>
<phrase> Nudge Forward Button </phrase> 
</textobject>
</inlinemediaobject>
       </glossterm>
       <glossdef>
       <para>
Without Modifier - Nudges the song forward a tiny amount (1/200 sec)
	</para>
       </glossdef>
       </glossentry>

       <glossentry>
       <glossterm>
<inlinemediaobject>
<imageobject>
<imagedata fileref="@image_path@/nudgeff.jpeg"  format="jpg">
</imageobject>
<textobject>
<phrase> Nudge Forward Forward Button </phrase> 
</textobject>
</inlinemediaobject>
       </glossterm>
       <glossdef>
       <para>
Without Modifier - Nudges the song forward a small amount (1/20 sec)
	</para>
       </glossdef>
       </glossentry>

       <glossentry>
       <glossterm>
<inlinemediaobject>
<imageobject>
<imagedata fileref="@image_path@/nudgemb.jpeg" format="jpg">
</imageobject>
<textobject>
<phrase> Nudge Measure Back Button </phrase> 
</textobject>
</inlinemediaobject>
       </glossterm>
       <glossdef>
       <para>
Without Modifier - Nudges the song back exactly one measure, if the bpm 
             is known.  Useful for looping part of a song, or seeking
	     through a song while keeping the beat.
       <para>
With <keycap>CONTROL</keycap> pressed - Nudges the song back exactly one beat.
	</para>
       </glossdef>
       </glossentry>


       <glossentry>
       <glossterm>
<inlinemediaobject>
<imageobject>
<imagedata fileref="@image_path@/nudgembb.jpeg" format="jpg">
</imageobject>
<textobject>
<phrase> Nudge Measure Back Back Button </phrase> 
</textobject>
</inlinemediaobject>
       </glossterm>
       <glossdef>
       <para>
Without Modifier - Nudges the song back exactly two measures.
       <para>
With <keycap>CONTROL</keycap> pressed - Nudges the song back exactly two beats.
	</para>
       </glossdef>
       </glossentry>


       <glossentry>
       <glossterm>
<inlinemediaobject>
<imageobject>
<imagedata fileref="@image_path@/nudgemf.jpeg" format="jpg">
</imageobject>
<textobject>
<phrase> Nudge Measure Forward Button </phrase> 
</textobject>
</inlinemediaobject>
       </glossterm>
       <glossdef>
       <para>
Without Modifier - Nudges the song forward exactly one measure.
       <para>
With <keycap>CONTROL</keycap> pressed - Nudges the song forward exactly one beat.
	</para>
       </glossdef>
       </glossentry>


       <glossentry>
       <glossterm>
<inlinemediaobject>
<imageobject>
<imagedata fileref="@image_path@/nudgemff.jpeg" format="jpg">
</imageobject>
<textobject>
<phrase> Nudge Measure Forward Forward Button </phrase> 
</textobject>
</inlinemediaobject>
       </glossterm>
       <glossdef>
       <para>
Without Modifier - Nudges the song forward exactly two measures.
       <para>
With <keycap>CONTROL</keycap> pressed - Nudges the song forward exactly two beats.
	</para>
       </glossdef>
       </glossentry>

</glosslist>


<sect2 id="turntableothercontrols"><title>Other Controls</title>

<glosslist>

       <glossentry>
       <glossterm>
Position Range
       </glossterm>
       <glossdef>
       <para>
Display the current position within the song.  Drag to change.
	</para>
       </glossdef>
       </glossentry>

       <glossentry>
       <glossterm>
Time Label
       </glossterm>
       <glossdef>
       <para>
Displays the current time in minutes and seconds.
	</para>
       </glossdef>
       </glossentry>

       <glossentry>
       <glossterm>
Beat Number
       </glossterm>
       <glossdef>
       <para>
If the beat information of the underlying source is known, then
this displays the number of beats away from the first, corresponding
to the current position.
	</para>
       </glossdef>
       </glossentry>

       <glossentry>
       <glossterm>
Sync Preview
       </glossterm>
       <glossdef>
       <para>
If the turntable is capable of synching the playing song (i.e., it
	has beat information for that song and for the lead song)
	then this shows how far out of sync it is.  The value is a fraction
	of a beat.  A negative value indicates that the song should be nudged
	back by that amount to be in sync.
	</para>
       </glossdef>
       </glossentry>

       <glossentry>
       <glossterm>
Resample Range
       </glossterm>
       <glossdef>
       <para>
Controls the resample rate (ie playback speed) of the song.  Drag to change.
	</para>
       </glossdef>
       </glossentry>


       <glossentry>
       <glossterm>
Anchor Button
       </glossterm>
       <glossdef>
       <para>
When this button is pressed, the turntable is set as the lead component.  
This means that other components' songs will attempt to sync to the
turntable's.  If the beat information of the turntable's song is unknown,
it won't make a very useful leader.
	</para>
       </glossdef>
       </glossentry>

       <glossentry>
       <glossterm>
Resample Rate
       </glossterm>
       <glossdef>
       <para>
This display indicates what speed the song is playing at.
	</para>
       </glossdef>
       </glossentry>


       <glossentry>
       <glossterm>
BPM Display
       </glossterm>
       <glossdef>
       <para>
This display indicates the bpm of the resampled song.  This value can be
	dragged onto another turntable's BPM display (using the middle or
	right button) causing the other turntable to resample itself such 
	that its output bpm matches ours.
	</para>
       </glossdef>
       </glossentry>

       <glossentry>
       <glossterm>
Jump Paddle
       </glossterm>
       <glossdef>
       <para>
This widget allows measured jumps of 1 to 16 beats.  Drag the paddle until
	the label indicates the number of beats you'd like to jump.  Release
	and the jump occurs.  Clicking in the trough and at the ends also
	allow easy jumping.
	</para>
       </glossdef>
       </glossentry>


       <glossentry>
       <glossterm>
Tempo Lock
       </glossterm>
       <glossdef>
       <para>
If this control is active, then the turntable will automatically adjust its
resampling rate when a new song is loaded.  The rate will be adjusted so that
the new output tempo is the same as the old.  Of course, the beat information
of both songs must be known for this to happen.
	</para>
       </glossdef>
       </glossentry>

       <glossentry>
       <glossterm>
Tempo Scale Arrows
       </glossterm>
       <glossdef>
       <para>
These arrows are adjacent to the tempo display, in the style of a spinbutton.
The up arrow doubles the effective tempo of the song, and the down button 
halves it.  When the effective tempo of a 180 bpm song is halved, the first 
beat remains at the same location but seeking and synchronization treat it as 
if it were 90 bpm.
	</para>
       </glossdef>
       </glossentry>

       <glossentry>
       <glossterm>
Cycle Beat Info 
       </glossterm>
       <glossdef>
       <para>
Some songs have a complicated beat info description, because different
parts of the song have different phases and tempos.  At any point, the
turntable uses a single firstbeat and tempo value.  When the position 
of the song is changed, the turntable will automatically cycle the beat
info to the range which describes the current position.  At times it is 
useful to select which beatinfo range to follow at any point in the
song.  A left click on this control cycles to the next beatinfo range.  
In some skins, a right click on this control will lock the beatinfo,
to prevent the turntable automatically selecting the range it thinks is
appropriate.
	</para>
       </glossdef>
       </glossentry>

</glosslist>


<sect1 id="wheels"><title>The Wheels</title>

<para>
One handy collection of components is the wheels gui.  This emulates a set
of dj turntables, packing two turntable components into a window with a 
crossfader to control the relative volumes of the two channels, a widget to
select the output device of a channel, and builders to dynamically add filters
to a channel.

The default wheels skin appears thus: <para>
<inlinemediaobject>
<imageobject>
<imagedata fileref="@image_path@/wheels-annotated.jpg" format="jpg">
</imageobject>
<textobject>
<phrase> Annotated Wheels Screenshot </phrase> 
</textobject>
</inlinemediaobject>
</para>




<sect1 id="builder"><title>The Builder</title>

<para> 
The builder provides dynamic insertion and removal of filters.  Many sound-producing components come packed into builders, so that a wide range of filters can be applied. 

<para> 

A builder with one gain and one bounce filter looks like this:
<para> 
<inlinemediaobject>
<imageobject>
<imagedata fileref="@image_path@/builder-annotated.jpg" format="jpg">
</imageobject>
<textobject>
<phrase> Annotated Builder Screenshot </phrase> 
</textobject>
</inlinemediaobject>


<glosslist>

       <glossentry>
       <glossterm>
Filter Launch Buttons
       </glossterm>
       <glossdef>
       <para>
These buttons add filters of different types to the filter stack.
	</para>
       </glossdef>
       </glossentry>

       <glossentry>
       <glossterm>
Filter Control Panel
       </glossterm>
       <glossdef>
       <para>
The <guibutton>X</guibutton> button removes the filter from the stack.
       <para>
The <guibutton>O</guibutton> button disables and reenables the filter.
       <para>
The <guibutton>&lt;</guibutton> button moves the filter up the stack one position.
       <para>
The <guibutton>&gt;</guibutton> button moves the filter down the stack one position.
	</para>
       </glossdef>
       </glossentry>

       <glossentry>
       <glossterm>
Help
       </glossterm>
       <glossdef>
       <para>
Launch online help.
	</para>
       </glossdef>
       </glossentry>

</glosslist>







<sect1 id="builderfilters"><title>Using the Various Filters</title>
<sect2 id="eqfilter"><title>Using the Equalization Filter</title>
<para>
This filter is an extremely simple lo/hi/band/notch filter.
</para>
<para>
You can change its mode with the pulldown menu.
The modes are:
</para>

<glosslist>

       <glossentry>
       <glossterm>
       notch
       </glossterm>
       <glossdef>
       <para>...
	cut out a particular frequency.
	</para>
       </glossdef>
       </glossentry>

       <glossentry>
       <glossterm>
       bandpass
       </glossterm>
       <glossdef>
       <para>
	cut out everything but a particular frequency.
       </para>
       </glossdef>

       <glossentry>
       <glossterm>
       lopass
       </glossterm>
       <glossdef>
       <para>
	cut out above a particular frequency.
       </para>
       </glossdef>
       </glossentry>


       <glossentry>
       <glossterm>
	hipass
       </glossterm>
       <glossdef>
       <para>
       cut out below a particular frequency.
       </para>
       </glossdef>
       </glossentry>

       <glossentry>
       <glossterm>
       hishelf
       </glossterm>
       <glossdef>
       <para>
       </para>
       </glossdef>
       </glossentry>

       <glossentry>
       <glossterm>
       loshelf
       </glossterm>
       <glossdef>
       <para>...</para>
       </glossdef>
       </glossentry>

       <glossentry>
       <glossterm>
       peaking eq
       </glossterm>
       <glossdef>
       <para>...</para>
       </glossdef>
       </glossentry>
</glosslist>

<para>
The frequency is in hertz, and its meaning depends on the selected mode.
</para><para>
The bandwidth is supposed to be the cutoff rate (meaning how sharply
the filter's output over frequency drop to 0).  It doesn't work
very well in some modes.
</para>
</sect2>
<sect2><title>Using the Fader</title>
<para>
The fader allows you to adjust an envelope which is applied over a
certain number of beats.  <emphasis>Enveloping</emphasis> means to change
the volume gradually over time.
</para>
</sect2>

<sect2 id="bouncefilter"><title>Using the Bounce Filter</title>
<para>
The bounce filter temporarily replaces the sound
stream with sound from a fraction of a beat earlier
in the song.  By applying this filter in time with
the music, it is possible to double or drop beats.
</para>
<para>
The bounce filter has one parameter, the amount of
delay.  This is displayed as a number of eighth beats; 
a value of four corresponds to half of a beat.
</para>
</sect2>

<sect2 id="spinfilter"><title>Using the Spin Filter</title>
<para>
The spin filter temporarily causes a section
of music to be looped.  While this loop is 
being played back, the underlying song 
continues to play at a normal speed, so that
it will stay synchronized.

</para><para>
The primary parameter is the amount of boffer.  This
is displayed as a number of whole beats.  If the
bpm of the song is not known, a tempo of 60 bpm
is assumed.  If a negative number is specified
as the beat factor, then the delay will be the
negative inverse of that number; for instance,
a value of -2 corresponds to a half beat period.

</para><para>
The spin filter can be locked into a spin mode.
In this situation, depressing the temporary
<guibutton>spin</guibutton> button will cause the 
looped buffer to be overwritten by incoming sound.
The spun sound will die if the underlying song stops.
</para>
</sect2>

<sect2 id="firfilter"><title>Using the Fir Filter</title>
<para>
The fir filter allows users to graphically place
echoes of different delays and volumes.  At small
delays, this will affect the tone of the sound.
The fir filter can also be used to place echoes
with delays equal to a fraction of a beat.

</para><para>
The largest component in the fir filter is the 
display area.  Grid units are marked off on the
display area for guidance.  The horizontal axis
represents time, and vertical bars are drawn 
every n samples.  The vertical axis represents 
volume.  Clicking with the left button will add
an echo.  An echo can be dragged with the left 
button, and removed with the right.  To the right
of the display area is a scrollbar which controls 
the zoom level in the time domain.

</para><para>
The <guilabel>grid unit</guilabel> adjustment controls the time 
represented by each vertical bar.  This number
is in samples, where 44100 samples equal one 
second.  The time between bars can also be set
as a number of beats.  When the <guilabel>beats</guilabel> 
scrollbar is set to non-zero value, the grid 
unit value is remembered, and this value is 
restored when the <guilabel>beat_factor</guilabel> is set to zero.

</para><para>
The <guibutton>normalize</guibutton> toggle button causes the total 
volume of all echoes to be held constant.  The
maximum value is given by the <guilabel>scale</guilabel> adjustment.
If the volume is not normalized, then the <guilabel>scale</guilabel>
value is applied to each echo's volume.
</para>
</sect2>

<sect2 id="flangefilter"><title>Using the Flange</title>
<para>
The flange filter applies a reverb
with a varying delay, resulting in
"swooshing" sounds.

</para><para>
The flange filter has a display area
similar the the fir filter's, into 
which echoes can be placed and
relocated.  However, note that 
multiple echoes will greatly increase
the instability of the filter.

</para><para>
The echoes are varied according to
a sine wave, triangle wave, or
buffer.  The frequency of the this
waveform can be adjusted with the <guilabel>hz</guilabel>
slider.  The lowest, center, and
greatest values can be set with the 
three horizontal sliders.

</para><para>
The overall amount of effect applied 
is controlled with the <guilabel>effect</guilabel> slider.
</sect2>


<sect2 id="mininetfilter"><title>Using the Mininetwork</title>
<para>
The mininetwork filter allows users to build simple filter
networks by graphically arranging filter icons.
</para><para>
When the mininetwork filter is launched, two icons are
present.  The green icon at the top represents the input,
and the red icon the output.  These two are connected such
that sound flows straight through the filter.

</para><para>
Select a filter type, e.g. <guimenuitem>delay</guimenuitem>, from the list.
Clicking on the display area will add a delay filter.
The icon can be dragged by its center to move it.
Drawing a line from the bottom of the green input icon
to the top of the delay filter will connect the two.
There is no restriction to how many connections can be
made from the output of any filter, so the input will
retain its connection to the output.  Once the output
of the delay filter is connected to the large read icon,
sound will also flow through the delay filter.

</para><para>
Clicking on any icon will bring up a panel displaying the
parameters of the filter.  For instance, clicking on the
delay filter allows control over the amount of delay.
For convenience, the scale of the delay can also be
changed.

</para><para>
Filters can be inserted between existing filters.  After
selecting the desired filter type (say, gain) click with
the middle button on a connection between two filters. A
gain filter is inserted and connected such that it controls
the volume of the sound flowing through that connection.

</para><para>
A filter and all its connections can be removed by clicking
on the filter with the right button.
</para><para>
The middle button will remove the filter, but restore as
many connections as possible.  A connection can be removed
by right clicking on it.
</para>

</sect2>
</sect1>





<sect1 id="buffereditor"><title>The Buffer Editor</title>


<sect2 id="loadingbuffer"><title>Loading a Buffer</title>
<para>
The <guibutton>Buffer Manager</guibutton> button opens the buffer manager.  
At first this will contain only the default waveforms (sin, square...) but 
wav files can be loaded from disk with the sample picker, and bits of mp3 
files can be cached using the cache component.  After selecting a waveform 
within the buffer manager, drag it onto buffer editor.  Alternately,
the <guibutton>=&gt;</guibutton> button loads the selected buffer without dragging.
</para>


<sect2 id="selectingbuffer"><title>Moving Around and Selecting</title>
<para>
A long horizontal sliders seeks within the waveform.  The zoom level 
is controlled by the vertical slider at the right edge of the display
area.  Buttons zoom to the entire audio sample or to the selected
region. The left and center mouse buttons can be used to select an area
of the waveform.  The <guibutton>select all</guibutton> button selects 
the entire waveform.

<sect2 id="buffereditoroperations"><title>Operating on the Selected Region</title>
<para>
Once a region of the waveform has been selected, it can be transformed.
The <guibutton>Cut</guibutton> button removes a section of waveform
to the buffer manager.  <guibutton>Copy</guibutton> leaves the
waveform untouched and copies the selection to the buffer manager.
<guibutton>Kill</guibutton> replaces a segment with silence.
<guibutton>Replace</guibutton> swaps the selected data with a waveform
from the buffer manager.  <guibutton>Insert Before</guibutton> and
<guibutton>Insert After</guibutton> paste a buffer next to the selection.
<guibutton>Reverse</guibutton> reverses the selected audio data.
</sect2>
</sect1>





<sect1 id="beatcalculator"><title>The Beat Calculator</title>

<para>To make full use of GDAM's beat information-aware features, you must determine the beat information which describes your favorite songs.  The primary tool to assist with this task is the beat calculator.  Given an estimation of the bpm and firstbeat location for a song, the beat calculator will graphically display predicted beats over a picture of the waveform.  These can be stretched and moved until (if possible) the bars correctly predict each beat.

<para>

The beat calculator looks like this:
<para>
<inlinemediaobject>
<imageobject>
<imagedata fileref="@image_path@/beatcalc-annotated.jpeg" format="jpg">
</imageobject>
<textobject>
<phrase> Annotated Beatcalc Screenshot </phrase> 
</textobject>
</inlinemediaobject>




<glosslist>

       <glossentry>
       <glossterm>
Waveform Display
       </glossterm>
       <glossdef>
       <para>
Here is displayed a picture of a section of the song, overlaid with bars where beats are predicted.  Songs can be dropped onto this area in order to load them.  Left-clicking near a beat line will relocate it to the position of the click by adjusting the bpm slightly.  Clicking while shift is depressed will relocate the nearest beat line by shifting the location of the first beat slightly.  Control-click will set the location of the first beat.  The second mouse button can be used to highlight a section of the song (not shown), which can then be replayed.  This aids you in identifying features within the sound.
       </para>
       </glossdef>
       </glossentry>

       <glossentry>
       <glossterm>
Zoom Level
       </glossterm>
       <glossdef>
       <para>
Used to zoom in on / out from the song.  Examining the song up close makes it possible to identify features by sight, and perfect the accuracy of the beat information.
       </para>
       </glossdef>
       </glossentry>


       <glossentry>
       <glossterm>
Load From Song Selector
       </glossterm>
       <glossdef>
       <para>
The circular button opens the song selector, and the arrow button imports the currently selected song from the song selector, and begins it loading. 
       </para>
       </glossdef>
       </glossentry>


       <glossentry>
       <glossterm>
Load From Disk
       </glossterm>
       <glossdef>
       <para>
Rather than loading from the song database, any song can be loaded from disk. 
       </para>
       </glossdef>
       </glossentry>

       <glossentry>
       <glossterm>
Play Selection
       </glossterm>
       <glossdef>
       <para>
The <guibutton>PLAY</guibutton> and <guibutton>STOP</guibutton> buttons can 
be used to hear a portion of sound.  If a portion of sound is selected, that 
portion will be played.  Otherwise, the song will be played from the current 
position.
       </para>
       </glossdef>
       </glossentry>

       <glossentry>
       <glossterm>
Estimate BPM By Tapping
       </glossterm>
       <glossdef>
       <para>
To get a good first estimate of the tempo of a song, click the 
<guibutton>tap</guibutton> button in time with the music.  The bpm value 
(calculated since the time of the first tap) is displayed, and you can start 
over by pressing the <guibutton>reset</guibutton> button.
       </para>
       </glossdef>
       </glossentry>

       <glossentry>
       <glossterm>
Update Database
       </glossterm>
       <glossdef>
       <para>
Once you are satisfied that the current beat info provides an accurate 
description of the song's rhythm, use the <guibutton>Update Database</guibutton>
button to write the information to the song database.  Don't forget to save 
the database (in the song selector)  before quitting, so that you will 
forevermore be able to have full control over this song.
       </para>
       </glossdef>
       </glossentry>

       <glossentry>
       <glossterm>
Current Beatinfo
       </glossterm>
       <glossdef>
       <para>
The <guilabel>bpm</guilabel> and <guilabel>first beat</guilabel> fields hold 
the current values being used to draw beatlines on the waveform.  These values 
can be set here, although fine adjustments will most likely be made with the 
mouse on the waveform display.
       </para>
       </glossdef>
       </glossentry>

       <glossentry>
       <glossterm>
Position
       </glossterm>
       <glossdef>
       <para>
This slider controls the position within the song which is displayed in the center of the waveform display.  When you are zoomed in very close on a song, you'll have to click in the trough and arrows to get fine enough position control.
       </para>
       </glossdef>
       </glossentry>

       <glossentry>
       <glossterm>
Help
       </glossterm>
       <glossdef>
       <para>
Like most components, the beat calculator has online help which can be launched by clicking on the button with the question mark.
       </para>
       </glossdef>
       </glossentry>

</glosslist>






<sect1 id="beatcalcexample"><title>Beat Calculator Example</title>

<para>To make full use of GDAM's beat information-aware features, you must determine the beat information which describes your favorite songs.  The primary tool to assist with this task is the beat calculator.  Given an estimation of the bpm and firstbeat location for a song, the beat calculator will graphically display predicted beats over a picture of the waveform.  These can be stretched and moved until (if possible) the bars correctly predict each beat.
<para>

This is a step-by-step journal of using the beat calculator to find 
firstbeat and bpm values which describe a song.<para>

<orderedlist>

<listitem>
<para>
Find a promising song, and drop it onto the beat calculator.  Alternately, use
the arrow button to import the currently selected song from the song selector.
After a short delay, an image of the song's waveform is displayed.
<para>
<inlinemediaobject>
<imageobject>
<imagedata fileref="@image_path@/beatcalc01.jpeg" format="jpg">
</imageobject>
<textobject>
<phrase> Beatcalc Example Pic 1 </phrase> 
</textobject>
</inlinemediaobject>
</para>
</listitem>


<listitem>
<para>
I use the middle mouse button to set the position marker (vertical red line)
near the beginning of the song.  I press play, and listen for the first measure
of the song.  Noting the time (five and a half seconds of introduction on 
this track) i begin to click on the <guibutton>tap</guibutton> button in time 
with the music.  After a minute or so, the bpm value given by the timing of 
my taps has closed in on a reasonable first estimate.
<para>
<inlinemediaobject>
<imageobject>
<imagedata fileref="@image_path@/beatcalc02.jpeg" format="jpg">
</imageobject>
<textobject>
<phrase> Beatcalc Example Pic 2 </phrase> 
</textobject>
</inlinemediaobject>
</para>
</listitem>


<listitem>
<para>
I enter my first guess at the tempo of the song and the location of the first 
beat.  Yellow bars appear on the image where beat locations are predicted.  I
zoom in close to the first beat, and play the song from there.  This time,
i can hear a clicktrack marking the locations of the beat lines.
<para>
<inlinemediaobject>
<imageobject>
<imagedata fileref="@image_path@/beatcalc03.jpeg" format="jpg">
</imageobject>
<textobject>
<phrase> Beatcalc Example Pic 3 </phrase> 
</textobject>
</inlinemediaobject>
</para>
</listitem>


<listitem>
<para>
A closer look supports what my ears told me: the beats are predicted a little
early of their actual location.  
<para>
<inlinemediaobject>
<imageobject>
<imagedata fileref="@image_path@/beatcalc04.jpeg" format="jpg">
</imageobject>
<textobject>
<phrase> Beatcalc Example Pic 4 </phrase> 
</textobject>
</inlinemediaobject>
</para>
</listitem>


<listitem>
<para>
I control-click on the actual location of the first beat, and the bars jump
into alignment.  I can hear the clicks move much closer into synch with the
music.
<para>
<inlinemediaobject>
<imageobject>
<imagedata fileref="@image_path@/beatcalc05.jpeg" format="jpg">
</imageobject>
<textobject>
<phrase> Beatcalc Example Pic 5 </phrase> 
</textobject>
</inlinemediaobject>
</para>
</listitem>


<listitem>
<para>
Moving further into the song, I see that my bpm estimate is too high; the clicks
are getting ahead of the music.
<para>
<inlinemediaobject>
<imageobject>
<imagedata fileref="@image_path@/beatcalc06.jpeg" format="jpg">
</imageobject>
<textobject>
<phrase> Beatcalc Example Pic 6 </phrase> 
</textobject>
</inlinemediaobject>
</para>
</listitem>


<listitem>
<para>
I left-click on precise beat locations, and the bpm value is nudged down so
that the beat lines fall on my mouse press locations.
<para>
<inlinemediaobject>
<imageobject>
<imagedata fileref="@image_path@/beatcalc07.jpeg" format="jpg">
</imageobject>
<textobject>
<phrase> Beatcalc Example Pic 7 </phrase> 
</textobject>
</inlinemediaobject>
</para>
</listitem>


<listitem>
<para>
I continue through the song, improving the bpm estimate, until i reach the end.
<para>
<inlinemediaobject>
<imageobject>
<imagedata fileref="@image_path@/beatcalc08.jpeg" format="jpg">
</imageobject>
<textobject>
<phrase> Beatcalc Example Pic 8 </phrase> 
</textobject>
</inlinemediaobject>
</para>
</listitem>

<listitem>
<para>
I return to the first beat, zoom in closer, and make another pass through.
Shift-click is used to shift the first beat location slightly without
disturbing the bpm value.  I also verify that the clicks are reasonably
accurate throughout the entire song.  When i'm happy with the values,
i use the <guibutton>update database</guibutton> button to write the bpm and 
firstbeat data into the database.  I'll save the database so the data will 
forever be available.
<para>
<inlinemediaobject>
<imageobject>
<imagedata fileref="@image_path@/beatcalc09.jpeg" format="jpg">
</imageobject>
<textobject>
<phrase> Beatcalc Example Pic 9 </phrase> 
</textobject>
</inlinemediaobject>
</para>
</listitem>

</orderedlist>

</sect1>



<sect1 id="sequencer"><title>The Sequencer</title>

<para>
    First, use must produce some samples to sequence.
    Open the "Sample Picker" and "Buffer Manager" and
    select some .WAV files somewhere.  
    Select one of them in the buffer manager.

</para><para>
    Then, clicking on the sequencer's background area should
    yield a circle.  If you press the <guibutton>Play</guibutton> 
    button you should hear that sample play repetitively.

</para><para>
    You may select different samples in the buffer manager.

</para><para>
    To move a sample, drag it with the mouse.

</para><para>
    To delete a sample, right-click on it.

</para><para>
    To move a bunch of samples, select them with the middle-button,
    then they all drag as a unit.  You can use shift to copy.

</para><para>
    By default, the vertical axis represents volume.
    By pressing the <guibutton>By Resample Rate</guibutton> button, the
    vertical axis will represent the frequency (that is,  pitch).
    In this mode you can compose limited melodies.

</para><para>
    You may enter a filename in the entry box between the
    <guibutton>Save</guibutton> and <guibutton>Load</guibutton> buttons.  
    Then when you press the <guibutton>Save</guibutton> button the 
    sequence will be saved to that file.

</para><para>
    A playing sequence can be altered by tapping in time on 
    a gui button, a keyboard key, or a MIDI keyboard.  In the
    first two cases, the pitch and volume of the new samples 
    will be the current default pitch and volume.  In the
    last case, the pitch and volume will be determined by
    the MIDI input (i.e., which key was pressed and how hard.)
    MIDI input must be enabled and the correct channel selected
    for this to work.
</para>
</sect1>


<sect1 id="beatmatching"><title>Overview of Beat Matching in GDAM</title>
<para>
  This document is an explanation of beat matching in 
  GDAM.  See gdam.org for more information.

</para><para>
  In addition to complete control over position and speed,
  GDAM can make use of meta-information about the song.  This
  data must be entered manually by the user once, and resides
  in a database which GDAM references 
  (<filename>~/.gdam/song.database</filename> is a common location.)

</para><para>
  Currently, two values are used to describe the beat 
  information of a song - the tempo (beats per minute)
  and phase (location of the first beat.)  Knowledge of
  the tempo allows the user to automatically resample 
  songs so that they will play in time, seek around 
  within a song by even beats, and coordinate many
  effects to fit with the song.  Knowledge of both the
  location of the first beat and the bpm allows GDAM
  to extrapolate the location of every single beat.  
  This can then be used to force songs to play in time
  with eachother, ensuring that the beats overlap nicely.

</para><para>
  Several tools exist to help one build their song database.
  The Database Builder is accessible from the song selector,
  and uses find and/or locate to add mp3 files to the database.
  The Beat Calculator graphically displays the waveform of
  a song, and draws lines where beats are predicted.  The user
  can then stretch and move the beats until (if possible) they
  accurately describe the position of every beats.  Chunks of
  the song can be highlighted and played back for orientation.
  In addition, a click track is played in time with song.
  One can hear the effect of adjusting the beat information
  instantly, and audibly verify the accuracy of a song's beat 
  information.  The volume of the click track can be adjusted.
  Once satisfied, the user can update the database with the
  song's info, and then save the database.
</para>
<para>
  Collecting beat information takes a little practice, but
  will soon become easy.  The impact of a beat is percieved when 
  the waveform jumps from low amplitude to high amplitude, where the 
  slope is the greatest.  Percussion often stands out from the 
  surrounding music as a strong nearly-vertical boundary between a looser,
  lower-frequency waveform and a more dense clump representing the
  high frequencies of, say, a snare hit.
</para>
<para>
  Some songs will drift or change tempo over time.  A more
  descriptive system of describing beat information will be
  introduced in the future to account for these cases.  For
  now, use beat info as a guidline if you wish.  Note that 
  a song may display small local drift when zoomed in upon 
  which is not apparent when listened to.
</para>



<chapter id="gdamcli"><title><command>gdamcli</command>: Command Line Interface to the GDAM Server</title>

<sect1 id="runningcli"><title>Running <command>gdamcli</command></title>
<para>
<command>gdamcli</command> is a barebone text interface to the 
<command>gdam-server</command>.
It is useful for
<itemizedlist>
<listitem><para>writing test code.  
</para></listitem>
<listitem><para>scripting (and hence batch processing).  
</para></listitem>
<listitem><para>very primitive interface to everything gdam can do.  
</para></listitem>
</itemizedlist>
</para><para>
<cmdsynopsis>
	<command>gdamcli</command>
	<arg>--gdam-server <replaceable>host:port</replaceable></arg>
	<arg>--device <replaceable>device</replaceable></arg>
	<arg rep="repeat">
	   <group>
	     <arg><replaceable>script_name</replaceable></arg>
	     <arg>-e "<replaceable>command</replaceable>"</arg>
	   </group>
	</arg>
</cmdsynopsis>

</para><para>
    <command>Gdamcli</command> is a command line interface which allows one 
    to examine the state of the mixer, and adjust sources by hand.  
    <userinput>ls $mixer</userinput> returns a list of sources attached the 
    top level mixer.  <userinput>detach <replaceable>n</replaceable></userinput>
    removes source <replaceable>n</replaceable> from the mix (useful if an 
    unwanted song is somehow playing on the server.)  
    <userinput>ls <replaceable>n</replaceable></userinput> returns info about 
    source <replaceable>n</replaceable>.  
    <userinput>set <replaceable>n arg value</replaceable></userinput>
    sets argument <replaceable>arg</replaceable> to 
    <replaceable>value</replaceable> for source <replaceable>n</replaceable>.  
    Each source has its own set of arguments, which can be determined by 
    <userinput>ls</userinput>'ing it.
</para>
<para>
    If no script_names or commands are given, 
    <command>gdamcli</command> enters
    into "interactive mode" much like many shells.
    Commands and script_names are useful for automated
    tasks.
</para>

<sect1 id="clicommands"><title><command>gdamcli</command> Command Summary</title>

<para>
    Here are most of the commands:
</para>
<para>
<itemizedlist>
<listitem>
<para>

<cmdsynopsis>
<command>
ls
</command>
<arg>-a</arg>
<arg>-R</arg>
<arg rep=repeat><replaceable>source_id</replaceable></arg>
</cmdsynopsis>
</para>
<para>
	        ls - list (or print) soundsources.   The source_id's may be 
		those returned by subsource creation routines, or may be 
		determined by <userinput>ls</userinput> or other means.

</para><para>
		Options:
<glosslist>

       <glossentry>
       <glossterm>
       -a
       </glossterm>
       <glossdef>
       <para>
	show all arguments
       </para>
       </glossdef>
       </glossentry>

       <glossentry>
       <glossterm>
       -R
       </glossterm>
       <glossdef>
       <para>
	recurse -- print the entire tree.
	       usually <userinput>ls</userinput> shows just one layer: this
	       makes it ascend the entire tree.
       </para>
       </glossdef>
       </glossentry>

</glosslist>
</para></listitem>

<listitem><para>
<cmdsynopsis>
<command>silence</command>
<arg><replaceable>mixer_id</replaceable></arg>
</cmdsynopsis>
</para><para>
		silence - remove all sound sources for a device.
		Defaults to the mixer for the default device.
</para>
</listitem>

<listitem>
<para>
<cmdsynopsis><command>mixer</command></cmdsynopsis>
</para>
<para>
	mixer - return the default mixer id number.
	This is the source id to <command>ls</command> and the default mix_id
	for <command>add</command>.
</para></listitem>


<listitem>
<para></para>
<cmdsynopsis>
<command>device</command>
<arg><replaceable>device_id</replaceable></arg>
</cmdsynopsis>
<para>
	device - return the default device id number.
</para></listitem>

<listitem><para>
<cmdsynopsis>
<command>source</command>
<arg choice="req"><replaceable>name</replaceable></arg>
<arg><replaceable>GdamSourceType</replaceable></arg>
<arg rep=repeat>
  <replaceable>arg_name</replaceable>
  <replaceable>arg_value</replaceable>
</arg>
</cmdsynopsis>
</para><para>
	source - create a sound source.  Creates a new source named the 
	specified variable name, and sets the specified arguments.  The 
	source is generally then set as another's child or 
	<userinput>add</userinput>-ed to the mix.
</para></listitem>

<listitem><para>
<cmdsynopsis>
<command>set</command>
 <arg>
  <group>
   <arg><replaceable>source_id</replaceable></arg>
   <arg>$<replaceable>variable_name</replaceable></arg>
  </group>
  <arg rep="repeat">
   <replaceable>arg_name</replaceable>
   <replaceable>arg_value</replaceable>
  </arg>
 </arg>
</cmdsynopsis>
	set - set a source's arguments.  TODO: finish writing.
</para></listitem>

<listitem><para>
<cmdsynopsis><command>detach</command><arg><replaceable>id</replaceable></arg>
</cmdsynopsis>
	detach - orphan a sound source.  This causes the source id to stop 
	feeding whatever it is feeding.  It usually dies thereafter (unless
	it is not attached or is still otherwise accessible).
</para></listitem>


<listitem><para>

<cmdsynopsis>
<command>add</command>
<arg choice="req"><replaceable>source_id</replaceable></arg>
<arg><replaceable>source_id</replaceable></arg>
</cmdsynopsis>
	add - add a source to a mixer.  Add the given source to the 
	given mixer (or the default mixer if no mix is specified).
</para></listitem>



<listitem><para>

<cmdsynopsis><command>help</command><arg>topic</arg></cmdsynopsis>

		If no topic is specified, a list of topics is printed.
</para></listitem>
</itemizedlist>
</para>
<para>
	help - online help TODO:  write me!  
</para>









<chapter id="gdam123"><title><command>gdam123</command>: Command Line Mp3 Player</title>

<sect1 id="runninggdam123"><title>Running <command>gdam123</command></title>
<para>
<command>gdam123</command> is a command line utility to play mp3 files on a 
gdam server.  It takes a list of mp3 files, and emulates 
<command>mpg123</command>'s ^C handling.  In
addition, <command>gdam123</command> features a healthy set of vi key bindings 
and playlist handling features.  
</para>

<para>

<cmdsynopsis>
	<command>gdam123</command>
	<arg>--gdam-server <replaceable>host:port</replaceable></arg>
	<arg>--device <replaceable>device</replaceable></arg>
	<arg>-z</arg>
	<arg rep="repeat">
	     <replaceable>filename</replaceable>
	</arg>
	<arg rep="repeat">
	     <replaceable>directory</replaceable>
	</arg>
	<arg rep="repeat">
	     <replaceable>playlist</replaceable>
	</arg>
</cmdsynopsis>


<para>
Mp3 files, playlists, directories, and gdam song databases can be given
on the command line.  Playlists are files with some lines which are paths
to mp3 files.  If any path is not absolute, then the path to the playlist
is prepended.  If a directory is given, then any mp3 files within that
directory will be added.  Each directory will be sorted according to
playlist or ccdb data files which exist in that directory.  Subdirectories 
are recursively processed.   If <option>-z</option> is given, the 
playlist is shuffled before playback.
</para>


<sect1 id="gdam123keys"><title>Key Bindings</title>
<para>
Most of these keys can be preceeded by a number, which usually means
to apply the command that many times.  
<para>
<segmentedlist><title>simple <command>gdam123</command> key bindings</title>
  <segtitle> key </segtitle>
  <segtitle> action </segtitle>
  <seglistitem>
    <seg> j,k </seg> 
    <seg> skip to next/prev song </seg>
  </seglistitem>
  <seglistitem>
    <seg> <replaceable>n</replaceable>G </seg> 
    <seg> skip to <replaceable>n</replaceable>th song.  G skips to last
    		song, </seg>
  </seglistitem>
  <seglistitem>
    <seg> h,l </seg> 
    <seg> seek back/forward a beat, or a second if bpm is unknown </seg>
  </seglistitem>
  <seglistitem>
    <seg> [,] </seg> 
    <seg> seek back/forward a bar, or four seconds if bpm is unknown </seg>
  </seglistitem>
  <seglistitem>
    <seg> ^ </seg> 
    <seg> seeks to beginning of song </seg>
  </seglistitem>
  <seglistitem>
    <seg> <replaceable>n</replaceable>| </seg> 
    <seg> skip to <replaceable>n</replaceable>th second </seg>
  </seglistitem>
  <seglistitem>
    <seg> i </seg> 
    <seg> pause/unpause song </seg>
  </seglistitem>
  <seglistitem>
    <seg> o,p </seg> 
    <seg> decreases/increases volume by <replaceable>delta</replaceable>%, 
    	default 10%</seg>
  </seglistitem>
  <seglistitem>
    <seg> O,P </seg> 
    <seg> set volume to 0%, 100% </seg>
  </seglistitem>
  <seglistitem>
    <seg> z </seg> 
    <seg> shuffle playlist </seg>
  </seglistitem>
  <seglistitem>
    <seg> r </seg> 
    <seg> toggle repeat mode </seg>
  </seglistitem>
  <seglistitem>
    <seg> n </seg> 
    <seg> repeat last search </seg>
  </seglistitem>
  <seglistitem>
    <seg> N </seg> 
    <seg> repeat last search, in opposite direction </seg>
  </seglistitem>
  <seglistitem>
    <seg> ^G (control-g) </seg> 
    <seg> print extended information about the current song.  Info 
    		includes length, sampling rate, and id3 tags. </seg>
  </seglistitem>
  <seglistitem>
    <seg> q </seg> 
    <seg> quit <command>gdam123</command> </seg>
  </seglistitem>
</segmentedlist>
</para>



<sect1 id="gdam123excommands"><title>Ex-Style Commands</title>
<para>
Gdam123 also accepts ex-style input.  A colon(:) initiates an ex command, 
which can be seen as it is entered.  <userinput>:help</userinput> produces 
a full list of key bindings and ex commands.  
<userinput>:a <replaceable>filename</replaceable></userinput> appends a file 
to the playlist.  Directories and playlists can also be appended.  

<segmentedlist><title>ex-style <command>gdam123</command> key bindings</title>
  <segtitle> command </segtitle>
  <segtitle> action </segtitle>
  <seglistitem>
    <seg> :volume <replaceable>n</replaceable> </seg> 
    <seg> set volume to <replaceable>n</replaceable>%.  Volumes above 100%
    		are allowed.</seg>
  </seglistitem>
  <seglistitem>
    <seg> :set volume_delta <replaceable>delta</replaceable> </seg> 
    <seg> changes the effect of a volume nudge to 
    		<replaceable>delta</replaceable>%.  Affects o,p key bindings.
    		</seg>
  </seglistitem>
  <seglistitem>
    <seg> :print </seg> 
    <seg> print playlist.  </seg>
  </seglistitem>
  <seglistitem>
    <seg> :append <replaceable>filename</replaceable> </seg> 
    <seg> if <replaceable>filename</replaceable> is an mp3 file, it is 
    appended to playlist if it is an mp3 file.  If it is a playlist, the 
    contents are added.  If it is a directory, the subdirectories are 
    sourced for mp3 files.
  </seglistitem>
  <seglistitem>
    <seg> :<replaceable>n</replaceable> </seg> 
    <seg> skip to the <replaceable>n</replaceable>th song.
  </seglistitem>
</segmentedlist>
</para>









<chapter id="ladspa"><title>LADSPA Support </title>

<sect1 id="ladspaplugins"><title>Ladspa Plugins</title>
<para>
<acronym>LADSPA</acronym> is a relatively new simple audio plugin 
architecture.  This standard is open, and aims to enable linux audio 
applications to share audio plugins.  GDAM has preliminary support for 
both loading <acronym>LADSPA</acronym> plugins and creating them from 
mininetwork layouts.

<sect1 id="installingladspa"><title>Installing LADSPA</title>

<itemizedlist>
<listitem><para>
    Download the <acronym>LADSPA</acronym> <acronym>SDK</acronym>, available 
    <ulink url="http://www.muse.demon.co.uk/ladspa.html">
    online</ulink>
</para>
</listitem>
<listitem><para>
    Copy <filename>ladspa.h</filename> to <filename>/usr/local/include</filename>.
</para></listitem>
</itemizedlist>

<important>
<para>
Note:  if compiling, you must do this <emphasis>BEFORE</emphasis> you 
configure GDAM - otherwise it will automatically compile without 
<acronym>LADSPA</acronym> support.  You'll need to remove 
<filename>config.cache</filename> and reconfigure... best to start with 
a fresh copy of the source.
</para>
<para>
The binary distribution packages should always include <acronym>LADSPA</acronym>
support.  However, even with the packages, you will need 
<filename>ladspa.h</filename> to compile new plugins.
</para>
</important>


<sect1 id="installingpluginmaker"><title>Installing <command>ladspapluginmaker</command></title>
<para>
The latest version of <command>ladspapluginmaker</command> is available on the 
web at <ulink url="http://www.gdam.org/">gdam.org</ulink>, in the download 
section.  Source tarballs, rpms and debs are available.
</para>


<sect1 id="writingladspaplugins"><title>How to Write LADSPA Plugins Using GDAM</title>
<sect2 id="writingladspapluginsoverview"><title>Overview</title>
<para>
The procedure has two steps:
<itemizedlist>
<listitem>
<para>
    Create a flow graph graphically using GDAM (inside the mininetwork
    filter).  Save it to XML.
</para>
</listitem>
<listitem>
<para>
    Convert the XML to a LADSPA plugin using <command>ladspapluginmaker</command>.
    Usually this will convert the xml to C code, then it runs the compiler.
</para>
</listitem>
</itemizedlist>


<sect2 id="writingladspapluginsmininet"> <title>Using the Mininetwork</title>
<para>
The mininetwork has many types of "nodes"
which you can create, delete, and connect.
<para>
Here is the example we will use throughout:
<para>
<inlinemediaobject>
<imageobject>
<imagedata fileref="@ladspa_image_path@/mininet.jpg" format="jpg">
</imageobject>
<textobject>
<phrase> Screenshot of the Mininetwork Widget </phrase> 
</textobject>
</inlinemediaobject>
<para>
This actually sounds like a plucked string filter.
(I'll describe it a bit more below).
<para>
You can see it contains a bunch of nodes
which are connected.
You can drag them around, and drag pipes from inputs to outputs.
Here are exactly what the various mouse buttons do:
<glosslist>
<glossentry>
<glossterm>left mouse button:</glossterm>
<glossdef><para>
    If you clicked on a node's input or output, you may
    drag a pipe to another node's input or output. (you must
    connect inputs to outputs though!).
    If you clicked on a node, you may drag it, and it will be selected.  
    When it is selected,
    a menu of adjustable parameters appears. (eg for the gain filter,
    a <guilabel>gain</guilabel> slider appears in that window.)
    If you clicked outside a node, a new unconnected node is formed.
</para> </glossdef>
</glossentry>
<glossentry>
<glossterm>middle mouse button:</glossterm>
<glossdef><para>
    If you clicked on a node, it is deleted, but its
    inputs are attached to its outputs.
    If you clicked on a pipe,
    a new node is formed in the middle of the pipe,
    properly connected.
</para> </glossdef>
</glossentry>
<glossentry>
<glossterm>right mouse button:</glossterm>
<glossdef><para>
    If you clicked on a node, it and all its pipes will be deleted.
    If you clicked on a pipe, it will be deleted.
</para> </glossdef>
</glossentry>
</glosslist>

<para>
The inputs to each node are on the top of the node --
each node has only one output, but you can connect an
arbitrary number of things to that output.
<para>
Here are some common nodes:
<glosslist>
<glossentry>
<glossterm>Mix</glossterm>
<glossdef><para>
<inlinemediaobject>
<imageobject>
<imagedata fileref="@ladspa_image_path@/mix.jpg" format="jpg">
</imageobject>
</inlinemediaobject>
This just adds all its inputs together.
</para></glossdef>
</glossentry>

<glossentry>
<glossterm>Modulator</glossterm>
<glossdef><para>
<inlinemediaobject>
<imageobject>
<imagedata fileref="@ladspa_image_path@/modulator.jpg" format="jpg">
</imageobject>
</inlinemediaobject>
   This multiplies its inputs like a ring modulator.
   Or equivalently it is a variable gain.
</para></glossdef>
</glossentry>

<glossentry>
<glossterm>Constant Gain</glossterm>
<glossdef><para>
<inlinemediaobject>
<imageobject>
<imagedata fileref="@ladspa_image_path@/gain.jpg" format="jpg">
</imageobject>
</inlinemediaobject>
   This multiplies its single input by a constant value.
   [in the gui, you can change the constant, but it is constant once
   it is converted to a LADSPA plugin].
</para></glossdef>
</glossentry>

<glossentry>
<glossterm>Constant Delay</glossterm>
<glossdef><para>
<inlinemediaobject>
<imageobject>
<imagedata fileref="@ladspa_image_path@/delay.jpg" format="jpg">
</imageobject>
</inlinemediaobject>
   This delays its input for a certain number of samples.
   [in the gui, you can change the constant, but it is constant once
   it is converted to a LADSPA plugin].
</para></glossdef>
</glossentry>

<glossentry>
<glossterm>Variable Delay</glossterm>
<glossdef><para>
<inlinemediaobject>
<imageobject>
<imagedata fileref="@ladspa_image_path@/variabledelay.jpg" format="jpg">
</imageobject>
</inlinemediaobject>
   This delays its input for a number of samples, which is computed
   from another nodes output.
<para>
   The actual delay at any time is given by:
<para>
   delay = (base_delay) + (delay_fluctuation * input_value)
<para>
   where the input_value is from the delay-input (which is the top-right
   connector on the variable delay).
</para></glossdef>
</glossentry>

<glossentry>
<glossterm>Input</glossterm>
<glossdef><para>
<inlinemediaobject>
<imageobject>
<imagedata fileref="@ladspa_image_path@/input.jpg" format="jpg">
</imageobject>
</inlinemediaobject>
   This represents where sound is input to the filter from the source above it.
   You cannot create new inputs or destroy the existing one.
</para></glossdef>

</glossentry>
<glossentry>
<glossterm>Output</glossterm>
<glossdef><para>
<inlinemediaobject>
<imageobject>
<imagedata fileref="@ladspa_image_path@/output.jpg" format="jpg">
</imageobject>
</inlinemediaobject>
   The output from the filter.  You cannot create new outputs or destroy 
   the existing one.
</para></glossdef>
</glossentry>
</glosslist>
</para>



<sect3><title>Brief Digression into the Plucked String Filter</title>
<para>
The plucked string is basically a feedback of the tuning
frequency with a lowpass filter.
<itemizedlist>
<listitem><para>
    In the upper-left corner, the input is revolumized (by a modulator)
    with a control node (at left).  This implements the input gain slider.
</para></listitem>
<listitem><para>
    In the mix in the center is the mix which is collecting feedback.
</para></listitem>
<listitem><para>
    The right side is the feedback loop.  It is revolumized
    to control how loud the reverb should be.
</para></listitem>
<listitem><para>
    The two lower-right nodes implement a very simple lowpass
    filter that just averages the last two samples.
</para></listitem>
</itemizedlist>
This is usually called a Karplus-Strong string filter.

<sect2 id="writingladspapluginsmininetsave"><title>Saving the New Filter</title>
<para>
You just press the <guibutton>save</guibutton> button, at the left.
It will prompt you for a filename -- you'll
have to specify it in the next step.



<sect2 id="writingladspapluginsconvert"><title>Converting the Filter to a LADSPA Plugin</title>
<para>
Suppose you saved the mininetwork as <ulink
url="http://www.ffem.org/gdam/examples/pluckedstring.xml">
pluckedstring.xml</ulink>.  Then you would run the following command:
<screen>
	ladspapluginmaker --input pluckedstring.xml \
	                  --output output_dir \
			  --class PluckedString \
			  --basename pluckedstring \
			  --description "Karplus-Strong Plucked String" \
			  --unique-id 10 \
			  --build
</screen>
<para>
The <option>--unique-id</option> option deserves brief mention.
Currently all plugins are centrally allocated
by talking to Richard Furse, <email>richard@muse.demon.co.uk</email>.
He will assign you a list of UniqueIDs.
In the interim, you can use ids  less than 4000 for development
purposes.
<para>
(TODO: put more of these options in the xml!)
<para>
This will create a directory <filename>output_dir</filename> with
three files in it:
<itemizedlist>
<listitem>
<para>
<filename>output_dir/pluckedstring.c</filename> - the c file implementing the plugin 
(<ulink url="http://www.ffem.org/gdam/examples/pluckedstring.c">online</ulink>)
</para></listitem>
<listitem>
<para>
<filename>output_dir/pluckedstring.h</filename> - the h file with the instance structure (which is named PluckedString) in it.  Available 
<ulink url="http://www.ffem.org/gdam/examples/pluckedstring.h">online</ulink>.
</para>
</listitem>
<listitem><para>
<filename>output_dir/pluckedstring.so</filename> - the library we obtained by 
compiling the above source files.
</para></listitem>
</itemizedlist>



<sect2 id="loadingladpsaplugins"><title>Loading LADSPA Filters with GDAM</title>
<para>
GDAM automatically scans for LADSPA plugins when it
starts up.  It looks in <filename>/usr/lib/ladspa</filename>
and <filename>/usr/local/lib/ladspa</filename>.  It will
write a summary file to <filename>~/.gdam/ladspa.xml</filename>.
<para>
This is what the loaded plugin looks like:
<para>
<inlinemediaobject>
<imageobject>
<imagedata fileref="@ladspa_image_path@/ladspa.jpg" format="jpg">
</imageobject>
<textobject>
<phrase> Screenshot of the Compiled Ladpsa Plugin </phrase> 
</textobject>
</inlinemediaobject>
</para>
















<chapter id="hardwareinput"><title>Hardware Input Support</title>


<sect1 id="hardwareinputoverview"><title>Hardware Input in GDAM</title>

<para>
    GDAM supports hardware input in a few ways.  Midi devices, auxilliary
keyboards, and ultrasonic rangefinder input plugins exist already.  As of
writing, only gui components make use of hardware input, but it is implemented
on a lower level, so other clients may support it in the future.  </para>

<para>
    You can get started immediately:  open the midi selector
    and then open a gain widget.  It should have a MIDI button
    once the selector is opened.  Depressing that button with
    the mouse, which wiggling a midi knob will automatically
    attach the gain's volume to the knob.  </para>

<para>
    You can also specify more information about your device.
    Then the messages will be more readable, and that is 
    the only way to trap "System Exclusive" messages.  
</para>


<para>
NOTE: hardware input has been rewritten as of version 0.922.  Changes include unification of hardware input methods, and the ability to assign a set of bindings to a component by reading an xml file.

<para>

GDAM supports midi hardware input.  Through plugins, other hardware
input devices (i.e. sonic rangefinders) can be supported.  Hardware 
input devices are cool because they transcend the clumsy mouse-and-keyboard
interface most computer users suffer.  For instance, midi sliders allow
a user to vary several parameters simultaneously.  Also, hardware input
assignments don't obey window focus the way a computer's normal keyboard
does, and will continue working regardless of what application the user
may be mousing around in.  Additionally, hardware input devices allow 
the operator to spend less time hunched over a monitor.



<sect1 id="midicontrollers"><title>MIDI Controllers</title>

<para>
GDAM can make use of many knobs, sliders, and pitch wheels found on midi 
keyboards.  If your hardware offers a mode of operation where all controls emit
"continuous controller" type messages (most often used for interfacing to computer sofware) select that.  GDAM may not be able to use all system exclusive and nonstandard messages.  For midi input to work, several files must be in 
place describing the device.  create a file 
<filename>~/.gdam/input.devices</filename> with entries as follows:

<para>

<screen>/dev/midi /home/geoff/gdam/skin/midi/roland-jp8000.xml GdamMidiDevice
</screen>

<para>
listing each device, the patch description file (or "none"), and the 
corresponding gdam class.  The patch file contains descriptions for different 
input mechanisms, as shown here:

<screen>
&lt;Gdam-Trap-Descriptions&gt;
  &lt;trap&gt;
    &lt;description&gt;funky pitchwheel&lt;/description&gt;
    &lt;GdamMidiEventPitchWheel&gt;
      &lt;input_id&gt;0&lt;/input_id&gt;
      &lt;device&gt;/dev/midi&lt;/device&gt;
    &lt;/GdamMidiEventPitchWheel&gt;
  &lt;/trap&gt;
&lt;/Gdam-Trap-Descriptions&gt;
</screen>

<para>
The default input.devices file contains a generic entry which should allow
instant use of many midi devices... just open <filename>/dev/midi</filename>.  
See the <ulink url="http://ffem.org/gdam/links.html">links section</ulink> 
for commercial midi controller devices.



<sect1 id="rangefinders"><title>Ultrasonic Rangefinders</title>
<para>
A friend of mine hacked a parallel port interface to a few ultrasonic rangefinders.  GDAM  supports these devices as midi input via a plugin.  Thus, we can control aspects of the sound by moving our hands through space.  This interface was originally developed for the Texas Instruments Calculator Based Rangefinder:

<para>
<inlinemediaobject>
<imageobject>
<imagedata fileref="@image_path@/cbr.jpg" format="jpg">
</imageobject>
<textobject>
<phrase> Picture of CBR Rangefinder </phrase> 
</textobject>
</inlinemediaobject>

<para>
<ulink url="http://www.pasco.com">Pasco</ulink> scientific equipment 
offers a compatible model which performs much better:

<para>
<inlinemediaobject>
<imageobject>
<imagedata fileref="@image_path@/pasco.jpg" format="jpg">
</imageobject>
<textobject>
<phrase> Picture of Pasco Rangefinder </phrase> 
</textobject>
</inlinemediaobject>

<para>
Once we've reconstructed the hardware a bit, we will most likely post
instructions here so that others can try it out.  The 
<filename>input.devices</filename> line describing a rangefinder looks 
as follows: 
<para>

<screen>/dev/rangefinder none GdamRangeFinder</screen>
<para>



<sect1 id="secondarykeyboards"><title>Secondary Computer Keyboards </title>
<para>
A recent development, secondary keyboards may be the easiest way for the
greatest number of users to add hardware input, because the requirements
are slight.  Because I have my mouse on a ps2-to-serial convertor, I have
a free ps2 port on my computer.  I can attach a second computer keyboard
to this port, and open it as a hardware input device in gdam.  I can then
use keys on the second keyboard to control gdam, without worrying about window
focus, and while simultaneously using the normal keyboard for whatever I need.
Perhaps better than a standard keyboard would be a bank of 10-key pads,
one for each turntable... if i get a USB port, i'll look into it.  
The default <filename>input.devices</filename> file contains a line:
<para>

<screen>/dev/psaux none GdamPs2Keyboard</screen>

<para>
which should allow any user with a second keyboard on /dev/psaux to make 
immediate use of it.
<para>



<sect1 id="dynamicinputassignment"><title>Dynamic Input Assignment</title>
<para>
Many components have buttons labeled <guibutton>midi</guibutton> or 
<guibutton>m</guibutton> adjacent to adjustments.  These are used to assign 
hardware control over that adjustment (or rather, the
value which that adjustment controls).  While holding the button
down with the mouse, move a midi slider or other device.  From then on, that
device will have control over the corresponding value.  An adjustment can be
freed from control by right clicking on the <guibutton>m</guibutton> button.  
These buttons will only respond to their most recent dynamic assignment, but a 
piece of hardware can control several different adjustments.  This method of 
assignment is useful for quickly adding control to a newly created filter, or 
reassigning some unique input device like a ribbon pad or rangefinder.
<para>





<sect1 id="inputbindingfiles"><title>Input Binding Files</title>
<para>
Sets of hardware input bindings can be read from an xml file and applied to a 
component.  This is useful for, say, assigning one of five standard 
keybinding sets to a new turntable; in one simple step, an entire row of 
keyboard buttons can be set to control all the iconated buttons.  


<sect2 id="inputbindingfileformat"><title>Binding File Format</title>
<para>
A gdam hardware binding file looks like this:
<para>

<screen>
&lt;Gdam-Binding-Interface&gt;
  &lt;constant&gt;
    &lt;argument&gt;seek_by_bars&lt;/argument&gt;
    &lt;value&gt;2&lt;/value&gt;
    &lt;GdamPs2KeyboardPress&gt;
      &lt;key&gt;c&lt;/key&gt;
      &lt;device&gt;dev/psaux&lt;/device&gt;
    &lt;/GdamPs2KeyboardPress&gt;
  &lt;/constant&gt;
&lt;/Gdam-Binding-Interface&gt;
</screen>

<para>

The file is a list of bindings between Gdam-Binding-Interface tags:
<para>

<screen>
&lt;Gdam-Binding-Interface&gt;
  [binding]
  [binding]
&lt;/Gdam-Binding-Interface&gt;
</screen>



<sect2 id="inputbindingfileformatbinding"><title>Binding Descriptions</title>

<para>
Each binding is nested between tags describing the type of input behavior,
and contains a comonent argument and corresponding values(s).
The "constant" type of binding causes an arg to be set to a specific
value.  Allowed values vary depending on the component argument being
manipulated... boolean args can be 0 or 1, float args can vary over an
allowed range, and string args need to be certain predefined tokens.
The "range" bindings translate a range of midi values to a range
of argument values.  This cannot be used with a string arg.
<para>
The arguments and values which each type of model accepts can
be determined by reading the <filename>model/*.c</filename> source 
files and searching for <userinput>gdam_arg_register</userinput>
function calls.  Alternately, you can examine the skin xml files
to see how arguments are attached.

<para>
The constant binding prototype looks like this:
<para>

<screen>
  &lt;constant&gt;
    &lt;argument&gt;argument_name&lt;/argument&gt;
    &lt;value&gt;value to set on input event&lt;/value&gt;
    [input event description]
  &lt;/constant&gt;
</screen>

<para>
the range binding prototype looks like this:
<para>

<screen>
  &lt;range <optional>type="SomeType"</optional>&gt;
    &lt;argument&gt;argument_name&lt;/argument&gt;
    &lt;min_value&gt;min midi value translates to this arg value&lt;/min_value&gt;
    &lt;max_value&gt;max midi value translates to this value&lt;/max_value&gt;
    [input event description]
  &lt;/range&gt;
</screen>

<para>
and the signal binding prototype (which doesn't need an event input description) looks like this:
<para>

<screen>
  &lt;signal <optional>type="GdamPacker"</optional>&gt;
        &lt;signal&gt;whatever&lt;/signal&gt;
        &lt;handler&gt;gdam_packer_trap_key_press:e:tt1:gdam_skin_arg_int:play_or_synch:-1&lt;/handler&gt;
  &lt;/signal&gt;
</screen>

<para>

Either tag can take a <userinput>type</userinput> arg, causing the
binding to be applied only to components of a certain type.  This allows
a single file to contain bindings for a variety of components, and each
component or skin sourced will apply only the bindings which are
relevant to that type.  The following attaches only to turntables,
and causes the turntable to play when the specified event happens.

<para>

<screen>
  &lt;constant type="GdamTurntable"&gt;
    &lt;argument&gt;play_or_synch&lt;/argument&gt;
    &lt;value&gt;3&lt;/value&gt;
    [input event description]
  &lt;/constant&gt;
</screen>

<para>
And the following unmutes a gain component.
<para>

<screen>
  &lt;constant type="GdamGain"&gt;
    &lt;argument&gt;muted&lt;/argument&gt;
    &lt;value&gt;0&lt;/value&gt;
    [input event description]
  &lt;/constant&gt;
</screen>


<sect2 id="inputbindingfileformatevent"><title>Event Descriptions</title>

<para>
An input event description identifies a particular event on a particular device.
When input device events are caught from opened devices, they
are added to the midi device manager gui.  The description
printed there should contain enough information to create
event binding descriptions.
<para>
The exact prototype of an event description varies depending on the type 
of event trapped.  The basic form is as follows:
<para>

<screen>
    &lt;EventType&gt;
      &lt;event_param&gt;value&lt;/event_param&gt;
      &lt;other_event_param&gt;other_value&lt;/other_event_param&gt;
    &lt;/EventType&gt;
</screen>

<para>
This is a description for pressing the 'q' key on a ps2 keyboard attached to 
<filename>/dev/aux</filename>.  It is appropriate for driving a constant
argument binding:

<para>

<screen>
    &lt;GdamPs2KeyboardPress&gt;
      &lt;device&gt;/dev/psaux&lt;/device&gt;
      &lt;key&gt;q&lt;/key&gt;
    &lt;/GdamPs2KeyboardPress&gt;
</screen>

<para>
The following traps the note off event for note index 24 (octave 1, note c) on 
midi channel 0 (which will most likely be labelled '1' on the hardware). 
<para>

<screen>
    &lt;GdamMidiEventNoteOff&gt;
      &lt;input_id&gt;0&lt;/input_id&gt;
      &lt;midi_index&gt;24&lt;/midi_index&gt;
      &lt;device&gt;/dev/midi&lt;/device&gt;
    &lt;/GdamMidiEventNoteOff&gt;
</screen>



<para>
The following traps a midi sysex string of
a certain value.  'System Exclusive' messages
are used by hardware manufacturers to extend
the midi protocol in various ways.  Switching
instruments, modes, patterns, and waveforms
will often cause midi sysex strings to be
emitted.  The only parsing available is
to match a hex string, as printed in the
midi device manager gui when the event
occurs.
<para>

<screen>
    &lt;GdamMidiEventSysex&gt;
      &lt;sysex&gt;0x01 0x02 0x03 0x04&lt;/sysex&gt;
      &lt;device&gt;/dev/midi&lt;/device&gt;
    &lt;/GdamMidiEventSysex&gt;
</screen>

<para>
The following catches midi set-parameter events (parameter events are
most often emitted when a knob, slider, ribbon bar or other 
continuous controller is adjusted).  This type of event is 
appropriate for controlling a range-type arg.  If used with a 
constant argument binding, the arg's value will be set to that constant 
anytime the midi parameter changes.  This is most likely not the desired
behavior.  'input_id' is the midi channel being monitored, and 'parameter'
the continuous controller index (ie which slider);
<para>

<screen>
    &lt;GdamMidiEventParameter&gt;
      &lt;input_id&gt;0&lt;/input_id&gt;
      &lt;parameter&gt;3&lt;/parameter&gt;
      &lt;device&gt;/dev/midi&lt;/device&gt;
    &lt;/GdamMidiEventParameter&gt;
</screen>

<para>
Midi pitchwheels, used to bend the pitch of a midi note by a 
sub-half-step interval, emit a different range of values than 
parameter sliders.  For this reason, they require a special binding.
<para>

<screen>
    &lt;GdamMidiEventPitchWheel&gt;
      &lt;input_id&gt;3&lt;/input_id&gt;
      &lt;device&gt;/dev/midi&lt;/device&gt;
    &lt;/GdamMidiEventPitchWheel&gt;
</screen>



<sect1 id="inputbindingfileexamples"><title>Example Input Binding Files</title>
<para>
When you have a new piece of midi hardware, and want to use it with 
gdam, you usually follow a simple procedure.  Plug the device into
<filename>/dev/midi</filename>, run <command>gdam-launcher</command>, 
and open the midi selector.  Type <userinput>/dev/midi</userinput>
into the device entry, and press <guibutton>open</guibutton>.  Play 
with the device, and watch which controls produce new events in the
event list.  Decide what controls are available, what you want to use them
for, and what xml is needed to describe this binding.


<sect2 id="inputbindingfileexampledr660"><title>Boss Dr Rhythm DR-660</title>
<para>
This is a small drum machine, with 16 drum pads.  It has the ability to play
back midi tunes, but we're not interested in that.  What is useful to us is
that the 16 drum pads emit note-on and note-off events, each pad a different
note.  Furthermore, there is a 'pad bank' button which cycles through sets
of pad-to-note bindings.  If we carefully program to pad banks so that 
there are no conflicting note values, we could control 32 or 48 or 64 
different events with the unit.  When i open the device in the midi selector,
and tap the first two drum pads, i get the following new events:

<screen>
note on, channel 9, c# octave 3, idx=49
note off, channel 9, c# octave 3, idx=49
note on, channel 9, a octave 3, idx=57
note off, channel 9, a octave 3, idx=57
</screen>

<para>
I notice that even if i press and hold a drum pad, a release event
immediately follows the press event.  This is unfortunate because
the pads can only be used as event triggers, not as momentary-on
buttons.  I decide to use the first two pads to seek backwards in
a turntable by one and two bars respectively, and to write a binding
file which i can source on a set of wheels.  From looking at 
<filename>wheels-hotkeys.xml</filename> and other input binding files,
i know how to make a binding associate with the left turntable of a
set of wheels, addressing it by name.  The following xml file
implements these two bindings.
<screen>
&lt;Gdam-Binnding-Interface&gt;
  &lt;constant type="GdamPacker:tt1"&gt;
    &lt;argument&gt;seek_by_bars&lt;/argument&gt;
    &lt;value&gt;-2&lt;/value&gt;
    &lt;GdamMidiEventNoteOn&gt;
      &lt;input_id&gt;9&lt;/input_id&gt;
      &lt;midi_index&gt;49&lt;/midi_index&gt;
      &lt;device&gt;/dev/midi&lt;/device&gt;
    &lt;/GdamMidiEventNoteOn&gt;
  &lt;/constant&gt;
  &lt;constant type="GdamPacker:tt1"&gt;
    &lt;argument&gt;seek_by_bars&lt;/argument&gt;
    &lt;value&gt;-1&lt;/value&gt;
    &lt;GdamMidiEventNoteOn&gt;
      &lt;input_id&gt;9&lt;/input_id&gt;
      &lt;midi_index&gt;57&lt;/midi_index&gt;
      &lt;device&gt;/dev/midi&lt;/device&gt;
    &lt;/GdamMidiEventNoteOn&gt;
  &lt;/constant&gt;
&lt;/Gdam-Binding-Interface&gt;
</screen>

<sect2 id="inputbindingfileexamplea30"><title>Roland A-30 Midi Keyboard Controller</title>
<para>
This is a full-sized midi controller keyboard with a pitchwheel, an expression
lever, and one slider.  The slider can be assigned to any parameter value, so
it could be reused to control more then one value.  The expression lever emits
parameter one, and is activated by pressing upwards on the pitch wheel lever.
Exercising these controls in <command>gdam-launcher</command> produces the
following new events.
<screen>
note on, channel 0, e octave 4, idx=64
note off, channel 0, e octave 4, idx=64
note on, channel 0, f octave 4, idx=65
note off, channel 0, f octave 4, idx=65
note on, channel 0, f# octave 4, idx=66
note off, channel 0, f# octave 4, idx=66
pitchwheel, channel 0
parameter 1, channel 0
parameter 56, channel 0
</screen>
<para>
The keys emit seperate press and release events, so they can be used as 
momentary-on buttons.  I decide to use the first note to mute the gain on
the left turntable; when i depress the 'e' key the gain will be muted, and
when i release the gain key the volume will be restored.  At the same time,
I'll have the data slider control the volume of the left turntable.
The following xml does the trick:

<screen>
&lt;Gdam-Binding-Interface&gt;
  &lt;range type="GdamPacker:gain1"&gt;
    &lt;argument&gt;volume&lt;/argument&gt;
    &lt;min_value&gt;0.0&lt;/min_value&gt;
    &lt;max_value&gt;2.0&lt;/max_value&gt;
    &lt;GdamMidiEventParameter&gt;
      &lt;input_id&gt;0&lt;/input_id&gt;
      &lt;parameter&gt;56&lt;/parameter&gt;
      &lt;device&gt;/dev/midi&lt;/device&gt;
    &lt;/GdamMidiEventParameter&gt;
  &lt;/range&gt;
  &lt;constant type="GdamPacker:gain1"&gt;
    &lt;argument&gt;muted&lt;/argument&gt;
    &lt;value&gt;1&lt;/value&gt;
    &lt;GdamMidiEventNoteOn&gt;
      &lt;input_id&gt;0&lt;/input_id&gt;
      &lt;midi_index&gt;64&lt;/midi_index&gt;
      &lt;device&gt;/dev/midi&lt;/device&gt;
    &lt;/GdamMidiEventNoteOn&gt;
  &lt;/constant&gt;
  &lt;constant type="GdamPacker:gain1"&gt;
    &lt;argument&gt;muted&lt;/argument&gt;
    &lt;value&gt;0&lt;/value&gt;
    &lt;GdamMidiEventNoteOff&gt;
      &lt;input_id&gt;0&lt;/input_id&gt;
      &lt;midi_index&gt;64&lt;/midi_index&gt;
      &lt;device&gt;/dev/midi&lt;/device&gt;
    &lt;/GdamMidiEventNoteOff&gt;
  &lt;/constant&gt;
&lt;/Gdam-Binding-Interface&gt;
</screen>
<para>
I'll also use the pitchwheel with a "bend" filter.  The bend filter applies
a temporary rate change to a song, with the ability to rewind.  The 'wheels'
guicomponent doesn't have a bender packed in, so i cannot address it by name.
However if i create a bender in the filter stack, i can source the following
file to have it follow the pitchwheel.  I choose the speeds to range from
still to double speed.  This puts a rate of 100% in the center.  As the 
pitchwheel is spring-loaded to return to its center, this is convenient.
<screen>
&lt;Gdam-Binding-Interface&gt;
  &lt;range type="GdamBender"&gt;
    &lt;argument&gt;bend_amount&lt;/argument&gt;
    &lt;min_value&gt;0&lt;/min_value&gt;
    &lt;max_value&gt;1&lt;/max_value&gt;
    &lt;GdamMidiEventPitchWheel&gt;
      &lt;input_id&gt;0&lt;/input_id&gt;
      &lt;device&gt;/dev/midi&lt;/device&gt;
    &lt;/GdamMidiEventPitchWheel&gt;
  &lt;/range&gt;
&lt;/Gdam-Binding-Interface&gt;
</screen>



<sect1 id="inputbindingload"><title>Assigning Input Bindings</title>
<para>
Components which support binding sets will have buttons labeled with the 
hardware input icon (a circle with several pins inside) or the word 
<guibutton>Bind</guibutton>.
Clicking on such a button will open a file selection dialog.  Select a
file appropriate to the type of component and input device (ie 
<filename>ps2.turntable.xml</filename> to attach a turntable to a 
secondary keyboard.) The file will be parsed, the hardware device opened 
if needed, and the bindings applied. 
</para>
</sect1>
</chapter>






<appendix id="faq"><title>Frequently Asked Questions</title>

<qandaset defaultlabel='qanda'>
<qandadiv>
<bridgehead id="q0" renderas=sect1>
How do I enable multiple devices with GDAM?
</bridgehead>
<qandaentry>
<question>
<para>How do I enable multiple devices with GDAM?</para>
</question>
<answer>
<para>
   Some client can make use of several devices at once.  These clients
   take several devices as arguments:
</para>
<screen>
	      gdam-launcher --device /dev/dsp1 --device /dev/dsp
</screen>
<para>
   The deviceswitcher component allows gui components to be switched
   between the first and second devices.  If you are using more than 
   two devices, you'll have to modify 
   <filename>deviceswitcher*.xml</filename> to contain 
   more device selection buttons. 
<para>
   Additionally you may have to add lines to your
   <filename>server.config</filename> file:
</para>
<screen>
	  Device          "oss"           "/dev/dsp8"
</screen>
<para>
   where <filename>/dev/dsp8</filename> is the device you are trying to use.
</para>
</answer>
</qandaentry>
</qandadiv>


<qandadiv>
<para>
<bridgehead id="q1" renderas=sect1>
In what ways can gdam use multiple devices? 
</bridgehead>

<qandaentry>
<question>
<para>
In what ways can gdam use multiple devices? 
</para>
</question>
<answer>
<para>
   With only one sound device, a user has no ability to cue a 
   new track. (ie listen to something which isn't played to the
   entire room.)  In this situation, all sound sources are 
   mixed into a single stream which goes to the device. 
   Continuous mixing can only be done using the automated 
   beatmatching system, which requires knowledge
   about each song used.
<para>
   With two sound devices, there are different ways to mix.
   The first method is to mix the room's sound on one device,
   and use the other channel for previewing new tracks, setting
   up loops and sequences, etc.  Streams are output to only one
   device, but which device can be switched on the fly.  This 
   allows the user to preview a song playing alongside the current
   mix, then mute it, switch devices, and fade it into the main
   mix.  However, be aware that sound output by the two sound 
   cards will most likely be slightly out of synch.  Thus, one
   will likely use the automatic beatmatching after switching
   devices.
<para>
   An alternate method is use an external, physical mixer to 
   crossfade between two sound cards.  One stream is assigned
   to each device, and new tracks are cued by making one channel
   audible only on the mixers' headphone output.  This allows the
   user to adjust the speed and position of each stream until
   they play in synch, and then bring up the room volume of the
   new channel.  Thus, songs can be beatmatched by hand,
   as with a standard dj turntable setup.  A benefit of this
   method is that beat info isn't required to get a clean 
   mix.  If beatinfo is know, it can be used to automatically
   beatmatch songs across devices.  However, the sound output
   by the two sound cards will likely be slightly out of synch,
   so the user will most likely need to nudge it slightly for
   perfect alignment.
<para>
   There is a further phase of device usage which we are working
   towards.  In this next stage, any stream can be output to multiple
   devices, with different volumes.  This will allow the user to 
   preview a copy of the room mix with a new stream audible only 
   to him.  This full cueing capability will allow beatmatching by 
   hand without an external mixer.
</para>
</answer>
</qandaentry>
</qandadiv>

<qandadiv>
<para>
<bridgehead id="q3" renderas=sect1>
How does the beat synching work?
</bridgehead>
<qandaentry>
<question> 
<para> How does the beat synching work? </para>
</question>
<answer>
<para>
   In short, beat synching works by relying on information about
   songs read from a database to automatically match the tempo and
   phase of multiple streams.  This information must be determined
   by a person at some point, probably using tools provided with
   gdam.  Beat synching is optional, to provide users instant, 
   perfect control over their favorite songs.  see doc/beatmatching.txt 
   for more information.
</para>
</answer>
</qandaentry>
</qandadiv>


<qandadiv>
<para>
<bridgehead id="q4" renderas=sect1>
Can it automatically determine the beat?
</bridgehead>
<qandaentry>
<question> 
<para> Can it automatically determine the beat? </para>
</question>
<answer>
<para>
   No, we've never found an algorithm that was
   fast and accurate enough.  We have a link to a paper by 
   Eric Scheirer which is about the best starting point we've found...
   See gdam.org.
</para>
</answer>
</qandaentry>
</qandadiv>



<qandadiv>
<para>
<bridgehead id="q5" renderas=sect1>
Why are labels/tooltips blank or redrawn improperly?
</bridgehead>
<qandaentry>
<question> 
<para> Why are labels/tooltips blank or redrawn improperly?  </para>
</question>
<answer>
<para>
   If the labels are drawing over themselves without
   erasing the old text, or tooltips are popping up without
   text, it is probably because you're using an early, 
   buggy gtk themes package.  Upgrade to the latest gtk 
   packages, see gdam.org for details.
</para>
</answer>
</qandaentry>
</qandadiv>



<qandadiv>
<para>
<bridgehead id="q6" renderas=sect1>
Is there an easy way to remove all sound sources from a device?
</bridgehead>
<qandaentry>
<question> 
<para>  Is there an easy way to remove all sound sources from a device?  </para>
</question>
<answer>
<para>
   Yes. 
   <userinput>gdamcli -e silence</userinput>
   will remove all sources attached 
   to the default sound device.  Other devices can be specified 
   with the <userinput>--device</userinput> flag.
</para>
</answer>
</qandaentry>
</qandadiv>



<qandadiv>
<para>
<bridgehead id="q7" renderas=sect1>
Why is GDAM complaining about not having "Group Audio"? 
</bridgehead>
<qandaentry>
<question> 
<para> Why is GDAM complaining about not having "Group Audio"? </para>
</question>
<answer>
<para>
   In unix, every file and every process is owned by a "user".
   Also, every file is owned by a "group" and every process can
   be a member of a number of groups.  You can use the "groups"
   command to see which groups you are a member of.
<para>
   If you are in the same group or user as a file,
   you can change or destroy that file.  If you are in the same group
   as a process, you can `kill' that process.
<para>
   In order to be more secure, by default, GDAM "drops privileges"
   and runs as user "nobody" and group "audio". 
<para>
   Your system is complaining because you don't have a group "audio".
   It is recommended you add one.
<para>
   To add the group run either (as root):
<screen>
      groupadd audio
</screen>
   or
<screen>
      addgroup audio
</screen>
<para>
   If you do not have either of these commands you should
   consult your system documentation (you may have to edit /etc/group
   manually).
<para>
   You should probably add yourself to group audio:
<screen>
   usermod -G audio your_username
</screen>
<para>
   (You may have to modify /etc/group manually if you don't have that
   program).
<para>
   Finally, make the sound devices accessible to group audio:
<screen>
      chgrp audio /dev/dsp*
      chmod g+rw /dev/dsp*
</screen>
<para>
   This should help gdam run securely, even if you start it as root.
</para>
</answer>
</qandaentry>
</qandadiv>


<qandadiv>
<para>
<bridgehead id="q8" renderas=sect1>
Why is GDAM complaining about "DeviceAlias"?
</bridgehead>
<qandaentry>
<question> 
<para> Why is GDAM complaining about "DeviceAlias"? </para>
</question>
<answer>
<para>
   This is left over from an old feature.  Remove all 'DeviceAlias'
   lines from your server config file.
</para>
</answer>
</qandaentry>
</qandadiv>


<qandadiv>
<para>
<bridgehead id="q9" renderas=sect1>
Why isn't my favorite filter/component available anymore?
</bridgehead>
<qandaentry>
<question> 
<para> Why isn't my favorite filter/component available anymore? </para>
</question>
<answer>
<para>
   Try running gdam-launcher with the "--define unstable" flag.  Features
   which are under development, or have been found to be buggy, are marked 
   unstable and require this flag to be available.  Please note that if you
   define "unstable" at startup, gdam-launcher may make horrid sounds or
   seg fault.

</para>
</answer>
</qandaentry>
</qandadiv>



<qandadiv>
<para>
<bridgehead id="q10" renderas=sect1>
How can I get low latency sound without dropouts?
</bridgehead>
<qandaentry>
<question> 
<para> How can I get low latency sound without dropouts?  </para>
</question>
<answer>
<para>
 GDAM opens each sound device with an output buffer.  The larger the output
 buffer, the greater the latency between pressing a button and hearing the
 result.  A smaller output buffer gives a more responive system, but is more
 likely to suffer dropouts when the processor is busy.  The goal is to find
 a buffer size small enough to feel responsive, but large enough to avoid
 dropouts under normal use.
<para>
 The <filename>server.config</filename> file lists the amount of buffer 
 each sound device will be opened with.  The amount is given as a
 number of memory fragments, and the log of the fragment size.  Three
 fragments of base twelve corresponds to 70 milliseconds:
<para>
 <screen>
 Message: Set soundcard fragments:  3 frags of 4096 bytes; 0.070s
 </screen>
<para>
 If the server is feeding several sound cards, it may have trouble
 keeping up with small buffers.
<para>
 Running the server as root allows it to run at a high priority, 
 decreasing the likelihood of dropouts.  If you don't run the server
 as root, use a root shell to nice it to -20.  This will help prevent
 other programs from competing for processor time.
<para>
 A few boot-time options and system tunings can be helpful.  Try passing
 your kernel the 'no-hlt' option at boot.  Use hdparm to tune your
 hard drives, enabling 32-bit transfers and turning on DMA.  
<para>
 Certain hardware can occupy the kernel for long amounts of time, making
 low-latency sound impossible.  When i had an old pci video card, i had
 to keep the soundcard output buffer at 140ms or greater to avoid dropouts.
 After replacing it with a new agp video card, i was able to reduce the
 output buffer to 17ms.  I've read that some ps2 mice can occupy the kernel
 for up to 50ms, but mine doesn't seem to do so.
<para>
 Low-latency advocates have developed patches for the linux kernel
 designed to improve low-latency performance.  If you are using a 2.2 
 kernel, try patching with mingo's low-latency patches.  If you are using 
 a 2.4 test kernel, try looking for the appropriate patches on the 
 linux-kernel mailing list.
<para>
 For more information see 
  <ulink url="http://www.crosswinds.net/~linuxmusic/lowlatency.html">
  the low latency mini-howto</ulink> and the 
  <ulink url="http://chandra.ph1.uni-koeln.de/linux/HOWTO/Audio-Quality-HOWTO.html">
  linux audio quality howto</ulink>.
</para>
</answer>
</qandaentry>
</qandadiv>


<qandadiv>
<para>
<bridgehead id="q11" renderas=sect1>
I'd like to put two sound cards in my linux system.
</bridgehead>
<qandaentry>
<question> 
<para>  I'd like to put two sound cards in my linux system. </para>
</question>
<answer>
<para>
   With the standard kernel code, this can be tricky.  You'll
   probably compile sound support as modules, and insert the
   cards one at a time with any necessary parameters.
<para>
   With the commercial OSS drivers from
   <ulink url="http://www.opensound.com/">4front technology</ulink>,
   I had no problem getting several cards to work at once.  Their
   configuration utility autodetected and installed all three
   of my sound cards.  Many cheap and a few professional cards are
   supported.  A basic license costs $20, certain cards require
   more expensive options.
<para>
   <ulink url="http://alsa-project.org/">The ALSA project</ulink> has
   developed a free set of drivers meant as a powerful alternative to the 
   standard kernel drivers.  Many cards are supported, and the system is
   designed to support multiple cards without conflict.  
<para>
   An alternative to multiple sound cards is a multi-channel sound
   card.  I get great performance from my Trident 4DWave sound card,
   which features seperate front and rear stereo outputs.  A benefit
   to a card like this is that the timing of two channels, and the
   devices which feed them, is identical... they will not drift
   or be read from at different times.  One aspect of using this
   card is that i have to adjust the front and rear volumes of
   my sound devices by hand each time i restart the gdam server.
</para>
</answer>
</qandaentry>
</qandadiv>

<qandadiv>
<para>
<bridgehead id="q12" renderas=sect1>
I'd like to use the front and rear outputs of my four-channel soundcard.
</bridgehead>
<qandaentry>
<question> 
<para>  I'd like to use the front and rear outputs of my four-channel soundcard.  </para>
</question>
<answer>
<para>
   Those with SoundBlaster Live or Trident 4DWave cards can use your
   rear output for an independent cue channel.  Currently This is only 
   possible with ALSA drivers.  See "Supporting Four-Channel Soundcards 
   In GDAM" in the user manual.
</para>
</answer>
</qandaentry>
</qandadiv>


<qandadiv>
<para>
<bridgehead id="q13" renderas=sect1>
Why don't I see MIDI control buttons in my filters?
</bridgehead>
<qandaentry>
<question> 
<para>  Why don't I see MIDI control buttons in my filters?  </para>
</question>
<answer>
<para>
   To keep things simple for users without midi devices, filters will be
   created without midi-related buttons unless the Midi Selector has
   been opened.
</para>
</answer>
</qandaentry>
</qandadiv>

<qandadiv>
<para>
<bridgehead id="q14" renderas=sect1>
I only have one sound card.  Can use the left channel for the main mix and
the right channel for cueing?
</bridgehead>
<qandaentry>
<question> 
<para> I only have one sound card.  Can use the left channel for the main mix and the right channel for cueing?  </para>
</question>
<answer>
<para>
   With gdam-0.938 and later, try <command>gdam-launcher --define mono_cue</command>   
   The usual device-switching controls will move sources between
   the left and right channels.
</para>
</answer>
</qandaentry>
</qandadiv>


<qandadiv>
<para>
<bridgehead id="q15" renderas=sect1>
GDAM is too confusing!
</bridgehead>
<qandaentry>
<question> 
<para> GDAM is too confusing!  </para>
</question>
<answer>
<para>
   With gdam-0.938 and later, try <command>gdam-launcher --define simple</command>   Advanced and uncommon controls will be hidden.
 
</para>
</answer>
</qandaentry>
</qandadiv>



<qandadiv>
<para>
<bridgehead id="q15" renderas=sect1>
How can i exactly match tempos?
</bridgehead>
<qandaentry>
<question> 
<para>How can i exactly match tempos?</para>
</question>
<answer>
<para>
Most tempo displays are drag-n-drop sources and destinations.  Use the
right mouse button to drag the desired tempo onto a tempo of a different value.
The destination will change its resample rate to match the dropped value.
Alternately, double-clicking a tempo label will match the tempo of
the anchored turntable.
</para>
</answer>
</qandaentry>
</qandadiv>





</qandaset>
</appendix>




<appendix id="troubleshooting"><title>Troubleshooting</title>

<sect1><title>Common Problems and Solutions</title>

<sect2><title>GDAM Won't Compile?</title>
<para>
if it complains thusly:
<screen>
      /usr/lib/libglade.so: undefined reference to `xmlSAXUserParseFile'
      /usr/lib/libglade.so: undefined reference to `xmlSAXUserParseMemory'
      collect2: ld returned 1 exit status
</screen>

then you are most likely using libglade-0.11 with an old libxml.
try the packages from our web page, or the most recent version.
</para>

<sect2><title>GDAM seg faults?</title>
<para>
run it in debug mode, (the <option>--debug</option> flag does this) with a 
large terminal history.  page up to find the first of the spewage.
</para>

<itemizedlist>
<listitem><para>If you get messages like "error, placeholder in xml file"
trying upgrading to libglade 0.11 or higher
</para> </listitem>

<listitem><para>If you get invalid casts to GDAM types... 
then maybe you aren't linking with the most recent version of the
libraries; then perhaps you haven't made clean.  or, if you have 
installed an earlier version of gdam, the libraries may be hanging around
on your system causing conflicts.  Try removing 
<filename>/usr/local/lib/libgdam*</filename>.
and remaking.  If you make often in <filename>/home/joe/gdam/</filename>,
and run 
<command>/home/joe/gdam/server/gdam-server</command>,
then add <filename>/home/joe/gdam/lib</filename> to your
<envar>LD_LIBRARY_PATH</envar> to ensure you always link with the correct version.
<userinput>echo $LD_LIBRARY_PATH</userinput> and make sure
that no other libgdam binaries will 
be found before the correct one.
</para></listitem>

<listitem><para>If  gdam seg faults when creating skin, and the above does not 
      help, perhaps libglade doesn't work on your machine.  try compiling
      the libglade demo program:
<screen>
      % cp /usr/doc/libglade-devel-0.11/examples/test-libglade.c .
      # edit test-libglade.c to delete the line
	    #include &lt;config.h&gt;
	    (line 44)
      % gcc -o test test.c `libglade-config --libs --cflags`
      % cp /usr/doc/libglade-devel-0.11/examples/test.glade .
      % ./test test.glade
</screen>
if it seg faults, then libglade is unstable
for you.  sorry.  look for a newer version.
</para></listitem>
</itemizedlist>


<sect2><title>GDAM Server Stalls on Play?</title>
<para>
If clients can connect to the server, but position indicators
stay at <GuiLabel>0:00</GuiLabel>, try adding the 
<userinput>fork</userinput> option to the appropriate device in your 
<filename>server.config</filename> file.  Buggy drivers may require 
this option.  Also, run <command>/sbin/ifconfig</command> and make sure
you have an interface for localhost.
</para>


<sect2><title>GDAM Outputs Loud Static?</title>
<para>
If <command>gdam-server</command> outputs loud static, perhaps the
sound card requires that the byte ordering be switched.  On some
mac notebooks, this is the case.  Add the 
<userinput>wrong_endian</userinput> flag to the appropriate 
device in your <filename>server.config</filename> file.
</para>


<sect2><title>GDAM Can't Load Plugins?</title>
<para>
again, check that your <envar>LD_LIBRARY_PATH</envar> is correct.  Also, make sure that
you aren't accidentally running old gdam libraries.  Previous versions
installed binaries in <filename>/usr/bin</filename>.
These are no longer useful, and should
be removed.  In debugging mode, gdam will note each attempt to open a
plugin module, and the manner in which each failed to load.  Perhaps
you will find a message about a permissions problem, an unresolved
symbol in the module, or see that gdam isn't looking any place where
your modules have been installed.  Cut and paste relevant information
into mail to the gdam-user list or one of the authors for help.
</para>

<sect2><title>Executable and Plugin Versions Dont Match?</title>
<para>
GDAM plugins are compiled with version numbers, and these version
numbers are checked when plugins are loaded.  If the plugin's version
doesn't match the executables, GDAM will complain as follows:
<screen>
** WARNING **: the module gdamspin.c is compiled for version 0.930; 
			but lt-gdam-launcher is compiled for 0.929
</screen>
<para>
If you have been compiling from a copy of the CVS source, it is possible
that the release number has changed, but the plugins haven't needed
recompiling.  In this case, the warning is nothing to worry about,
and making clean will ensure all plugins have the same version number.
If this is not the case, then you're probably loading old plugins which
wont work properly and might crash.  Again, check that your 
<envar>PATH</envar> and <envar>LD_LIBRARY_PATH</envar> don't point
to old executables , libraries, or plugins.
</para>

<sect1 id="reportingproblems"><title>Reporting Problems</title>
<para>
If you continue to have trouble getting GDAM to run, please email
the authors.  Include details on which release, whether it was precompiled
or a source distribution, if you use OSS or native ALSA, and 
the results of running the program(s) with the <option>--debug</option> flag.
We'll attempt to explain the problem, and/or fix it in future releases.
</para>

</appendix>






<appendix id="gdamsecurity"><title>GDAM's Security Model</title>
<para>
  Security of your system is very important.
  GDAM grants permission to many resources:
  it uses memory, disk, cpu and sound devices.
</para>
<para>
  We've added a feature to let you connect to
  the server without listening on any port;
  this happens automatically if you run
  <command>gdam-launcher</command> when no
  server is running.  This is a relatively
  safe mode of operation.
<para>
  Currently there are few checks in place for
  attacks based on using up all available
  memory, disk or cpu.  If you care, use
  ulimit or nice to change the amount of resources
  gdam has available to it.
</para>

<para>
  However we've attempted to limit control in two ways:
  <itemizedlist>
    <listitem>
      <para>
	the authenticator - this grants access to a user
	for certain priviledges
      </para>
      <para>
	currently we don't have a useful authenticator
	in GDAM.  If you want to help us write one,
	please contact us.
      </para>
    </listitem>
    <listitem>
      <para>
	access to the users system is available by:
	querying and reading files, writing to the disk,
	reading and writing from sound devices,
	loading plugins in the plugin directories,
	potentially unlimited use of cpu and memory.
      </para>
    </listitem>
  </itemizedlist>
</para>
<para>
So how do you make a gdam-server fairly secure?
</para>

<para>
  <itemizedlist>
    <listitem>
      <para>
	set the user to nobody and the group to audio.
     </para>
    </listitem>
  </itemizedlist>
</para>
<para>
  <itemizedlist>
    <listitem>
     <para>
       make your audio devices readable or writable
       by group audio 
       (<userinput>chgrp audio /dev/dsp*; chgrp audio /dev/dsp*</userinput>),
       and <emphasis>not</emphasis>
       by the anonymous user (<userinput>chmod o-rwx /dev/dsp*</userinput>).
     </para>
    </listitem>
  </itemizedlist>
</para>

<sect1>
<title>
  Root and Realtime
</title>
  <para>
    <itemizedlist>
      <listitem>
	<para>
	  Running <command>gdam-server</command> as root
	  allows you to run it in <option>--realtime</option>
	  mode.  This allows gdam to consume <emphasis>all</emphasis>
	  the resources on your computer, and potentially get
	  very low latency in conjunction with the
	  <option>numfragments=</option> and <option>logfragsize=</option>
	  server config options.
	</para>
      </listitem>
    </itemizedlist>
  <para>
    <itemizedlist>
      <listitem>
	<para>
	  gdam will drop permissions when run as root,
	  but in still runs realtime.  this means it can entirely
	  crash your computer if it gets confused or too
	  far behind.  we recommend running non-realtime mode
	  (or maybe just increasing the priority using 
	  <command>renice</command>).
	</para>
      </listitem>
    </itemizedlist>
  </para>

</book>
