So you're feeling a bit overwhelmed!  MIDI has a lot of powerful
features, and so MSE needs a lot of powerful commands to access
everything that MIDI is capable of doing.  It's true this can be a bit
overwhelming.  This tutorial will hopefully ease you into the process of
defining MSE modules.

In the following tutorial you do not need to actually create a
definition file, we have already included them to save you the time.
Use them for reference as you proceed through the tutorial, if
necessary.  They are a good guide for proper stucture and ordering.


 1: First things first
=======================

The first step is to name our module.  Normally, you would name the
module according to the device you wanted it to control.  Let's call it
"Tutorial1".

General information about a module is defined with the command structure
'Define Device'.  It has two required parameters: 'Manufacturer' and
'Device'.  We will use these two parameters to name our module.  Here is
how it would look:

  Define Device (
    Manufacturer "Test"
    Device "Tutorial1"
  )

Notice the brackets that enclose the 'Define Device' structure.  Several
commands have parameters with the same name, such as 'Position'.  These
brackets ensure that the compiler can tell where one command ends and the
next one begins.  Brackets must always appear in pairs '(' for starting
(opening) and ')' for ending (closing) a structure.  We have also
indented the two parameters, so that it is easier to see that they are
part of the 'Define Device' structure.

Now we need to tell the compiler what fonts we want to use in this
module.  We just need one right now.  The compiler also needs to know how
we want to refer to this font later, we will just use the label "Font1".
We want to use the Topaz2 font with a size of 8.  Here is how it would
look:

  Define Font "Font1" (
    Name "Topaz2.font"
    Size 8
  )

'Define Font' has two requirements, a label "Font1" and the 'Name'
parameter.  The 'Size' parameter is actually optional.  The compiler will
default to a size of 8 if it is not told specifically to use a different
size.  We have included it here to make things more understandable.

The next thing to do is to define a window for our gadgets and text to
appear in.  Windows are defined like this:

  Define Window "Main" (
    Position 10 20
    Size 400 200
    Border
  )

We have given this one the label "Main", so that we can refer to it
later.  The two required parameters, 'Position' and 'Size' tell the
compiler where we want the window to appear on the screen.  In this case,
the upper left hand corner of the window should be at the coordinates:
x=10, y=20 and it should be 400 pixels wide and 200 pixels tall.  The
optional parameter 'Border' indicates that we want the window to have a
border drawn around it.

Finally, we need to reference the defined window or the compiler will
complain that it hasn't been used.  For now, we will just use an empty
window structure which we will explain later.

  Window "Main" (
  )



 2: Compiling a module
=======================

At this point, we have enough information to compile a module.  We have
included the file "Test/Tutorial1-A.def" which includes the commands we
have used so far.

Start the compiler by double clicking the "MSE-Compiler" icon.  When you
are prompted with the file requester, enter the "Test" directory and
select the file "Tutorial1-A.def".

Once you have selected the definition file to be compiled the compiler
begins its job.  This is not a very big definition yet, so you likely
will not get to see any of the information the compiler displays as it
compiles.  Basically, all you missed is the compiler counting lines,
fonts, windows, etc.  If there had been any errors, the compiler would
have told you and stopped.  Note that you do not have to quit the
compiler, it quits when it is finished.


 3: Viewing the module
=======================

In that couple of seconds the compiler generated our tutorial module.
Let's have a look and see what we have so far.  Start "MSE" by clicking on
its icon.  When you are prompted with the file requester, enter the "Test"
directory and select the file "Tutorial1.mse".  MSE will load the module
and display the defined window.  Our module does not do anything yet, so
enjoy the little bordered window and then quit MSE.


 4: Displaying text
====================

We have not used the font we defined, so let's dislay some text with it.
First, we need to the tell the compiler what window we want to display
the text in.  All of the commands that apply to windows, 'Text', 'Gadget',
'Border', etc. are contained within a window structure.  Simply, a window
structure looks like this:

  Window "Main" (
  )

That will not actually do anything on its own.  It simply tells the
compiler which window we are going to work with.  We need to put
something inside that structure for it to be of any real use.

  Window "Main" (
    Text "ABCDEFGHIJK" (
      Position 10 15
    )
  )

The text command has two required parameters: a text string and a
'Position'.  Here we have told the compiler to place the text
"ABCDEFGHIJK" at x=10, y=15.  'x' refers to the left edge of the text and
'y' refers to the baseline of the font.  The baseline is the point at
which a letter meets the ground, so to speak.  Letters such as
"abcdefhiklmnorstuvwxz" all sit on the baseline.  But "gjpqy" have
descenders, which drop below the baseline.  With a standard size 8 font
you have something like this:

      01234567     01234567

    0 **         0
    1 **         1
    2 ******     2 **    **
    3 **   **    3  **  **
    4 **   **    4   ****
    5 **   **    5    **
    6 o*****     6 o  **
    7            7  ***

