$Id: PORTING,v 1.6 89/05/06 17:13:07 lee Exp $
[Lee:]

The C source code for the various synth modules is generated by
a program 'menutoc'.  Although C source for 'menutoc' is included,
revising the program would require flex, the freely distributed "fast
lex" to compile.  But if you happen not to have flex, lex will serve --
see the note in the Makefile and notes at the beginning of file
makemenu.l.

	---------------------------------
[Kesti:]

In order to adapt it to the D-10's rather large data set, I have used glib's
ability to service multiple synths to instead service sub-sections of a single
D-10.  These subsections are:

	Performance mode patches
	Multi-timbral mode timbres

	Tone waveform generators
	Tone time variant filters
	Tone time variant amplifiers

	Rhythm setup
	Rhythm patterns
	Rhythm track

Because the memory requirement of a single program to service this much data
is large enough to be cumbersome, I have broken the subsections into three
separate programs.  These are d10patch, d10tone, and d10drum.

The tone services also require a separate program because, unlike all other
services, they must operate on a single common data set.  This required
changes to the data memory allocation and other functions in glib.c.  When
compiling d10tone, be sure to #define SINGLEDATA in glib.c to enable these
changes.

I believe that I have maintained glib's ability to be compiled for Un*x
(using SysV curses), DOS, and the Atari ST.  The sources supplied have
been succesfully compiled and run on an AT&T 3b1, running v3.51 software;
and an AT&T 6300 (with a V30 in the cpu socket), running AT&T's version of
DOS v3.20.  Borland Turbo C v1.0 was used to produce the executables and the
machine was fitted with a CMS-401 interface.

The Makefile provided was used on the 3b1, and produces a single executable
named glib that combines all services, but does not tie the tone data
together as discussed above.  This is presumably no problem, as the Un*x
version is intended to be for demo purposes.  If your Un*x machine has a
midi interface, I'd like hear from you!

The Turbo C project files (*.prj) are used by the integrated environment to
produce glib.exe, d10patch.exe, d10tone.exe, and d10drum.exe.  Be sure to
use the large memory model.  It is not recommended that glib.exe be used, as
it requires almost all the available memory of a 640K machine, and again,
would not tie the tone data together (SINGLEDATA should not be #defined
when compiling for glib.exe.).

[Lee:]

I did not include the .prj files mentioned above.  So many files
already!  But below are the contents of those files.  The file machdep.c
is a copy of pc-mach.c (and pc-mach.h should be copied to machdep.h);
the d10*.c files except d10ton.c) must be constructed from the
corresponding d10*.mnu files by the menutoc program; and the files
listdrum.c, listpat.c, and listton.c are the same as file list.c, but
with '#defines' removed for the unused modules.  That is to say, for the
D10 '#defines', keep only
	#define D10urp
	#define D10rsu
	#define D10tra
for listdrum.c, keep only
	#define D10pat
	#define D10tim
for listpat.c, and keep only
	#define D10wfg
	#define D10tvf
	#define D10tva
for listton.c.
::::::::::::::
contents of file d10drum.prj
::::::::::::::
d10urp.c
d10rsu.c
d10tra.c
glib.c
listdrum.c
vis.c
machdep.c
::::::::::::::
contents of file d10patch.prj
::::::::::::::
d10pat.c
d10tim.c
glib.c
listpat.c
vis.c
machdep.c
::::::::::::::
contents of file d10tone.prj
::::::::::::::
d10ton.c
d10wfg.c
d10tvf.c
d10tva.c
glib.c
listtone.c
vis.c
machdep.c
::::::::::::::
contents of file glib.prj
::::::::::::::
d10pat.c
d10tim.c
d10wfg.c
d10ton.c
d10tvf.c
d10tva.c
d10urp.c
d10rsu.c
d10tra.c
glib.c
list.c
vis.c
machdep.c
----------------------


[Thompson:]

Compiling
---------
machdep.c and machdep.h are machine-dependent parts.  The *-mach.h and
*-mach.c files are the versions of these files for different machines,
e.g. unix-mach.[ch] is for UNIX, st-mach.[ch] is for the Atari ST.
Copy the proper files to machdep.c and machdep.h before compiling
for a particular machine.   For example, on UNIX, do the following:

	cp unix-mach.c machdep.c
	cp unix-mach.h machdep.h
	make glib

The contents of list.c control which synths are supported; modify
the defines at the beginning of that file appropriately.  When
compiling, you need to include glib.c and the appropriate synth
files (e.g. if you define DW8000 in list.c, then you need to compile
with dw8000.c).  A single version of glib can support as many synths
as you want, although some compilers may have size limitations or
overlay schemes that get in the way.


Hacking glib - Internals
------------------------
The program is written so that support for a new synth can be added by
adding an entry to the array in list.c, describing the various attributes
of the synthesizer and the C functions to be called to control it.  And, of
course, you have to write those C functions.  Adding a new synth, for a
reasonable C programmer, might be described as mostly straightforward but
tedious.  People other than the original author HAVE done it, with no help.
Glib allows you to re-use the front-end interface of the librarian and
editor, but it does not relieve you of having to write C code which
interacts with the synth (which, depending on the synth, can of course be
easy or maddening) and with the raw data formats.  Naturally, using one of
the existing synth files as an example of how to do things is the best way
to start on a new one.

The 'E' array in list.c has the following structure:

struct editinfo {
	char *ed_name;		/* Synth name */
	struct paraminfo *ed_params;	/* list of parameters */
	struct labelinfo *ed_labels;	/* screen labels in edit mode */
	int ed_nvoices;		/* number of voices */
	int ed_vsize;		/* size of each voice data, in bytes */
	int ed_nsize;		/* name size */
	int ed_dataid;		/* data ID */
	int (*ed_din)();	/* copy voice data into paraminfo array */
	int (*ed_dout)();	/* copy voice data out of paraminfo array */
	int (*ed_sedit)();	/* send 1 voice to synth edit buffer */
	int (*ed_sone)();	/* send 1 voice to a synth (permanent) patch*/
	int (*ed_sbulk)();	/* send bulk voice data */
	int (*ed_gbulk)();	/* get bulk voice data */
	char *(*ed_nof)();	/* get name of a voice out of data */
	int (*ed_snof)();	/* set name of a voice in data */
	char *(*ed_numof)();	/* convert voice number to on-screen text */
	int (*ed_cvtnum)();	/* convert visable voice number to std. format */
};

In glib, there are several relatively independent representations of the
synth voice data.  First, there is the data that is stored in the
library and synth banks (ie.  the data used and manipulated via the
librarian screen).  This is the format of the data that is written to
and read from files (a single byte, given as 'ed_dataid' above, is added
to the beginning of the file, to identify it).  The size of a single
voice in this data is 'ed_vsize'.  The number of voices in a bank is
'ed_nvoices', so the amount of space taken up by a library bank is
ed_vsize * ed_nvoices.

When a voice is edited, the voice data is copied into the parameter
array (see below), in p_val.  The 'ed_din' function is called to do this.
After a voice is edited, 'ed_dout' takes the updated parameter values 
and puts them back into the original data format.  Note that this means
that the bytes in the 'raw' voice data and the values in the parameter
array (ie. the values manipulated by the editor) need not be the same.
There are utility functions 'getval' and 'setval' which should be used
for getting and setting the values in the parameter array.  See dx100.c
for usage.

The ed_sedit, ed_sone, ed_sbulk, and ed_gbulk functions are called to
send voices to and get voices from the synthesizer.  Only one of ed_sone
and ed_sbulk need be defined, although ed_sone should be preferred.
(I had trouble getting the DX100 to accept a single permanent voice
change, so it always does a bulk voice transfer.)  The data passed to
these functions is in the library bank format.  The ed_gbulk function is
optional, so that write-only MIDI devices (like the DEP-5) are allowed.

The ed_nof function is called to pull the voice name out of the raw
voice data (as stored in the library banks), and it should return a
C string containing the name.  The ed_snof function is called to
stick a voice name into the raw voice data.  Note that the 'raw'
library bank voice data does NOT have to match the data that is
really sent to the synthesizer (by the ed_sedit and ed_sone functions).
For example, the DEP-5 does not have names as part of the voice data,
but that does not prevent glib from maintaining and storing (in the files)
voice names.  This holds for the DW-8000 as well.

The ed_numof function is called to convert the voice number to the
text that is displayed on the librarian screen.  This can handle
the odd numbering convention of the DW-8000.  If ed_numof==NULL, the
number is used as-is.  Otherwise, ed_numof is called with the voice
number MINUS 1 (i.e. 0-based); ed_numof should return a string
containing the desired display.  Likewise, the ed_cvtnum function is
used to convert user input from an odd numbering system to the standard
sequential internal representation (0 to whatever).

The editor screen is controlled by two arrays, ed_labels and ed_params.
ed_labels contains arbitrary screen labels, in the following structure:

struct labelinfo {
	int l_row;	/* 0-based */
	int l_col;	/* 0-based */
	char *l_text;
};

The ed_params array is used to specify the parameters that the user can peruse
and change in the edit screen, and looks like this (one for each parameter):

struct paraminfo {
	char *p_name;		/* the parameter name */
	char *p_label;		/* on-screen label (possibly NULL) */
	int p_lrow;		/* position for printing label */
	int p_lcol;
	int p_vrow;		/* position for printing value */
	int p_vcol;
	char *((*p_tovis)());	/* function converts value to on-screen text*/
	int p_min;		/* minimum parameter value */
	int p_max;		/* maximum parameter value */
	int p_val;		/* parameter value */
	int p_flags;		/* flag to enable/disable parameter */
};

The editor calls p_tovis with a parameter value, and expects that function
to pass back a string which contains what should be displayed on the
screen for that value.  Often, this is just an 'sprintf' of the value,
or perhaps the value offset by something.  Or, it could be some text
that represents the value (e.g. "on" for 1 and "off" for 0).  Or, it could
be something more interesting, e.g. a picture of the voice algorithm.
The parameter value strings can make use of cursor motion, by including the
sequences ~d,~u,~l,~r to go down,up,left,right.  The dx100 and dep5 editors
use this to handle the display of the algorithm drawings.

A parameter can be 'disabled' by setting p_flags to non-zero.  The p_tovis
function can set the external variable 'Redraw' to 1 if it wants to force
the entire editor screen to be redrawn (e.g. after a parameter has been
disabled).

Support for a mouse has been added, although it is currently disabled
for the Atari, since I was having various hassles getting it under control.
It did work, but had various quirks.

Mouse support for the Amiga was added, and appears to work after fixing
a few problems in glib.c, so it may be possible to enable the Atari mouse
support now.

                             ...Tim Thompson...twitch!glimmer!tjt...

[notes from Ed Wilts, ewilts%Janus.MtRoyal.AB.CA@Ucnet.UCalgary.CA,
 on the Amiga version for the D-10]

...  The problem I had in getting it
going was more in the execution than the compilation.  Without a sufficiently
large stack, you will get highly intermittent results, and depending on the
state of the moon and the time of day, gurus.  I was getting frequent timeouts
reading from the D-10 and sometimes the data would be all read but not in the
proper order.  I was getting quite frustrated for a while...

My stack was originally 4000 - the default.  I boosted it to 8192 with no
greater results, and finally went to 32768 and now it seems to work.  At least
I can read from the D-10 consistently. ...
