On Thu, 2005-04-14 at 06:01, Bernard Hurley wrote: > I have somewhat rashly volunteered to be Implementation documenter. > Han-Wen informs me that various abortive starts have already been made > on this. So if you have any material that would be useful, please e-mail > it to me. >
Bernard, Here are materials I put together in my abortive start. They were helpful to me but are by no means complete, especially with the new backends in 2.5.x. Thanks for taking on this project. Carl Sorensen
@c -*- coding: latin-1; mode: texinfo; -*- @c This file is part of lilypond.tely @c A menu is needed before every deeper *section nesting of @node's; run @c M-x texinfo-all-menus-update @c to automatically fill in these menus before saving changes @node Programming Concepts manual @chapter Programming Concepts manual This chapter explains some of the concepts related to LilyPond programming. It is intended as an introductory reference for developers who want to make changes to LilyPond. @menu * Program Execution Overview:: * Music classes:: * Contexts:: * Engravers:: * Grobs:: * Stencils:: * Iterators:: * Keywords and special \\words :: @end menu @node Program Execution Overview @section Program Execution Overview @cindex Program Execution Overview Execution of LilyPond begins with the parser (@file{lily/parser.yy}). When the input file is parsed, a Music + Music_output_def object is created. This object leads to a Global_context object (see @file{lily/global-context.cc}). The Global_context object creates a Score context to interpret the music. (@file{lily/score.cc}). Interpreting proceeds, with context objects being created as dictated by the Music + Music_output_def object. When the interpretation is complete, Score_context::get_output() returns a Music_output object, which is a Paper_score object for notation or a Performance object for MIDI. During the interpretation process, Music_iterators handle the interpretation of Music objects and synchronize the various Contexts to ensure that the different Items are tied together appropriately. This is accomplished in Global_context::run_iterator_on_me, by a recursive call to Music_iterator::pending_moment. The events are delivered to Music_iterator::procss(next_moment). Finally, Global_context::one_time_step() is called to create all the grobs for the current time step. This Music_output object is the entry point for the backend (see ly_format_output(), in @file{lily/score.cc}). The backend is responsible for putting ink on the page (or notes in the MIDI file). The main steps of the backend are found in @file{lily/paper-score.cc} (Paper_score::process) and @file{lily/system.cc} (System::get_lines()). System::get_line() causes each grob to deliver a Stencil to the outputting backends (@file{scm/output-tex.scm} and @file{scm/output-ps.scm}) to produce TeX and Postscript, respectively. @node Music Classes @section Music Classes @cindex Music Classes @node Contexts @section Contexts @cindex Contexts Contexts are used to process music expressions, generating music events and passing these events to one or more Engravers. Engravers handle the events and convert them to grobs. Contexts are created in lilypond input files. The predefined contexts are included in @file{ly/engraver-init.ly}. This file is the appropriate place to add a new context. During development, the new context can be created in a lilypond input file. Once the context is debugged, it can be added to @file{ly/engraver-init.ly}. @node Engravers @section Engravers @cindex Engravers Engravers are used to handle music events for inclusion on the page. In most intances, they convert music events to grobs, but there are also engravers that don't create grobs, such as swallow-engraver and grob-pq-engraver. Each unique kind of grob should have its own engraver. Engravers are C++ classes (see @file{lily/note-heads-engraver.cc}). To add an engraver, simply create a file for the class and add it to the lily/ directory. Make will then include the file when LilyPond is rebuilt. In creating the engraver, it is best to use an existing engraver as a template, as there is a number of subtleties that must be done correctly. The work of adding the class to LilyPond is done in the ENTER_DESCRIPTION macro. A list of all engravers is found in @internalsref{engravers}. @node Grobs @section Grobs @cindex Grobs Grobs (graphic objects) are produced by LilyPond to place graphics on the page. They are created from within engravers, either as Spanners (a derived class of objects that span more than one ``column'', such as slurs, and beams) or Items (a derived class of objects that only occupy a single column, such as notes, clefs, etc.) There are two other derived classes: System (derived from Spanner, contaning a "line of music") and Paper_column (derived from Item, containing all Items that happen at the same moment). They are separate classes because they play a special role in the linebreaking process. The definition of all grobs is found at @internalsref{All layout objects}. Each grob has an interface, which is not a C++ class per se. The idea of a grob interface hasn't crystallized well. At the moment, an interface is a symbol, with a bunch of grob properties. They are not objects that are created or destroyed. Grob interfaces are defined by programmers in @file{scm/define-grob-interfaces.scm}. These definitions are documented in @internalsref{Graphical object interfaces}. Grob properties are used to help the Stencil creators do their job. Properties can include constants, functions, or other grobs. This allows multi-element grobs such as Spanner , System, and Paper_column to properly handle the individual grobs of which they are comprised. Grob properties are currently used as elements of an alist chain that are used in Stencil creation. Stencil creators use the props alist to control the characteristics of the created Stencil. Grob properties are defined by programmers in @file{scm/define-grob-properties.scm}. These properties are docemented in @internalsref{User backend properties}. > @node Stencils @section Stencils @cindex Stencils Stencils are the output specifications created by LilyPond grobs. They are C++ objects containing a Box, which describes the physical limits of the ink on the paper, and a Scheme function, which is evaluated by the backend to create the TeX or Postscript code responsible for generating the ink. The Box has an X_AXIS extent and a Y_AXIS extent. The extents are pairs. The first element of the pair is the coordinate of the left (for X_AXIS) or bottom (for Y_AXIS) side of the stencil's bounding box. The second element of the pair is the coordinate of the right or top side of the bounding box. The coordinates are measured relative to the stencil's reference point. The first element of each extent pair must be less than the second. In most cases, the first element of the extent will be negative and the second element will be positive, which place the reference point for the stencil inside the bounding box. The reference point for the stencil is in @var{Stencil::origin_}, and can be accessed in Scheme with @var{ly:stencil-origin}. The Scheme function contains a specification of how to print the object, along with the horizontal and vertical extents. The specification is a scheme expression that is processed by the various output backends, such as @file{scm/output-tex.scm}. When a new stencil specification is added to LilyPond, the appropriate code for handling the specification must be added to the relevant backends. Lilypond routines for defining and adjusting stencils are generally found in @file{lily/stencil.cc} and @file{lily/stencil-scheme.cc}. @file{lily/stencil.cc} implements the Stencil class. @file{lily/stencil-scheme.cc} implements scheme accessors to the Stencil class. Scheme accessors are of the form @code{ly:stencil-*}, and are used to manipulate stencils in scheme. Internal documentation of the scheme accessors is found at @internalsref{ly:stencil-add}. Stencils are usually created in @code{Class::print_function()}, which is exported to Scheme using the macro MAKE_SCHEME_CALLBACK. @node Smobs @section Smobs @cindex Smobs Smobs are C++ objects in Scheme. Scheme objects (lists, functions) are manipulated from C++ as well using the GUILE C function interface (prefix: scm_). Smobs are the primary interface (sometimes called 'glue' or 'lubrication') between the guile (Scheme) part and C++ part of LilyPond. C++ routines can call Scheme routines (using scm_call_0, scm_call_1 as well as the guile C function interface). Scheme routines can call C++ routines if the C++ routines have been exported using LY_DEFINE. For an example, see @file{scm/stencil-scheme.scm}. @node Iterators @section Iterators @cindex Iterators Music_iterators are used to walk through different music classes and deliver events in a synchronized way, so that notes that play together are processed at the same moment and (as a result) end up at the same horizontal position. Music_iterators are created during the interpreting phase, in @code{Music_iterators::get_static_get_iterator()} according to the @code{iterator-ctor} property of music types (see @file{scm/define-music-types.scm}). Music_iterators are able to read and set Context properties, idem for Engravers and Contexts. They can send 'synthetic' music events to a context in order to influence the behavior of Engraver. part-combine-status is an example of a synthetic event used by Part_combine_iterator to communicate with (to) Part_combine_engraver. @node Keywords and special \\words @section Keywords and special \\words @cindex Keywords and special \\words LilyPond keywords are defined in defined in @file{lily/my-lily-lexer.cc}. Most of the words prededed by a backslash are really identifiers, rather than reserved words, and are defined in @file{ly/*.ly}. @node Making Additions to LilyPond @chapter Making Additions to LilyPond This chapter describes approaches to common additions to LilyPond @menu * Adding articulation signs:: * Adding new grobs:: @end menu @node Adding articulation signs @section Adding articulation signs @cindex Adding articulation signs Articulation signs can easily be added using metafont. The steps involved are the following @list @item Add the articulation sign to the feta font (see @file{mf/feta-schrift.mf}). It is often easy to do this by modifying an existing character in the font. @item Tell LilyPond about your articulation sign by adding it to the file @file{scm/script.scm}. @item Add a handy shortcut to the file @file{ly/script-init.ly}. @item For testing, add it to @file{input/test/script.chart.ly}. @item For documentation, add it to the Articulations section of the user manual, found in @file{Documentation/user/notation.itely}. @end{list} Whenever changes are made to the font, you must clean the fonts before rebuilding, or you will not see the changes. This can be done by executing @file{buildscripts/out/clean-fonts}. @node Troubleshooting the build process @chapter Troubleshooting the build process @cindex Troubleshooting the build process In order to make changes in LilyPond, it is necessary to rebuild the application. This chapter covers common problems in building both the application and the documentation. @node Using gdb with LilyPond @chapter Using gdb with LilyPond @cindex Using gdb with LilyPond @cindex Debugging To use gdb with lilypond, it is necessary to first compile it with debugging symbols. ./configure --prefix=$(pwd) --enable-debugging make Do not use make install, as that will strip out the debugging symbols. Start LilyPond under gdb with the following gdb ./lily/out/lilypond @node Debugging LilyPond in guile @cindex Debugging You can debug in guile by using #(top-repl). ----- toto=\notes { c'' } #(top-repl) ----- nicolas:/tmp> lilypond toto.ly lilypond (GNU LilyPond) 2.1.28 Exécution de usr... Maintenant en traitement: « toto.ly » Analyse... guile> (define-module (*anonymous-ly-1*)) guile> toto #<Music SequentialMusic> guile> (use-modules (lilypond music-expressions)) guile> (mus:display toto) <SequentialMusic :elements ( <EventChord :elements ( <NoteEvent :duration #<Duration 4 > :pitch #<Pitch c'' > >) >) > guile> (quit) Thanks for that precious tip, Han-Wen.
_______________________________________________ lilypond-devel mailing list lilypond-devel@gnu.org http://lists.gnu.org/mailman/listinfo/lilypond-devel