Where the baseline is at row 6.  When defining the position text, you
have to keep the baseline in mind when indicating coordinates.  If you
wanted the upper left hand corner of the letter 'b' to appear at x=5,
y=10 you would use 'Position 5 16'.  In the above examples, 'o' indicates
the point at which coordinates refer (at 0,6).


We will display two different texts in our previously defined window:

  Window "Main" (
    Text "Plain Text" (
      Position 20 25
    )
    Text "Shadow Text" (
      Position 20 40
      Color 2
      Shadow
    )
  )


Refer to MSE-Compiler.guide for more information about the extra
parameters, 'Color' and 'Shadow', used here and others that can also be
used.

Compile "Test/Tutorial1-B.def" and open the 'Tutorial1.mse' module in MSE
to see the results.


 4: Adding borders
===================

Let's make things a little prettier and add a border around the text.
Note that the Border option in 'Define Window' is actually a quick form
of this command.  When used in 'Define Window', the 'Position' and 'Size'
are determined by the size of the window and no other options are
allowed.  The 'Border' command allows some additional features.  Borders
are defined like this:

  Border (
    Position 10 10
    Size 107 40
    Fill 3
  )

Remember that, although we have not shown it this way, this command and
others like it must be contained within a 'Window' structure.

The 'Position' parameter, as with 'Define Window', refers to the
coordinates of the upper left hand corner of the border.  Again, 'Size'
refers to the width and height in pixels.  Note that there is an
alternative to using the 'Size' command anywhere it is used.  'Position2'
sets the position of the lower right hand corner.  In the above example,
we could have used 'Position2 117 50' instead of 'Size 107 40' and would
have gotten the same result.  When using a paint program to do intial
layout designs, the 'Position2' alternative can save you some calculation
since most paint programs only give x/y coordinates.

The 'Fill' option tells the compiler that we want the border filled with
color 3.  It is important to realize that sometimes the order that
commands appear within the definition file needs to be considered.  If we
added this 'Border' definition in AFTER the 'Text' commands, the text
would be overdrawn by the fill option we have used.  Because we want the
text to appear over the filled border, we have to order it BEFORE.
Something like this:

  Window "Main" (
    Border (
      Position 10 10
      Size 107 40
      Fill 3
    )
    Text "Plain Text" (
      Position 20 25
    )
    Text "Shadow Text" (
      Position 20 40
      Color 2
      Shadow
    )
  )

Compile "Test/Tutorial1-C.def" and open the 'Tutorial1.mse' module in MSE
to see the results.


 5: Adding gadgets
===================

To interact with MSE we have to add gadgets.  Although MSE supports
several different kinds, we will begin with a simple slider gadget
example:

  Gadget "Notes" (
    Position 140 140
    Type Slider (
      Range 0 127
      Size 100 10
      Direction HORIZONTAL
    )
  )

This defines a gadget with the label "Notes".  Currently, gadget labels
are not used but because future features will need them, they are
required.  The gadget command has two additional required parameters:
'Position' and 'Type'.  As with other commands, 'Position' defines the
upper left hand coordinate of the gadget.  'Type' is used to define the
kind of gadget and its parameters.  Note that 'Type' is also a structure
imbedded (or nested) within the Gadget command with its own structure
bracketing pair.

The 'Type Slider' structure has three required parameters.  'Range' sets
the minimum and maximum values for the gadget.  'Size' sets the width
(100) and height (10) of the gadget.  'Direction' determines the
orientation of the gadget.

Note that 'Gadget' is a window command and like others must be placed
within a window structure.

Compile "Test/Tutorial1-D.def" and open the 'Tutorial1.mse' module in MSE
to see the results.


 6: Displaying gadget values
=============================

Our gadget does not do much, yet.  Let's enhance it a little by adding a
couple optional parameters to the 'Type Slider' structure:

      LevelPlace ABOVE
      Default 63

This tells the compiler that we want the value (or level) of the gadget
to be displayed above the gadget and that we what the gadget's intial
level to be set at 63.  Once an editor contains midi patch data, the
'Default' value can usually be determined from the default patch data, so
this parameter would normally not be included.  If it was, it would
override the value contained in the patch data.  This is not what we
normally want to happen.

Note that different gadget types have different parameters, they can not
be interchanged.

We would like to see some text to remind us what the gadget is for, so we
have also added a new 'Text' structure.

  Text "Note #" (
    Position 167 159
    Color 3
  )

Compile "Test/Tutorial1-E.def" and open the 'Tutorial1.mse' module in MSE
to see the results.


 7: Understanding how MSE handles MIDI
=======================================

Our module is not very useful, yet.  Let's teach it about MIDI.  For this
example, we will use a feature of MIDI that will work with almost any
MIDI sound module... note playing.  This is not a great application of
MSE but is easy enough to get started.

