## Lesson files

Some of the exercises in GNU Solfege use data files that contain questions. These data files are called 'lesson files'. The lesson file exercises can easily be extended if the questions supplied with the program does not fit your needs. The following list show the exercises that use lesson files, and also show the name you should use to refer to them when you write lesson files: singanswer, chord, chord-voicing, id-by-name, dictation, sing-chord and harmonic-progression-dictation.

If you want to write lesson files, my advise is to look at the example files in `example-lesson-files/` and some of the files in `lesson-files/` and use this document and the music format spec for reference. You should save your private lesson files in `$HOME/lessonfiles/`. If you save them in `lesson-files/` they might get accidentally deleted when you upgrade the program. To practise your files, you must select them in the "Select lesson file" dialog in the "user" lesson collection. If you think it is difficult to write lesson files using this documentation, you can vent your frustration to the email list solfege-devel@lists.sf.net or on the wiki at www.solfege.org/wiki.

### File encoding

New in version 2.0 is that Solfege by default expect the content of lesson files to be in UTF-8 encoding. gedit is a nice little editor that let you edit unicode files.

If you don't like unicode, you can tell Solfege that the file has another encoding by inserting a special comment line as the first line of the file. The following example set the charset to ISO 8859-1, a charset commonly used in many west-european languages:

    # -*- coding: iso-8859-1 -*-

Russians might want to use koi8-r:

    # -*- coding: koi8-r -*-

The program use the python libs to convert to unicode, so it should understand almost any encoding you can think of. If you see some characters are missing, for example when the name of questions are displayed on buttons, then most likely you have done something wrong with the encoding.

### Lesson file contents

A lesson file consist of a header block and one or more question blocks:

    header {
      ASSIGNMENT
      ASSIGNMENT
      ...
    }
    question {
      ASSIGNMENT
      ...
    }

### Header block

The header block can be placed anywhere in the file, but by convention it should be the first block in the file. If more that one header block is found, for example when using the `include` function, only the first header block is used, the rest are ignored.

Definitions to put in the header block:

`version = STRING`

  Tell the oldest version of solfege the lessonfile is known to work with. For example `version = "1.1.1"` This variable is not required, but it should be used because it can (but don't guarantee to) help avoid trouble if the lesson file format changes in the future.

`title = STRING`

  Short oneline description. You should add this to all lesson files.

`description = STRING`

  Optional, long description that can contain html tags. Use this if you have to describe how the lesson file should be used. The description is read from within Solfege on the "Config" page of an exercise when the user has clicked the button labeled "Details".

`content = LIST`

  A list of all the exercises that can use this lesson file. This variable is requried. Possible values are the names of the lesson file exercises, as documented in the beginning of this file.

  Some lessonfiles can be useful for more than one exercise. For example, a file with chords can also be used by the id-by-name exercise, and should have: `content = chord, id-by-name`

`random_transpose = [key|semitones|accidentals], INTEGER, INTEGER | no | yes`

  In some exercises the program can transpose the music to create variation. The variable is ignored in exercises that does not support transposing.

  `random_transpose = no`

    This is the default value. No transposition will be done.

  `random_transpose = yes`

    The exercise will do random transposition. What kind of transposition depends on the exercise, but you get a ok result from this.

  `random_transpose = accidentals, INTEGER, INTEGER`

    For this transposition mode to work propertly, then music in the lessonfile has to be in the keys c major or a minor, or the question must have a `key` variable like this:

        question {
                 name = "the name"
                 key = "d \major"
                 music = music("\key d \major d' e fis")

    for this to work correctly.

    Transpose the music by random. But make sure the number of flats or sharps are within the range specified by `INTEGER, INTEGER`. To explain how this works, think of flats as negative numbers and sharps as positive numbers. The code

        random_transpose = accidentals, -2, 3

    will give you questions with 1 or 2 flats, 0 accidentals or 1, 2 or 3 sharps. The code

        random_transpose = accidentals, 2, 3

    will create questions with two or three sharps.

  `random_transpose = key, INTEGER1, INTEGER2`

    Transpose the music `INTEGER1` steps down or `INTEGER2 steps` steps up the circle of fifth. (And by my own definition, up is more sharps and down is more flats ... :-) ) This is real transposition where both the key and the notes are transposed.

  `random_transpose = semitones, INTEGER1, INTEGER2`

    Transpose the music at most `INTEGER1` steps down or `INTEGER2` steps down. This is real transposition where both the key and the notes are transposed. You will easily end up with music in the keys with LOTS of accidentals. The code

        random_transpose = semitones, -2, 6

    will transpose the questions no more than 2 semitones down and 6 semitones up. This is the same as the old `random_transpose = INTEGER, INTEGER` syntax.

`labelformat = normal | progression`

  The default value is `normal`. Set to `progression` for lesson files where the name of the questions is a harmonic progression, written in a undocumented, but not difficult format. Check some existing lesson file to see how it works. This variable is ignored by all exercises except id-by-name

`questions_selectable = yes | no`

  Let the user select what questions to be asked from the lesson file. Works for id-by-name and is ignored by the other exercises.

`have_repeat_slowly_button = yes | no`

  Set to `yes` if you want the exercise to have a "Repeat slowly" button. Works for id-by-name and is ignored by the other exercises.

`have_repeat_arpeggio = yes | no`

  Set to `yes` if you want the exercise to have a "Repeat arpeggio" button. Works for singanswer and is ignored by the other exercises.

`have_music_displayer = yes | no`

  Set to `yes` if you want the question to have a music displayer. The program will display the answer in the music displayer when the user gives up or answers correctly. Works for id-by-name and is ignored by the other exercises.

`enable_right_click = yes | no`

  Default value: `yes`. Set to `no` for lesson files where it does not make sense to right click buttons. This variable is recognised by the exercises id-by-name, chord-voicing and chord.

`filldir = horiz | vertic`

  Tell the direction the buttons are filled. Default value is `horiz`. Works for id-by-name and is ignored by the other exercises.

`fillnum = INTEGER`

  Tell how many buttons there are in each row or column. The default value is `1`. Works for id-by-name and is ignored by the other exercises.

### Question block

`name = "some short name"`

  Questions written for id-by-name and chord exercise need a name.

`music = music(MUSICSTRING, MUSICFORMAT)"`

  For most lesson files the music representing the question is assigned to the `music` variable. Note that there is a shortcut. Instead of:

      question {
         name = "Lisa gikk til skolen"
         music = music(...)"
      }

  you can write:

      question {
         name = "Lisa gikk til skolen"
         music(...)
      }

  There is a separate section documenting the `music` object.

`tempo = INTEGER / INTEGER`

  beats per minute / notelen per beat, for example 120/4.

`instrument = STRING, INTEGER`, `instrument = STRING, INTEGER, STRING, INTEGER, STRING, INTEGER`,

  Example:

      instrument = "cello", 100

  The instrument name should be one of those defined in the file soundcard/__init__.py. If you don't enter a complete name, solfege will try to find a matching instrument name. The integer is the velocity of the tones, it should be in the range 0-127. For lesson files where it makes sense, it is possible to specify three set of instruments. The following example will play bass for the lowest tone, piano in the middle and clarinet on the top tone:

      instrument = "bass", 100, "acoustic grand", 100, "clarinet", 100

  Solfege will try to lookup the midi instrument in this order:

  - inside the question block

  - lesson file global variable

  - instrument set in preferences window

#### Question block definitions for the chord exercise

In lesson files that is written to work with `chord` exercise, two more variables can used:

`inversion`

  0 = root position, 1 = first inversion etc.

`toptone`

  1, 3, 5, 7

#### Question block definitions for the dictation exercise

By default, the dictation exercise will show the first column of music, and then the user should write the rest. But if the first column is not good enough, if there for example are only rests on the first beat, these two variables can tell the program how much music to display:

`clue_end = nn/dd`

  `clue_end=1/4` will display all music in the first quarter note.

`clue_music = MUSIC`

  Write the exact music you want to display. If for example you want to display the whoe bar in the upper staff, and only one note in the lower staff.

(Use only one if these variables in a question. Using both are undefined.)

#### Question block definitions for the sing-chord exercise

Questions for this exercise need to have the `key` variable set if the key signature is anything else than c major (or a minor). Example:

    question { "c''|e'|g|c" }
    question { "a'|e'|c'|a" }
    question { key="d \major" "a'|fis'|d'|d"}
    question { key="f \minor" "as'|f'|c'|f"}

### `music` objects

Synopsis: `music(MUSICCODE, MUSICTYPE=normal)`. The default value for `MUSICTYPE` is `normal`, so you only have to specify it for other music types.

Available musictypes:

`normal`

  This is music entered completely following the music format spec. This means you have to enter complete code with a `\staff` command. Example:

         variable = music("\staff\relative c' { c' d' }")

`chord`

  Enter the tones from the lowest to the highest tone, like this:

         variable = music("c' e' g'", chord)

  Short-hand function `chord` is defined. Calling

      chord("c e g")

  is the same as

      music("c e g", chord)

  .

`satb`

  Use this format to enter music where the program need to know what voice (in a choir) will sing the different tones. Take this, for example:

         variable = music("c''|e'|g|c")

  The `c''` will be sung by the soprano, `e'` by the alto, etc.

  Short-hand function `satb` is defined.

`voice`

  This musictype saves some key strokes if you want to enter a melody.

         variable = music("c'4 c' g' g' | a' a' g'2", voice)

  is the same as

         variable = music("\staff{ c'4 c' g' g' | a' a' g'2", normal)

  Short-hand function `voice` is defined.

`rvoice`

  `rvoice` is similar to `voice` except that the music is in `\relative` mode, relative to the first tone. The music from:

        variable = music("c'4 c g' g | a a g2", rvoice)

  will be interpreted as

        \staff\relative c'{ c4 c g' g' | a a g2 }

  . and producing the same music as in the `voice` example above.

  Short-hand function `rvoice` is defined.

`wavfile`

  MUSICDATA is the file name of a `.wav` file. The path given to the file is relative to the directory the lesson file is stored in. Example:

        variable = music("share/fifth-small-220.00.wav", wavfile)

  Short-hand function `wavfile` is defined.

`cmdline`

  MUSICDATA is a command you want to execute. Example:

       cmdline("./bin/csound-play-harmonic-interval.sh 220.000000 320.100000")

  Short-hand function `cmdline` is defined.

### Global variables

Global variables can save you a few key strokes.

    s = "\score\relative c'{ %s }

    question {
      # instead of music = music("\score\relative c'{ c d e f g2 g2 }") :
      music = music(s % "c d e f g2 g")
    }

Also, the two variables `tempo` and `instrument` can at top level to set the defaul values for a whole file. You can override this for singel questions by putting another difinition inside the question block.

### Comments

Everything after # on a line is ignored

### Grammar

Disclaimer: I don't know any of the standard ways of describing grammar, like BNF. So this is just an attemt to describe the file format to get people started writing lesson files.

Lessonfiles consists of assignment statements and blocks containing assignment statements.

#### Functions

`_`

  takes a string as its only argument. Use this if you want Solfege to translate the string for you. Example:

      description = _("This is a short description")

`include`

  includes another file in to this file. Example:

      include("singchord-1")

#### Types

`string`

  is quoted using the `"` character, like this: `"this is a string"`. Use tripple quotes for strings that contain line breaks:

      description = """<h1>Long desription<h1>
                     This lessonfile need very much descriptions.
                     bla bla bla"""

  If the string need to contain the `"` character, you have to use tripple quotes:

      description = """Try <a href="solfege:practise/melodic-interval">this
      </a> for a simpler interval exercise."""

  NB: All strings have to be unicode strings. If you get error messages like this one:

      In line 21 of input: does not recognise this string '<' as a valid token.'
      (line 20):
      question {
      (line 21): question {
      (line 22):   name = _("Ionia�)

  then you must check the encoding of your file. See the section about file encoding. You can change the encoding of a file using the iconv program:

      iconv -f YOUR_ENCODING -t utf8 your.file

`integer`

  is an integer is an integer...

`tempotype (in lack of a better name)`

  is entered as `bpm/beatlen`. An example:

      tempo = 120/4

  will set the tempo to 120 beats per minute, each beat being a quarter note.

#### Operators

Operators can only be used on strings

`+`

  is used for joining strings

`%`

  is similar to what you find in python, but it is very limited. It only know about `%s`. One example:

      "\staff\relative c'{%s}" % "c d e"

  evaluates to

      "\staff\relative c'{c d e}"

#### Reserved words

OUTDATED. FIXME. To be put on the right side of assignments. The current parser does not complain if you redefines the identifiers, so don't do that!

`chord, dictation, id-by-name, sing-chord`

  Possible values for `content`

`horiz, vertic`

  Used for table filling in id-by-name exercise

`normal, progression`

  `labelformat` values.

#### Identifiers

Identifiers match the regular expression "[a-zA-Z]+[\w_-]*".

#### Block

There are two block types, `header` and `question`.

    blocktype {
      CONTENTS
    }