@c -*-texinfo-*- @c Move chapter @node Development @chapter Development @menu * CodingStyle:: * Making patches:: * Localisation:: * Helping with development:: @end menu @node CodingStyle @section CodingStyle - standards while programming for GNU LilyPond As a general rule, you should always try to continue computations, even if there is some kind of error. When the program stops, it is often very hard for a user to pinpoint what part of the input causes an error. Finding the culprit is much easier if there is some viewable output. So functions and methods do not return errorcodes, they never crash, but report a programming_error and try to carry on. @unnumberedsubsec Languages C++ and Python are preferred. Python code should use an indent of 8, using TAB characters. @unnumberedsubsec Filenames Definitions of classes that are only accessed via pointers (*) or references (&) shall not be included as include files. filenames @example ".hh" Include files ".cc" Implementation files ".icc" Inline definition files ".tcc" non inline Template defs @end example in emacs: @example (setq auto-mode-alist (append '(("\\.make$" . makefile-mode) ("\\.cc$" . c++-mode) ("\\.icc$" . c++-mode) ("\\.tcc$" . c++-mode) ("\\.hh$" . c++-mode) ("\\.pod$" . text-mode) ) auto-mode-alist)) @end example The class Class_name is coded in @file{class-name.*} @unnumberedsubsec Indentation Standard GNU coding style is used. In emacs: @example (add-hook 'c++-mode-hook '(lambda() (c-set-style "gnu") ) ) @end example If you like using font-lock, you can also add this to your @file{.emacs}: @example (setq font-lock-maximum-decoration t) (setq c++-font-lock-keywords-3 (append c++-font-lock-keywords-3 '(("\\b\\([a-zA-Z_]+_\\)\\b" 1 font-lock-variable-name-face) ("\\b\\([A-Z]+[a-z_]+\\)\\b" 1 font-lock-type-face)) )) @end example @unnumberedsubsec Classes and Types @example This_is_a_class @end example @unnumberedsubsec Members @example Class::member () Type Class::member_type_ Type Class::member_type () @end example the @code{type} is a Hungarian notation postfix for @code{Type}. See below @unnumberedsubsec Macros Macro names should be written in uppercase completely. @unnumberedsubsec Broken code Try not to write broken code. This includes hardwired dependencies, hardwired constants, slow algorithms and obvious limitations. If you can not avoid it, mark the place clearly, and add a comment explaining shortcomings of the code. @unnumberedsec Hungarian notation naming convention The C++ part of LilyPond uses a naming convention derived from the so-called @emph{Hungarian Notation}. Macros, @code{enum}s and @code{const}s are all uppercase, with the parts of the names separated by underscores. The hungarian notation is to be used when variables are not declared near usage (mostly in member variables and functions). @unnumberedsubsec Types @table @code @item @code{byte} unsigned char. (The postfix _by is ambiguous) @item @code{b} bool @item @code{bi} bit @item @code{ch} char @item @code{f} float @item @code{i} signed integer @item @code{str} string class @item @code{sz} Zero terminated c string @item @code{u} unsigned integer @end table @unnumberedsubsec User defined types @example /* Slur blah. blah. */ class Slur @{ ... @}; Slur* slur_p = new Slur; @end example @unnumberedsubsec Modifiers The following types modify the meaning of the prefix. These are preceded by the prefixes: @table @code @item @code{a} array @item @code{arr} user built array. @item @code{c} const. Note that the proper order is @code{Type const} and not @code{const Type} @item @code{C} A const pointer. This would be equivalent to @code{_c_l}, but since any "const" pointer has to be a link (you can't delete a const pointer), it is superfluous. @item @code{l} temporary pointer to object (link) @item @code{p} pointer to newed object @item @code{r} reference @end table @unnumberedsubsec Adjective Adjectives such as global and static should be spelled out in full. They come before the noun that they refer to, just as in normal english. @example foo_global_i: a global variable of type int commonly called "foo". @end example static class members do not need the static_ prefix in the name (the Class::var notation usually makes it clear that it is static) @table @code @item @code{loop_i} Variable loop: an integer @item @code{u} Temporary variable: an unsigned integer @item @code{test_ch} Variable test: a character @item @code{first_name_str} Variable first_name: a String class object @item @code{last_name_ch_a} Variable last_name: a @code{char} array @item @code{foo_i_p} Variable foo: an @code{Int*} that you must delete @item @code{bar_i_l} Variable bar: an @code{Int*} that you must not delete @end table Generally default arguments are taboo, except for nil pointers. The naming convention can be quite conveniently memorised, by expressing the type in english, and abbreviating it @example static Array foo @end example @code{foo} can be described as "the static int-pointer user-array", so you get @example foo_static_l_arr @end example @unnumberedsec Miscellaneous For some tasks, some scripts are supplied, notably creating patches, a mirror of the website, generating the header to put over cc and hh files, doing a release. Use them. @node Making patches @section Making patches @unnumberedsec Track and distribute your code changes This page documents how to distribute your changes to GNU lilypond We would like to have unified context diffs with full pathnames. A script automating supplied with Lily. Distributing a change normally goes like this: @itemize @bullet @item make your fix/add your code @item Add changes to CHANGES, and add yourself to Documentation/topdocs/AUTHORS.texi @item generate a patch, @item e-mail your patch to one of the mailing lists gnu-music-discuss@@gnu.org or bug-gnu-music@@gnu.org @end itemize Please do not send entire files, even if the patch is bigger than the original. A patch makes it clear what is changed, and it won't overwrite previous (not yet released) changes. @unnumberedsec Generating a patch Simple version: run @example make -C lilypond-x.y.z/ distclean make -C lilypond-x.y.z.NEW/ distclean diff -urN lilypond-x.y.z/ lilypond-x.y.z.NEW/ @end example Complicated (but automated) version: In @file{VERSION}, set MY_PATCH_LEVEL: @example VERSION: ... MY_PATCH_LEVEL=jcn1 @end example In @file{CHANGES}, enter a summary of changes: @example 0.1.73.jcn1 =========== * A concise, yet clearly readable description of what changed. @end example Then, from the top of Lily's source tree, type @example make release @end example These handy python scripts assume a directory structure which looks like: @example lilypond -> lilypond-x.y.z # symlink to development directory lilypond-x.y.z/ # current development patches/ # patches between different releases releases/ # .tar.gz releases @end example @unnumberedsec Applying patches [outdated: please use xdeltas] If you're following LilyPond development regularly, you probably want to download just the patch for each subsequent release. After downloading the patch (into the patches directory, of course), simply apply it: @example gzip -dc ../patches/lilypond-0.1.74.diff.gz | patch -p1 -E @end example and don't forget to make automatically generated files: @example autoconf footnote(patches don't include automatically generated files, i.e. file(configure) and files generated by file(configure).) configure @end example @node Localisation @section Localisation - User messages in LilyPond This document provides some guidelines for uniformising user messages. In the absence of other standards, we'll be using these rules when coding for LilyPond. Hopefully, this can be replaced by general GNU guidelines in the future. Not-preferred messages are marked with @code{+}. By convention, agrammatical examples are marked with @code{*}. @subsection Guidelines @itemize @bullet @item Every message to the user should be localised (and thus be marked for localisation). This includes warning and error messages. @item Don't localise/gettextify: @itemize @minus @item @code{programming_error ()}s @item @code{programming_warning ()}s @item debug strings @item output strings (PostScript, TeX) @end itemize @item Messages to be localised must be encapsulated in @code{_ (STRING)} or @code{_f (FORMAT, ...)}. Eg: @example warning (_ ("Need music in a score")); error (_f ("Can't open file: `%s'", file_name)); @end example In some rare cases you may need to call @code{gettext ()} by hand. This happens when you pre-define (a list of) string constants for later use. In that case, you'll probably also need to mark these string constants for translation, using @code{_i (STRING)}. The @code{_i} macro is a no-op, it only serves as a marker for @file{xgettext}. @example char const* messages[] = @{ _i ("enable debugging output"), _i ("ignore lilypond version"), 0 @}; void foo (int i) @{ puts (gettext (messages [i])); @} @end example See also @file{flower/getopt-long.cc} and @file{lily/main.cc}. @item Don't use leading or trailing whitespace in messages. @item Messages containing a final verb, or a gerund (@code{-ing}-form) always start with a capital. Other (simpler) messages start with a lowercase letter: @example The word `foo' is not declared. `foo': not declared. Not declaring: `foo'. @end example @item To avoid having a number of different messages for the same situation, we'll use quoting like this @code{"message: `%s'"} for all strings. Numbers are not quoted: @example _f ("Can't open file: `%s'", name_str) _f ("Can't find charater number: %d", i) @end example @item Think about translation issues. In a lot of cases, it is better to translate a whole message. The english grammar mustn't be imposed on the translator. So, iso @example _ ("Stem at ") + moment.str () + _(" doen't fit in beam") @end example @noindent have @example _f ("Stem at %s doen't fit in beam", moment.str ()) @end example @item Split up multi-sentence messages, whenever possible. Instead of @example warning (_f ("out of tune! Can't find: `%s', "Key_engraver")); warning (_f ("Can't find font `%s', loading default", font_name)); @end example @noindent rather say: @example warning (_ ("out of tune:"); warning (_f ("Can't find: `%s', "Key_engraver")); warning (_f ("Can't find font: `%s', font_name)); warning (_f ("Loading default font")); @end example @item If you must have multiple-sentence messages, use full punctuation. Use two spaces after end of sentence punctuation. No punctuation (esp. period) is used at the end of simple messages. @example _f ("Non-matching braces in text `%s', adding braces", text) _ ("Debug output disabled. Compiled with NPRINT.") _f ("Huh? Not a Request: `%s'. Ignoring.", request) @end example @item Don't modularise too much; a lot of words cannot be translated without context. It's probably safe to treat most occurences of words like stem, beam, crescendo as separately translatable words. @item When translating, it is preferrable to put interesting information at the end of the message, rather than embedded in the middle. This especially applies to frequently used messages, even if this would mean sacrificing a bit of eloquency. This holds for original messages too, of course. @example en: can't open: `foo.ly' + nl: kan `foo.ly' niet openen (1) kan niet openen: `foo.ly'* (2) niet te openen: `foo.ly'* (3) @end example The first nl message, although gramatically and stylishly correct, is not friendly for parsing by humans (even if they speak dutch). I guess we'd prefer something like (2) or (3). @item Please don't run make po/po-update with GNU gettext < 0.10.35 @end itemize @node Helping with development @section Getting involved If you want to help developing LilyPond your efforts are appreciated. You can help LilyPond in several ways. Not all tasks requiring programming or understanding the full source code. Please don't expect us to give you instructions on what you should do. We're just a bunch of simple hackers, and we're absolutely incompetent about management, design in advance, delegating work. Some people write to us "I want to help, what should I do?", but we never know what to answer them. If you want to hack, just start hacking. You can send us the result as a patch, and we'll gladly incorporate it. If you need some hints on where to get started: there are a number of specific areas where you could do work. @unnumberedsubsec Users Mutopia needs your help. The mutopia project is a collection of public domain sheet music. You can help the project by entering music (either by hand, or by converting from scans or MIDI) and submitting it. Point your browser to the @uref{http://sca.uwaterloo.ca/Mutopia, Mutopia webpage}. @unnumberedsubsec Writers The documentation of LilyPond and related utilities needs a lot of work. The documentation is written in @uref{http://www.gnu.org/software/texinfo,texinfo}. The documentation of LilyPond is sorely lacking in terms of completeness, depth and organisation. Write if you know how to write english documentation in texinfo, and know about music and music notation. You must also know how to use LilyPond (or be prepared to learn using it). The task is not especially hard, but it is a lot of work, and you must be familiar with LilyPond. @unnumberedsubsec Translators LilyPond is completely ready for internationalized messages, but there are only a few translations so far (dutch, italian, german, japanese, french, russian). Translation involves writing a .po file, which is relatively easy, and does not even require running LilyPond. @unnumberedsubsec Hackers There are lots of possibilities of improving the program itself. There are both small projects and big ones. Most of them are listed in our TODO file, listed on the homepage of Jan and @uref{http://www.cs.uu.nl/~hanwen/lily-devel,Han-Wen}. Modifying LilyPond almost always requires patches to the C++ part. If you still don't have any idea what to do, you might want to browse the mailing lists; Users do lots of feature requests, and you could implement any of them. There are also numerous other interesting projects that are more or less related to LilyPond @itemize @bullet @item Writing convertors, eg. from NIFF and MIDI (we tried writing one with limited success: midi2ly, included with lilypond.) We found that writing them in Python is the easiest. @item Writing a GUI frontend to LilyPond. At the moment @uref{denemo,denemo.sourceforge.net} is the most advanced. @item Helping write @uref{http://solfege.sourceforge.net/,solfege tools} @item Helping @uref{primrose.sourceforge.net,primrose}, a tool for scanning sheet music. @end itemize @node ETF format @section An incomplete description of the Enigma Transport Format Enigma Transport Format (ETF for short) is a format designed by Coda music technology, and it is used in the proprietary notation package Finale. Since it is very poorly documented, I'll attempt some documentation here. ETF is an memory dump where object pointers have been replaced by object numbers. The numbers are larger than 0 and the number 0 is used to denote the nil pointer. The dump is encoded in ASCII (where the mac version uses CR, and the PC CR/LF as line delimiters) A file is divided into sections like this @example ^section-header DATA ^section-header DATA (etc.) @end example @var{DATA} is stored in the form of tagged lines, where a tagged line looks like @example ^TG(N1[,N2]) X1 X2 X3 (etc) @end example The caret is at the start of the line, @code{TG} is a two letter tag, and @var{N1} (and optionally @var{N2}) are numbers identifying the object to be described. @var{X3}, @var{X4} etc contain data in the form of either a signed 16 bit number, or a 32 bit number (in hex, with a $ sign prepended). The number of Xs per line for a certain tag is constant. The numbers in @code{N1} need not be consecutive or ascending, mostly. If an object is too large to fit on a single line (which typically has only five X's), it is put on multiple lines and padded with zero's, eg. @example ^GF(1,2) 3 0 1 2 3 ^GF(1,2) 4 0 0 0 0 @end example (the GF object requires 6 16 bit words, hence the 4 padding zeroes). Note structure: Each staff can contain up to four layers, where a layer correspond to a horizontal `line' of notes. Each layer is broken up into frames, where each frame is one measure of a layer. @example ^GF(s,m) @var{c} @var{flags} @var{f1} @var{f2} @var{f3} ^GF(s,m) @var{f4} 0 0 0 0 @end example Here @var{s} is the staff number, @var{m} the measure number, @var{flags} is a 16-bit bit-vector, and @var{f1} to @var{f4} are frame identifiers. @var{c} is a clef-identifier. There is a second variant of the @code{GF} tag, which has only one line; it looks like @example ^GF(s,m) @var{fr} @var{c} @var{x} @var{y} @var{z} @end example here, @code{fr} is a frame number, @code{c} the clef number. The function of x, y , z is unknown. A frame is described by the FR tag @example ^FR(@var{n}) @var{n1} @var{n2} 0 0 @end example This means frame number @var{n} runs from note @var{n1} to note @var{n2} Where `running from' is interpreted as ``that part of a linked note list that starts with note @var{n1} and ends with note @var{n2}''. This is something different from the sequence of notes @var{n1}, @var{n1 + 1} , ... , @var{n2 - 1}, @var{n2}. Notes (or more accurately chord-notes/rests) are described as follows: @example ^eE(@var{n}) @var{l1 l2 dur pos $flags extflags pitchcount} pitchrecords @end example This is note number @var{n} (in list where @var{l1} and @var{l2} are previous and next). Durations are stored as a number where 1024 is the quarter note, 512 the eighth, etc. Dotted notes are stored by multiplying the dur field appropriately. pitchcount is the number of pitch records. Each pitchrecord looks like @example pitch $flags @end example (note that the line starts with spaces, and not with a caret) pitch is a 16 bit number, where the lower order 4-bits is a signed nybble which adds an alteration (0 = natural, 1 = sharp, etc.) The remaining 12 bits encodes the note-name (octave inclusive.) Both the alteration and the note-name are relative to the scale as defined by the key-signature in this measure. The person who invented this should have his head checked out. The key and time signature are defined in the MS field @example ^MS(n) space key beats beatlen y z @end example @var{n} is the measure number. @var{space} is the width of the measure (?), @var{key} the number of the keysignature (0 = C major, 1 G major, etc. 255 = F major, 254 = Bflat major). beats and beatlen determine time signature. Key and time are determined score wide. The mind boggles at how they plan to do polytonal and polymetric music. And how do they do mid-measure keychanges? Slurs are (among others) stored with an Sx tag @example ^Sx(@var{slurnumber}) @var{stuff} @end example The slur has many parameters. The 6th number on the first line is the starting note, the 3rd number on the 4th line the ending note. Some other information can be found in the Finale Plug-in Development (there is a vague manual, and some source files that are useful). You can download the PDK from Coda's website, @uref{http://www.codamusic.com/coda/Fin2000_pdk_download.asp}. You do need to register as a user (you can also do it if you have never bought an coda product). More tags: @example RU - repeat ES - end repeat ET - end repeat text BR - backw repeat mt - measure text pT - page text TX - text blocks SD - shape DY - score expr AC - tempo GF - clef IS - staff spec DO (shape expression), DT (text expression), IK (chord playback), IS (staff spec), IV (chord suffix), IX (articulation definition - documented in edata.h), Iu (instrument used - documented in edata.h), LA (layer preferences - documented in eprfdata.h), MN (measure number region), MS (measure spec), PS (page spec), RS (repeat style - documented in edata.h), RT (text repeat style text - documented in edata.h), SD (shape), SS (staff system spec), TX (text block), pT (page text) TP - tuplet sl - slur shapetag @end example