The are several parts to defining MIDI information.  First, the compiler
needs to know what MIDI channel the device is operating on and where it
should send the MIDI data.  These parameters should be included within
the 'Define Device' structure.

    Channel 1
    Handler MIDI

This tells the compiler to use the public domain MIDI.library for
controlling your MIDI devices.  If you do not have it installed, install
it in your LIBS: directory now -OR- consult the MSE-Compiler.guide for
other 'Handler' options.  If the device you want to control is set to a
channel other than 1 or OMNI, this should be changed too.

Secondly, we need to tell the compiler what the MIDI message looks like.
This is done with the 'Define Midi' command.  The MIDI specification
defines the note message as such:

  $9n ## vv

  where:   n = MIDI Channel (0-15)
          vv = velocity (NOTE ON vv = 1-127, NOTE OFF vv = 0)

In midi communication, channels are numbered 0-15 not 1-16 like we
usually see them displayed.

For this message, channels work like this: A value of $90 represents MIDI
Channel 1, $91 = 2, $92 = 3, ... $9F = 16.  If we ALWAYS wanted to use
channel 5 here we could use $94.  However, one of the features of MSE is
the ability to override the channel at anytime.  If we force this to be
$94, that feature will not work with this module.  For now we will use
$90 and add the channel # to it later.  Technically we are still forcing
this message to use channel 1, but this will make more sense later, when
we discuss this further.

For now, let's not concern ourselves with the velocity.  Instead we will
force it to 64.

Here, we will actually define two note messages: NOTE ON followed by NOTE
OFF.  As far as MIDI is concerned, this is not greatly useful, but serves
this tutorial purpose.

In the MSE definition language the message can be defined like this:

  Define Midi "Notes" (
    Data (
      $90  '            0 = Offset
      Byte 'Note #      1
      64   'Velocity    2
    )
  )

* The apostrophe is a special marker that can be used to tell the
  compiler that we are just making a note to ourselves.  When the
  compiler encounters this character, it ignores everything on the
  remainder of that line.

* As with other commands, '"Notes"' is simply a label for later
  referencing of this definition.

* 'Byte' as used here, serves only as a place holder.  The compiler
  actually stores this as 0 when it creates the module.  More
  importantly, it serves as a reminder to us that these are values that
  need to be inserted later.  You can put anything you want here, really,
  because it will be overwritten anyway.

So, now that we have the general structure of the message defined, we
need to consider how the missing values get put into the message.  A
couple things are still missing: Midi Channel and Note #.

We will use the slider gadget we defined previously to control the Note
#.  So we will handle that later.

'Define Midi' has a special parameter, 'Midi', that is used to tell the
compiler what values need to be inserted in the midi message before it
gets sent.  This is a good place to tell it about the Midi Channel.

We will use this feature to tell the compiler where in the message the
channel is to be stored, so that MSE can change it when we want it to.
Because we are sending two note message, we actually need to store it in
two places.  This parameter needs to be added to the already defined
'Define Midi' structure.

  Midi (
    Data (
      0 CHANNEL
    )
  )

* '0' represents a byte offset from the beginning of the message.
  Refer back to the definition.

* 'CHANNEL' is a special indicator to MSE that we want to add the current
  MIDI channel number to the value at the given offset.  Remember that we
  initialized this value to $90.  so, if the current channel was 5,
  $90 + 4 (remember channels are numbered 0-15) would be $94.


 8: Making gadgets send midi data
==================================

Now that we have told the compiler about the midi messages that we want
to use, it's time to tell our previously defined slider gadget about it.

Though, the MIDI note message supports a range of 128 notes, most sound
modules do not.  So, our gadget has too large a range.  We need to change
that first.

      Range 36 96

The 'Default' setting and and other parameters are okay the way they are.

The gadget command also has a 'Midi' parameter, similar to the one used
with 'Define Midi' but much more powerful.  There are some differences,
see the MSE-Compiler.guide for more details.

  Midi "Notes" (
    Data (
      1 VALUE Byte
    )
    Send
  )

* Here's where the label we defined earlier with 'Define Midi' comes in
  handy.  We use it to reference the already defined message.

* '1' represents a byte offset from the beginning of the message.

* 'VALUE' is a special indicator to MSE that we want to store the current
  value of the gadget.

* 'Byte' tells MSE how the value should be stored.  This is the normal
  method of storage, and the simplest.

* 'Send' is an option that tells MSE that it should send the midi
  message. If you do not include this, MSE will construct the midi
  message but will not send it.  Why doesn't MSE just send the message
  all the time?  Sometimes it is necessary to maintain several messages
  simultaneously and it is not necessary to send both so 'Send' is an
  option.


 9: Hearing the results
========================

Compile "Test/Tutorial1-F.def" and open the 'Tutorial1.mse' module in MSE
to see the results.  Visually, everything should look the same as the
last time.

However, if everything is properly connected to your sound module, when
you change the slider value, you should hear notes play.

Because we have not sent a note off message, the sound will play forever.
