]> git.donarmstrong.com Git - lilypond.git/commitdiff
Merge branch 'master' into translation
authorJean-Charles Malahieude <lilyfan@orange.fr>
Mon, 13 Feb 2017 17:28:14 +0000 (18:28 +0100)
committerJean-Charles Malahieude <lilyfan@orange.fr>
Mon, 13 Feb 2017 17:28:14 +0000 (18:28 +0100)
211 files changed:
Documentation/changes.tely
Documentation/contributor/quick-start.itexi
Documentation/contributor/regressions.itexi
Documentation/learning/fundamental.itely
Documentation/lilypond-texi2html.init
Documentation/notation/changing-defaults.itely
Documentation/notation/editorial.itely
Documentation/notation/percussion.itely
Documentation/notation/pitches.itely
Documentation/notation/staff.itely
Documentation/snippets/new/transposing-pitches-with-minimum-accidentals-smart-transpose.ly [new file with mode: 0644]
Documentation/snippets/transposing-pitches-with-minimum-accidentals-smart-transpose.ly
Documentation/web/community.itexi
Documentation/web/news-front.itexi
Documentation/web/news-headlines.itexi
Documentation/web/news.itexi
VERSION
input/regression/lyric-extender-rest.ly
input/regression/scheme-text-spanner.ly
lily/accidental-engraver.cc
lily/ambitus-engraver.cc
lily/arpeggio-engraver.cc
lily/auto-beam-engraver.cc
lily/axis-group-engraver.cc
lily/axis-group-interface.cc
lily/balloon-engraver.cc
lily/bar-engraver.cc
lily/bar-number-engraver.cc
lily/beam-collision-engraver.cc
lily/beam-engraver.cc
lily/beam-performer.cc
lily/bend-engraver.cc
lily/book-scheme.cc
lily/break-align-engraver.cc
lily/break-alignment-interface.cc
lily/breathing-sign-engraver.cc
lily/chord-name-engraver.cc
lily/chord-tremolo-engraver.cc
lily/clef-engraver.cc
lily/cluster-engraver.cc
lily/collision-engraver.cc
lily/completion-note-heads-engraver.cc
lily/completion-rest-engraver.cc
lily/concurrent-hairpin-engraver.cc
lily/context-def.cc
lily/control-track-performer.cc
lily/cue-clef-engraver.cc
lily/custos-engraver.cc
lily/default-bar-line-engraver.cc
lily/dot-column-engraver.cc
lily/dots-engraver.cc
lily/double-percent-repeat-engraver.cc
lily/drum-note-engraver.cc
lily/drum-note-performer.cc
lily/dynamic-align-engraver.cc
lily/dynamic-engraver.cc
lily/dynamic-performer.cc
lily/engraver.cc
lily/episema-engraver.cc
lily/extender-engraver.cc
lily/figured-bass-engraver.cc
lily/figured-bass-position-engraver.cc
lily/fingering-column-engraver.cc
lily/fingering-engraver.cc
lily/font-size-engraver.cc
lily/footnote-engraver.cc
lily/forbid-break-engraver.cc
lily/fretboard-engraver.cc
lily/function-documentation.cc
lily/glissando-engraver.cc
lily/grace-engraver.cc
lily/grace-spacing-engraver.cc
lily/gregorian-ligature-engraver.cc
lily/grid-line-span-engraver.cc
lily/grid-point-engraver.cc
lily/grob-interface-scheme.cc
lily/grob-pq-engraver.cc
lily/horizontal-bracket-engraver.cc
lily/hyphen-engraver.cc
lily/include/coherent-ligature-engraver.hh
lily/include/engraver.hh
lily/include/gregorian-ligature-engraver.hh
lily/include/ligature-engraver.hh
lily/include/lily-proto.hh
lily/include/performer.hh
lily/include/profile.hh
lily/include/protected-scm.hh
lily/include/scheme-engraver.hh
lily/include/stencil.hh
lily/include/translator.hh
lily/include/translator.icc
lily/instrument-name-engraver.cc
lily/instrument-switch-engraver.cc
lily/keep-alive-together-engraver.cc
lily/key-engraver.cc
lily/key-performer.cc
lily/kievan-ligature-engraver.cc
lily/laissez-vibrer-engraver.cc
lily/ledger-line-engraver.cc
lily/ligature-bracket-engraver.cc
lily/ligature-engraver.cc
lily/lyric-engraver.cc
lily/lyric-performer.cc
lily/mark-engraver.cc
lily/measure-grouping-engraver.cc
lily/melody-engraver.cc
lily/mensural-ligature-engraver.cc
lily/metronome-engraver.cc
lily/midi-cc-performer.cc
lily/multi-measure-rest-engraver.cc
lily/music.cc
lily/new-fingering-engraver.cc
lily/note-head-line-engraver.cc
lily/note-heads-engraver.cc
lily/note-name-engraver.cc
lily/note-performer.cc
lily/note-spacing-engraver.cc
lily/ottava-engraver.cc
lily/output-property-engraver.cc
lily/page-breaking.cc
lily/page-layout-problem.cc
lily/page-turn-engraver.cc
lily/paper-book.cc
lily/paper-column-engraver.cc
lily/paper-column.cc
lily/parenthesis-engraver.cc
lily/parser.yy
lily/part-combine-engraver.cc
lily/percent-repeat-engraver.cc
lily/phrasing-slur-engraver.cc
lily/piano-pedal-align-engraver.cc
lily/piano-pedal-engraver.cc
lily/piano-pedal-performer.cc
lily/pitch-squash-engraver.cc
lily/pitched-trill-engraver.cc
lily/prob-scheme.cc
lily/profile.cc
lily/program-option-scheme.cc
lily/protected-scm.cc
lily/pure-from-neighbor-engraver.cc
lily/repeat-acknowledge-engraver.cc
lily/repeat-tie-engraver.cc
lily/rest-collision-engraver.cc
lily/rest-engraver.cc
lily/rhythmic-column-engraver.cc
lily/scheme-engraver.cc
lily/script-column-engraver.cc
lily/script-column.cc
lily/script-engraver.cc
lily/script-row-engraver.cc
lily/separating-line-group-engraver.cc
lily/simple-spacer.cc
lily/slash-repeat-engraver.cc
lily/slur-engraver.cc
lily/slur-performer.cc
lily/spacing-engraver.cc
lily/span-arpeggio-engraver.cc
lily/span-bar-engraver.cc
lily/span-bar-stub-engraver.cc
lily/spanner-break-forbid-engraver.cc
lily/spanner.cc
lily/spring-smob.cc
lily/staff-collecting-engraver.cc
lily/staff-performer.cc
lily/staff-symbol-engraver.cc
lily/stanza-number-align-engraver.cc
lily/stanza-number-engraver.cc
lily/stem-engraver.cc
lily/stencil-expression.cc
lily/stencil-integral.cc
lily/stencil-interpret.cc
lily/stencil-scheme.cc
lily/stencil.cc
lily/system-start-delimiter-engraver.cc
lily/tab-note-heads-engraver.cc
lily/tab-staff-symbol-engraver.cc
lily/tab-tie-follow-engraver.cc
lily/tempo-performer.cc
lily/text-engraver.cc
lily/text-spanner-engraver.cc
lily/tie-engraver.cc
lily/tie-performer.cc
lily/time-signature-engraver.cc
lily/time-signature-performer.cc
lily/timing-translator.cc
lily/translator-ctors.cc
lily/translator-group.cc
lily/translator-scheme.cc
lily/translator.cc
lily/trill-spanner-engraver.cc
lily/tuplet-engraver.cc
lily/tweak-engraver.cc
lily/vaticana-ligature-engraver.cc
lily/vertical-align-engraver.cc
lily/volta-engraver.cc
ly/Welcome-to-LilyPond-MacOS.ly
ly/Welcome_to_LilyPond.ly
ly/articulate.ly
ly/music-functions-init.ly
po/lilypond.pot
python/GNUmakefile
python/midi.c [deleted file]
python/midi.py [new file with mode: 0644]
scm/bar-line.scm
scm/define-markup-commands.scm
scm/define-stencil-commands.scm
scm/fret-diagrams.scm
scm/output-lib.scm
scm/scheme-engravers.scm
scm/stencil.scm
scripts/midi2ly.py

index a78d6d32970966e367436263e8ea1e5502fc7d5a..2a647782442518f0e8eb42656a5a04ca1378193b 100644 (file)
@@ -108,7 +108,7 @@ that combine the characteristics of @code{modern-voice} and @code{piano}
 or their equivalents with cautionary accidentals.
 
 @item
-The music function @code{\\unfoldRepeats} can now take an
+The music function @code{\unfoldRepeats} can now take an
 optional argument-list specifying which type(s) of repeated music
 should be unfolded.  Possible entries are @code{percent}, @code{tremolo},
 @code{volta}.
index e3ee9e91416b14ec8795bcd72d498f8942827ec2..d41b7ad3e7d06169474acdb3893a61e358cca418 100644 (file)
@@ -508,28 +508,38 @@ This will download and update you to the lastest version of git-cl.
 @node Configuring git-cl
 @unnumberedsubsec Configuring @code{git-cl}
 
-@subsubheading Set up login accounts
-
 Because @code{git-cl} updates two separate websites (Google's Rietveld
 Code Review Tool and LilyPond's issue tracker) you @emph{must} have a
 valid user account (login and password) for both sites.
 
+@subsubheading Set up a login account for Rietveld Code Review Tool
+
 @noindent
-For the Rietveld Code Review Tool you will need a Google account.  Note
-that a Google account does not require that you have or use a @q{Google}
-email address.  You can use @emph{any} email address for your Google
-account.  Just select the option @qq{I prefer to use my current email
-address} when you sign up.
+For the Rietveld Code Review Tool you will need a Google account but
+this does @emph{not} require @q{Google} email address; i.e. @emph{any}
+email address for your Google account can be used.  Just select the
+option @qq{I prefer to use my current email address} when you sign up
+with Google.
+
+@warning{In order for @code{git-cl} to work correctly with this Google
+account, your Google Account Settings must have the
+@q{Access for less secure apps} set to @q{Allowed} -- this is normally
+the default setting.}
 
-@warning{In order for @code{git-cl} to work, your Google Account
-Settings must have the @q{Access for less secure apps} set to
-@q{Allowed}.  This is normally the default setting.}
+@subsubheading Set up a login account for LilyPond's Issue Tracker
+
+@noindent
+Please register a user account at
+@code{https://sourceforge.net/user/registration} preferably using the
+same email address that you want to use LilyPond Developer mailing list
+login.
 
 @noindent
-For the LilyPond issue tracker, please request a user account by sending
-an email to the LilyPond Developer's mailing list
-(@code{lilypond-devel@@gnu.org}), preferably using the same email
-address that you want to use for your user login.
+Once you have created this Sourceforge user account, send an email to
+the LilyPond Developer's mailing list (@code{lilypond-devel@@gnu.org})
+asking for write access to the issue tracker along with your Sourceforce
+@emph{Username} (not email address) and someone will then be able to set
+this up for you.
 
 @subsubheading Authorizing git-cl for the LilyPond issue tracker
 
index 9b13c25d53107f5696a528af18b04347f98a2639..1963a6bebcfac7ae5a1bd4b90cd849423184fadc 100644 (file)
@@ -11,7 +11,6 @@
 * Finding the cause of a regression::
 * Memory and coverage tests::
 * MusicXML tests::
-* Grand Regression Test Checking::
 @end menu
 
 
@@ -542,49 +541,3 @@ available in the LilyPond documentation:
 @uref{http://lilypond.org/doc/latest/input/regression/musicxml/collated-files}
 @end example
 
-
-@node Grand Regression Test Checking
-@section Grand Regression Test Checking
-
-@subheading What is this all about?
-
-Regression tests (usually abbreviated "regtests") is a collection
-of @file{.ly} files used to check whether LilyPond is working correctly.
-Example: before version 2.15.12 breve noteheads had incorrect width,
-which resulted in collisions with other objects.  After the issue was fixed,
-a small @file{.ly} file demonstrating the problem was added to the regression
-tests as a proof that the fix works.  If someone will accidentally break
-breve width again, we will notice this in the output of that regression test.
-
-@subheading How can I help?
-
-We ask you to help us by checking one or two regtests from time to time.
-You don't need programming skills to do this, not even LilyPond skills -
-just basic music notation knowledge; checking one regtest takes less than
-a minute.  Simply go here:
-
-@example
-@uref{http://www.philholmes.net/lilypond/regtests/}
-@end example
-
-@subheading Some tips on checking regtests
-
-@subsubheading Description text
-
-The description should be clear even for a music beginner.
-If there are any special terms used in the description,
-they all should be explained in our @rglosnamed{Top, Music Glossary}
-or @rinternalsnamed{Top, Internals Reference}.
-Vague descriptions (like "behaves well", "looks reasonable") shouldn't be used.
-
-@ignore
-this may be useful for advanced regtest checking
-@subsubheading Is regtest straightforward and systematic?
-
-Unfortunately some regtests are written poorly.  A good regtest should be
-straightforward: it should be obvious what it checks and how.  Also, it
-usually shouldn't check everything at once.  For example it's a bad idea to test
-accidental placement by constucting one huge chord with many suspended notes
-and loads of accidentals.  It's better to divide such problem into a series
-of clearly separated cases.
-@end ignore
index 6b74fe954a8a312b2c62d7158c9544128d572507..07d604e873e26396bac1c39b2f01a22db9f2d5d6 100644 (file)
@@ -1705,27 +1705,28 @@ in which context they operate.  Sometimes this is obvious,
 but occasionally it can be tricky.  If the wrong context
 is specified, no error message is produced, but the expected
 action will not take place.  For example, the
-@code{instrumentName} clearly lives in the @code{Staff} context, since
-it is the staff that is to be named.
-In this example the first staff is labeled, but not the second,
-because we omitted the context name.
+@code{clefGlyph} clearly lives in the @code{Staff} context, since
+it is the staff's clef glyph that is to be changed.
+In this example the first staff's clef is printed correctly, but not the
+second -- which prints the default treble clef instead of the
+expected bass (or F) clef -- because we omitted the context name.
 
 @lilypond[quote,verbatim,ragged-right]
 <<
   \new Staff \relative {
-    \set Staff.instrumentName = #"Soprano"
+    \set Staff.clefGlyph = "clefs.C"
     c''2 c
   }
   \new Staff \relative {
-    \set instrumentName = #"Alto"  % Wrong!
+    \set clefGlyph = "clefs.F"  % Wrong!
     d'2 d
   }
 >>
 @end lilypond
 
 Remember the default context name is @code{Voice}, so the second
-@code{\set} command set the property @code{instrumentName} in the
-@code{Voice} context to @qq{Alto}, but as LilyPond does not look
+@code{\set} command set the property @code{clefGlyph} in the
+@code{Voice} context to @code{clefs.F}, but as LilyPond does not look
 for any such property in the @code{Voice} context, no
 further action took place.  This is not an error, and no error
 message is logged in the log file.
@@ -1743,7 +1744,7 @@ such features, it is recommended to check the property name in the
 Internals Reference: see @rinternals{Tunable context properties}, or
 @rinternals{Contexts}.
 
-The @code{instrumentName} property will take effect only
+The @code{clefGlyph} property will take effect only
 if it is set in the @code{Staff} context, but
 some properties can be set in more than one context.
 For example, the property @code{extraNatural} is by
@@ -2377,8 +2378,9 @@ lower = \relative {
 \score {
   <<  % combine ChoirStaff and PianoStaff in parallel
     \new ChoirStaff <<
-      \new Staff = "sopranos" <<
-        \set Staff.instrumentName = #"Soprano"
+      \new Staff = "sopranos"
+      \with { instrumentName = #"Soprano" }
+      <<
         \new Voice = "sopranos" {
           \global
           \sopranoMusic
@@ -2387,24 +2389,31 @@ lower = \relative {
       \new Lyrics \lyricsto "sopranos" {
         \sopranoWords
       }
-      \new Staff = "altos" <<
-        \set Staff.instrumentName = #"Alto"
+      \new Staff = "altos"
+      \with { instrumentName = #"Alto" }
+      <<
         \new Voice = "altos" {
           \global
           \altoMusic
         }
       >>
-      \new Lyrics \lyricsto "altos" { \altoWords }
-      \new Staff = "tenors" <<
-        \set Staff.instrumentName = #"Tenor"
+      \new Lyrics \lyricsto "altos" {
+        \altoWords
+      }
+      \new Staff = "tenors"
+      \with { instrumentName = #"Tenor" }
+      <<
         \new Voice = "tenors" {
           \global
           \tenorMusic
         }
       >>
-      \new Lyrics \lyricsto "tenors" { \tenorWords }
-      \new Staff = "basses" <<
-        \set Staff.instrumentName = #"Bass"
+      \new Lyrics \lyricsto "tenors" {
+        \tenorWords
+      }
+      \new Staff = "basses"
+      \with { instrumentName = #"Bass" }
+      <<
         \new Voice = "basses" {
           \global
           \bassMusic
@@ -2414,8 +2423,8 @@ lower = \relative {
         \bassWords
       }
     >>  % end ChoirStaff
-    \new PianoStaff <<
-      \set PianoStaff.instrumentName = #"Piano"
+    \new PianoStaff \with { instrumentName = #"Piano" }
+    <<
       \new Staff = "upper" \upper
       \new Staff = "lower" \lower
     >>
@@ -2453,8 +2462,9 @@ Doing this gives for our ChoirStaff:
 
 @example
 \new ChoirStaff <<
-  \new Staff = "sopranos" <<
-    \set Staff.instrumentName = #"Soprano"
+  \new Staff = "sopranos"
+  \with @{ instrumentName = #"Soprano" @}
+  <<
     \new Voice = "sopranos" @{
       \global
       \sopranoMusic
@@ -2463,8 +2473,9 @@ Doing this gives for our ChoirStaff:
   \new Lyrics \lyricsto "sopranos" @{
     \sopranoWords
   @}
-  \new Staff = "altos" <<
-    \set Staff.instrumentName = #"Alto"
+  \new Staff = "altos"
+  \with @{ instrumentName = #"Alto" @}
+  <<
     \new Voice = "altos" @{
       \global
       \altoMusic
@@ -2473,8 +2484,9 @@ Doing this gives for our ChoirStaff:
   \new Lyrics \lyricsto "altos" @{
     \altoWords
   @}
-  \new Staff = "tenors" <<
-    \set Staff.instrumentName = #"Tenor"
+  \new Staff = "tenors"
+  \with @{ instrumentName = #"Tenor" @}
+  <<
     \new Voice = "tenors" @{
       \global
       \tenorMusic
@@ -2483,8 +2495,9 @@ Doing this gives for our ChoirStaff:
   \new Lyrics \lyricsto "tenors" @{
     \tenorWords
   @}
-  \new Staff = "basses" <<
-    \set Staff.instrumentName = #"Bass"
+  \new Staff = "basses"
+  \with @{ instrumentName = #"Bass" @}
+  <<
     \new Voice = "basses" @{
       \global
       \bassMusic
@@ -2501,8 +2514,8 @@ easy - we just pull out the piano part from the
 @q{Solo piano} template:
 
 @example
-\new PianoStaff <<
-  \set PianoStaff.instrumentName = #"Piano  "
+\new PianoStaff \with @{ instrumentName = #"Piano  " @}
+<<
   \new Staff = "upper" \upper
   \new Staff = "lower" \lower
 >>
@@ -2558,8 +2571,8 @@ stacked one above the other:
     @}
   >>  % end ChoirStaff
 
-  \new PianoStaff <<
-    \set PianoStaff.instrumentName = #"Piano"
+  \new PianoStaff \with @{ instrumentName = #"Piano" @}
+  <<
     \new Staff = "upper" \upper
     \new Staff = "lower" \lower
   >>
@@ -2611,8 +2624,9 @@ lower = \relative {
 \score {
   <<  % combine ChoirStaff and PianoStaff in parallel
     \new ChoirStaff <<
-      \new Staff = "sopranos" <<
-        \set Staff.instrumentName = #"Soprano"
+      \new Staff = "sopranos"
+      \with { instrumentName = #"Soprano" }
+      <<
         \new Voice = "sopranos" {
           \global
           \sopranoMusic
@@ -2621,8 +2635,9 @@ lower = \relative {
       \new Lyrics \lyricsto "sopranos" {
         \sopranoWords
       }
-      \new Staff = "altos" <<
-        \set Staff.instrumentName = #"Alto"
+      \new Staff = "altos"
+      \with { instrumentName = #"Alto" }
+      <<
         \new Voice = "altos" {
           \global
           \altoMusic
@@ -2631,8 +2646,9 @@ lower = \relative {
       \new Lyrics \lyricsto "altos" {
         \altoWords
       }
-      \new Staff = "tenors" <<
-        \set Staff.instrumentName = #"Tenor"
+      \new Staff = "tenors"
+      \with { instrumentName = #"Tenor" }
+      <<
         \new Voice = "tenors" {
           \global
           \tenorMusic
@@ -2641,8 +2657,9 @@ lower = \relative {
       \new Lyrics \lyricsto "tenors" {
         \tenorWords
       }
-      \new Staff = "basses" <<
-        \set Staff.instrumentName = #"Bass"
+      \new Staff = "basses"
+      \with { instrumentName = #"Bass" }
+      <<
         \new Voice = "basses" {
           \global
           \bassMusic
@@ -2653,8 +2670,9 @@ lower = \relative {
       }
     >>  % end ChoirStaff
 
-    \new PianoStaff <<
-      \set PianoStaff.instrumentName = #"Piano  "
+    \new PianoStaff
+    \with { instrumentName = #"Piano  " }
+    <<
       \new Staff = "upper" \upper
       \new Staff = "lower" \lower
     >>
index b6970ac606452a10e78532b8c5e2bd1319bff5fb..70a86344f15a486b8e1c4f852bccf0ae97e512b1 100644 (file)
@@ -1369,7 +1369,7 @@ sub lilypond_css_lines ($$)
     my $reldir = "";
     $reldir = "../" unless $bigpage;
     if ($have_index_entries) {
-      $Texi2HTML::THISDOC{'CSS_LINES'} .= "<script language=\"JavaScript\" src=\"${reldir}lily_search.js\"></script>\n";
+      $Texi2HTML::THISDOC{'CSS_LINES'} .= "<script language=\"JavaScript\" type=\"text/javascript\" src=\"${reldir}lily_search.js\"></script>\n";
     }
   }
 
index 222615a33f722a5ce07f6b5349bb659bda4d0c39..e72137aeddda7482385e321eb62de8c88fa04905 100644 (file)
@@ -1825,6 +1825,7 @@ LilyPond-specific?
 * The override command::
 * The tweak command::
 * set versus override::
+* The offset command::
 * Modifying alists::
 @end menu
 
@@ -2504,6 +2505,317 @@ a music event (@code{\tweak}) or, in the case of
 @code{\overrideProperty} for a specific override.
 
 
+@node The offset command
+@subsection The @code{\offset} command
+
+@funindex \offset
+@cindex offsetting
+@cindex defaults, offsetting
+
+While it is possible to set grob properties to new values with the
+@code{\override}, @code{\tweak}, and @code{\overrideProperty} commands,
+it is often more convenient to modify such properties relative to a
+default value.  The @code{\offset} command is available for this
+purpose.
+
+The syntax for @code{\offset} is
+
+@example
+[-]\offset @var{property} @var{offsets} @var{item}
+@end example
+
+The command works by adding the contents of @var{offsets} to the
+default setting of the property @var{property} of the grob indicated by
+@var{item}.
+
+Depending on the formulation of the command, @code{\offset} may act
+as either a @code{\tweak} or @code{\override}.  The variations in
+usage are discussed after consideration is given to grob properties
+that may be used with @code{\offset}.
+
+@subsubsubheading{Properties which may be offset}
+
+Many, but not all, grob properties may be offset.  If @var{property}
+cannot be offset, the object will remain unchanged and a warning will
+be issued.  In such cases, @code{\override} or @code{\tweak} should be
+used to modify the object instead.
+
+One can work by trial and error and let the warnings be the guide to
+what may or may not be offset.  A more systematic approach is possible,
+however.
+
+The following criteria determine whether a property can be modified with
+@code{\offset}:
+
+@itemize
+
+@item
+The property has a @q{default setting} in the grob's description.  Such
+properties are listed for each grob in @rinternals{All layout objects}.
+(They are also found in @file{scm/define-grobs.scm}.)
+
+@item
+The property takes a numerical value.  Numerical values include
+@code{number}, list of @code{number}s, @code{number-pair}, and
+@code{number-pair-list}.  The pages at @rinternals{All layout objects}
+list the type of data characteristic to each property.  It is immaterial
+whether the default setting is a function.
+
+@item
+The property cannot be a @q{subproperty}---a property residing within
+another property.
+
+@item
+Properties set to infinite values cannot be offset.  There is no
+sensible way to offset positive and negative infinity.
+@end itemize
+
+The following examples consider several grob properties against the
+criteria outlined above.
+
+@itemize
+
+@item Properties that may be offset
+
+@table @asis
+
+@item @code{Hairpin.height}
+
+This property is not a subproperty, and it is listed at
+@rinternals{Hairpin}.  For a value, it takes @q{dimension, in staff
+space} set to @code{0.6666}---clearly a non-infinite @code{number}.
+
+@item @code{Arpeggio.positions}
+
+The page @rinternals{Arpeggio} lists a @code{positions} property which
+accepts a @q{pair of numbers}.  It defaults to
+@code{ly:arpeggio::positions}---a callback which will be evaluated
+during the typesetting phase to yield a pair of numbers for any given
+@code{Arpeggio} object.
+
+@end table
+
+@item Properties that may not be offset
+
+@table @asis
+
+@item @code{Hairpin.color}
+
+There is no listing for @code{color} at @rinternals{Hairpin}.
+
+@item @code{Hairpin.circled-tip}
+
+The listing for @code{Hairpin.circled-tip} at @rinternals{Hairpin} shows
+that it takes a @code{boolean} value.  Booleans are non-numerical.
+
+@item @code{Stem.details.lengths}
+
+Though listed at @rinternals{Stem} and defaulting to a list of
+@code{number}s, this is a @q{subproperty}.  There is currently no
+support for @q{nested properties}.
+
+@end table
+
+@end itemize
+
+@subsubsubheading{@bs{}offset as an override}
+
+If @var{item} is a grob name like @code{Arpeggio} or
+@code{Staff.OttavaBracket}, the result is an @code{\override} of the
+specified grob-type.
+
+@example
+\offset @var{property} @var{offsets} [@var{context}.]@var{GrobName}
+@end example
+
+Note that the leading hyphen is @emph{never} used with the @q{override}
+form, just as it is never used with the @code{\override} command itself.
+
+The following example uses the @q{override} form to lengthen the
+default arpeggios shown in the first measure to cover the extent of
+the chords more fully.  The arpeggios are stretched by a half
+staff-space to top and bottom.  Also shown is the same operation done on
+the first chord with an ordinary override of the @code{positions}
+property.  This method is not at all expressive of the task of
+@q{stretching by a half staff-space}, as the endpoints must be specified
+with absolute rather than relative coordinates.  Furthermore, individual
+overrides would be needed for the other chords, as they vary in size and
+position.
+
+@lilypond[quote,verbatim]
+arpeggioMusic = {
+  <c' e' g'>\arpeggio <a' c'' e''>\arpeggio
+  <d' f' a' c''>\arpeggio <c' e' g' b' d'' f'' a''>\arpeggio
+}
+
+{
+  \arpeggioMusic
+  \bar "||"
+  \offset positions #'(-0.5 . 0.5) Arpeggio
+  \arpeggioMusic
+  \bar "||"
+  \once \override Arpeggio.positions = #'(-3.5 . -0.5)
+  <c' e' g'>1\arpeggio
+  \bar "||"
+}
+@end lilypond
+
+In its @q{override} usage, @code{\offset} may be prefaced with
+@code{\once} or @code{\temporary} and reverted using @code{\revert} with
+@var{property}.  This follows from the fact that @code{\offset} actually
+creates an @code{\override} of @var{property}.
+
+@lilypond[quote,verbatim]
+music = { c'8\< d' e' f'\! }
+
+{
+  \music
+  \offset height 1 Hairpin
+  \music
+  \music
+  \revert Hairpin.height
+  \music
+  \bar "||"
+  \once \offset height 1 Hairpin
+  \music \music
+  \bar "||"
+  \override Hairpin.height = 0.2
+  \music
+  \temporary \offset height 2 Hairpin
+  \music
+  \music
+  \revert Hairpin.height
+  \music
+  \bar "||"
+}
+@end lilypond
+
+Also like @code{\override}, the @q{override} form of @code{\offset} may
+be used with @code{\undo} and @code{\single}.
+
+@lilypond[quote,verbatim]
+longStem = \offset length 6 Stem
+
+{
+ \longStem c'4 c''' c' c''
+ \bar "||"
+ \undo \longStem c'4 c''' c' c''
+ \bar "||"
+ \single \longStem c'4 c''' c' c''
+ \bar "||"
+}
+@end lilypond
+
+@subsubsubheading{@bs{}offset as a tweak}
+
+If @var{item} is a music expression such as @code{(} or
+@code{\arpeggio}, the result is the same music expression with a tweak
+applied.
+
+@example
+[-]\offset [@var{GrobName}.]@var{property} @var{offsets} @var{music-expression}
+@end example
+
+The syntax of @code{\offset} in its @q{tweak} form is analogous to the
+@code{\tweak} command itself, both in ordering and in the presence or
+absence of the leading hyphen.
+
+The following example uses the @q{tweak} form to adjust the vertical
+position of the @code{BreathingSign} object.  Compare this with the
+ordinary @code{\tweak} command also demonstrated.  The syntax is
+equivalent; however, the output of @code{\tweak} is less intuitive,
+since @code{BreathingSign.Y-offset} is calculated from the middle
+staff-line.  It is not necessary to know how @code{Y-offset} is
+calculated when using @code{\offset}.
+
+@lilypond[quote,verbatim]
+{
+  c''4
+  \breathe
+  c''4
+  \offset Y-offset 2 \breathe
+  c''2
+  \tweak Y-offset 3 \breathe
+}
+@end lilypond
+
+In the previous example, the tweaked objects were created directly from
+the user input: the @code{\breathe} command was an explicit instruction
+to return a @code{BreathingSign} object.  Since the focus of the command
+was unambiguous, there was no need to specify the object's name.  When
+an object is @emph{indirectly} created, however, it is necessary to
+include the grob's name.  This is the same as for the @code{\tweak}
+command.
+
+In the following example, the @code{Beam} object is lowered two
+staff-spaces by applying @code{\offset} to the @code{positions}
+property.
+
+The first application of @code{\offset} requires that the grob's name
+be included, because nothing in the input explicitly creates the
+beam.  In the second application, the beam is created manually with the
+music expression @code{[}; therefore, the grob's name is not needed.
+(Also illustrated is a shorthand: a single @code{number} will be applied
+to both members of a @code{number-pair}.)
+
+@lilypond[quote,verbatim]
+{
+  c''8 g'' e'' d''
+  \offset Beam.positions #'(-2 . -2)
+  c''8 g'' e'' d''
+  c''8 g'' e'' d''
+  c''8-\offset positions #-2 [ g'' e'' d'']
+}
+@end lilypond
+
+@subsubsubheading{@bs{}offset with broken spanners}
+
+Independently modifying segments of a spanner extending over a line
+break or breaks is also possible.  In this case, @var{offsets}
+takes a list of values of the property's required data type.
+
+The @code{\offset} command used in this manner is similar to the
+@code{\alterBroken} command.  (See @ref{Modifying broken spanners}.)
+In contrast with @code{\alterBroken}, however, the values given to
+@code{\offset} are relative, not absolute.
+
+The following example displaces the @q{broken} @code{OttavaBracket}
+object through its @code{staff-padding} property.  Since the property
+takes a @code{number}, @var{offsets} is provided with a list of
+@code{number}s to account for the two segments created by the line
+break.  The slur piece on the first line is effectively untouched since
+@code{0} is added to its default value.  The segment on the second
+line is raised two staff-spaces from its default height.  The default
+height happens to be @code{2}, though it is not necesssary to know this.
+
+@lilypond[quote,verbatim]
+{
+  \offset staff-padding #'(0 3) Staff.OttavaBracket
+  \ottava #1
+  c'''2 c'''
+  \break
+  c'''2 c'''
+}
+@end lilypond
+
+The following example mimics the effect of the @code{\shape} command by
+offsetting the @code{control-points} property of the @code{Slur} object.
+Here, @var{offsets} is a list of @code{number-pair-list}s, one for each
+slur segment.  This example achieves a result identical to the
+corresponding illustration at @ref{Modifying shapes}.
+
+@lilypond[quote,verbatim]
+{
+  c'4-\offset control-points #'(
+               ((0 . 0) (0 . 0) (0 . 0) (0 . 1))
+               ((0.5 . 1.5) (1 . 0) (0 . 0) (0 . -1.5))
+              ) ( f'4 g' c''
+  \break
+  d'4 c'' f' c')
+}
+@end lilypond
+
+
 @node Modifying alists
 @subsection Modifying alists
 
index b1fbb8b1c938966009c9674d6aaf75ed133dc19c..458fce1ff4d97dbd8c6f27c6afb0f14ed297f2df 100644 (file)
@@ -507,12 +507,13 @@ If @code{x11-color} cannot make sense of the parameter then the
 color returned defaults to black.
 
 @lilypond[verbatim,quote]
-\relative c'' {
-  \override Staff.StaffSymbol.color = #(x11-color 'SlateBlue2)
-  \set Staff.instrumentName = \markup {
-    \with-color #(x11-color 'navy) "Clarinet"
+\new Staff \with {
+  instrumentName = \markup {
+    \with-color #(x11-color 'red) "Clarinet"
+    }
   }
-
+  \relative c'' {
+  \override Staff.StaffSymbol.color = #(x11-color 'SlateBlue2)
   gis8 a
   \override Beam.color = #(x11-color "medium turquoise")
   gis a
@@ -536,12 +537,13 @@ Exact RGB colors can be specified using the Scheme function
 @code{rgb-color}.
 
 @lilypond[verbatim,quote]
+\new Staff \with {
+  instrumentName = \markup {
+    \with-color #(x11-color 'red) "Clarinet"
+    }
+  }
 \relative c'' {
   \override Staff.StaffSymbol.color = #(x11-color 'SlateBlue2)
-  \set Staff.instrumentName = \markup {
-    \with-color #(x11-color 'navy) "Clarinet"
-  }
-
   \override Stem.color = #(rgb-color 0 0 0)
   gis8 a
   \override Stem.color = #(rgb-color 1 1 1)
index c6502992b0796ddf8dd53ed75090f895b7a20d77..da730eb5f3b944bf72299b193d0ced9cbf8eb5cd 100644 (file)
@@ -466,27 +466,22 @@ delicate things have a look at @ref{Staff symbol}.
 
 A tambourine, entered with @q{tamb}:
 
-@lilypond[quote,verbatim]
+@lilypond[verbatim,quote]
 #(define mydrums '((tambourine default #t 0)))
 
-tambustaff = {
-  \override Staff.StaffSymbol.line-positions = #'( 0 )
-  \override Staff.BarLine.bar-extent = #'(-1.5 . 1.5)
-  \set DrumStaff.instrumentName = #"Tambourine"
-}
+\new DrumStaff \with { instrumentName = #"Tambourine" }
 
-\new DrumStaff {
-  \tambustaff
+\drummode {
   \set DrumStaff.drumStyleTable = #(alist->hash-table mydrums)
+  \override Staff.StaffSymbol.line-positions = #'( 0 )
+  \override Staff.BarLine.bar-extent = #'(-1.5 . 1.5)
 
-  \drummode {
-    \time 6/8
-    tamb8. 16 8 8 8 8 |
-    tamb4. 8 8 8 |
-    % the trick with the scaled duration and the shorter rest
-    % is neccessary for the correct ending of the trill-span!
-    tamb2.*5/6 \startTrillSpan s8 \stopTrillSpan |
-  }
+  \time 6/8
+  tamb8. 16 8 8 8 8 |
+  tamb4. 8 8 8 |
+  % the trick with the scaled duration and the shorter rest
+  % is neccessary for the correct ending of the trill-span!
+  tamb2.*5/6 \startTrillSpan s8 \stopTrillSpan |
 }
 @end lilypond
 
@@ -495,19 +490,14 @@ Music for Tam-Tam (entered with @q{tt}):
 @lilypond[quote,verbatim]
 #(define mydrums '((tamtam default #t 0)))
 
-tamtamstaff = {
-  \override Staff.StaffSymbol.line-positions = #'( 0 )
-  \override Staff.BarLine.bar-extent = #'(-1.5 . 1.5)
-  \set DrumStaff.instrumentName = #"Tamtam"
-}
+\new DrumStaff \with { instrumentName = #"Tamtam" }
 
-\new DrumStaff {
-  \tamtamstaff
-  \set DrumStaff.drumStyleTable = #(alist->hash-table mydrums)
+\drummode {
+\set DrumStaff.drumStyleTable = #(alist->hash-table mydrums)
+\override Staff.StaffSymbol.line-positions = #'( 0 )
+\override Staff.BarLine.bar-extent = #'(-1.5 . 1.5)
 
-  \drummode {
-    tt 1 \pp \laissezVibrer
-  }
+  tt 1 \pp \laissezVibrer
 }
 @end lilypond
 
@@ -517,20 +507,16 @@ Two different bells, entered with @q{cb} (cowbell) and @q{rb} (ridebell)
 #(define mydrums '((ridebell default #t  3)
                    (cowbell  default #t -2)))
 
-bellstaff = {
-  \override DrumStaff.StaffSymbol.line-positions = #'(-2 3)
+\new DrumStaff \with { instrumentName = #"Different Bells" }
+
+\drummode {
   \set DrumStaff.drumStyleTable = #(alist->hash-table mydrums)
+  \override DrumStaff.StaffSymbol.line-positions = #'(-2 3)
   \override Staff.BarLine.bar-extent = #'(-1.5 . 1.5)
-  \set DrumStaff.instrumentName = #"Different Bells"
-}
 
-\new DrumStaff {
-  \bellstaff
-  \drummode {
-    \time 2/4
-    rb8 8 cb8 16 rb16-> ~ |
-    16 8 16 cb8 8 |
-  }
+  \time 2/4
+  rb8 8 cb8 16 rb16-> ~ |
+  16 8 16 cb8 8 |
 }
 @end lilypond
 
@@ -575,22 +561,22 @@ drumsB = {
 
 \score {
   \new StaffGroup <<
-    \new DrumStaff {
-      \set DrumStaff.instrumentName = \markup {
+    \new DrumStaff \with {
+      instrumentName = \markup {
         \column {
           "Tambourine"
           "et"
           "caisse claire s. timbre"
         }
       }
-      \set DrumStaff.drumStyleTable = #(alist->hash-table mydrums)
-      \drumsA
-    }
-
-   \new DrumStaff {
-     \set DrumStaff.instrumentName = #"Grosse Caisse"
-     \set DrumStaff.drumStyleTable = #(alist->hash-table mydrums)
-     \drumsB }
+    drumStyleTable = #(alist->hash-table mydrums)
+  }
+  \drumsA
+  \new DrumStaff \with {
+    instrumentName = #"Grosse Caisse"
+    drumStyleTable = #(alist->hash-table mydrums)
+  }
+  \drumsB
   >>
 }
 @end lilypond
index 6b9e0981214fc37d19b8e47f298c26962e7c2d3e..15af95d1405ba6ff626fd31ee912f7581f559274 100644 (file)
@@ -1523,26 +1523,24 @@ playing in unison.
 
 @lilypond[verbatim,quote]
 \new GrandStaff <<
-  \new Staff = "violin" {
-    \relative c'' {
-      \set Staff.instrumentName = #"Vln"
-      \set Staff.midiInstrument = #"violin"
-      % not strictly necessary, but a good reminder
-      \transposition c'
-
-      \key c \major
-      g4( c8) r c r c4
-    }
+  \new Staff = "violin" \with {
+    instrumentName = #"Vln"
+    midiInstrument = #"violin"
   }
-  \new Staff = "clarinet" {
-    \relative c'' {
-      \set Staff.instrumentName = \markup { Cl (B\flat) }
-      \set Staff.midiInstrument = #"clarinet"
-      \transposition bes
-
-      \key d \major
-      a4( d8) r d r d4
-    }
+  \relative c'' {
+    % not strictly necessary, but a good reminder
+    \transposition c'
+    \key c \major
+    g4( c8) r c r c4
+  }
+  \new Staff = "clarinet" \with {
+    instrumentName = \markup { Cl (B\flat) }
+    midiInstrument = #"clarinet"
+  }
+  \relative c'' {
+    \transposition bes
+    \key d \major
+    a4( d8) r d r d4
   }
 >>
 @end lilypond
index d097535643b0bb9a4f6e6841755b11c07b65fa5c..d7ed3e6738b55b9cb8ac7bbc3cc496625c8d0eaf 100644 (file)
@@ -215,8 +215,8 @@ that it supports printing the instrument name directly.  For
 details, see @ref{Instrument names}.
 
 @lilypond[verbatim,quote]
-\new PianoStaff <<
-  \set PianoStaff.instrumentName = #"Piano"
+\new PianoStaff \with { instrumentName = #"Piano" }
+<<
   \new Staff \relative { c''1 c }
   \new Staff \relative { \clef bass c1 c }
 >>
@@ -961,20 +961,14 @@ printed and subsequent changes will be ignored:
 @lilypond[verbatim,quote,ragged-right]
 prepPiccolo = <>^\markup \italic { muta in Piccolo }
 
+prepFlute = <>^\markup \italic { muta in Flauto }
+
 setPiccolo = {
-  \set Staff.instrumentName = #"Piccolo"
-  \set Staff.shortInstrumentName = #"Picc."
-  \set Staff.midiInstrument = #"piccolo"
   <>^\markup \bold { Piccolo }
   \transposition c''
 }
 
-prepFlute = <>^\markup \italic { muta in Flauto }
-
 setFlute = {
-  \set Staff.instrumentName = #"Flute"
-  \set Staff.shortInstrumentName = #"Flt."
-  \set Staff.midiInstrument = #"flute"
   <>^\markup \bold { Flute }
   \transposition c'
 }
@@ -982,14 +976,17 @@ setFlute = {
 \new Staff \with {
   instrumentName = #"Flute"
   shortInstrumentName = #"Flt."
-  midiInstrument = #"flute"
 }
 \relative {
   g'1 g g g \break
   g1 g \prepPiccolo R R \break
+  \set Staff.instrumentName = #"Piccolo"
+  \set Staff.shortInstrumentName = #"Picc."
   \setPiccolo
   g1 g g g \break
   g1 g \prepFlute R R \break
+  \set Staff.instrumentName = #"Flute"
+  \set Staff.shortInstrumentName = #"Flt."
   \setFlute
   g1 g g g
 }
diff --git a/Documentation/snippets/new/transposing-pitches-with-minimum-accidentals-smart-transpose.ly b/Documentation/snippets/new/transposing-pitches-with-minimum-accidentals-smart-transpose.ly
new file mode 100644 (file)
index 0000000..2cac27f
--- /dev/null
@@ -0,0 +1,84 @@
+\version "2.19.22"
+
+\header {
+  lsrtags = "pitches, scheme-language, workaround"
+
+  texidoc = "
+This example uses some Scheme code to enforce enharmonic modifications
+for notes in order to have the minimum number of accidentals.  In this
+case, the following rules apply:
+
+Double accidentals should be removed
+
+
+B sharp -> C
+
+
+E sharp -> F
+
+
+C flat -> B
+
+
+F flat -> E
+
+
+In this manner, the most natural enharmonic notes are chosen.
+
+"
+  doctitle = "Transposing pitches with minimum accidentals (\"Smart\" transpose)"
+}
+#(define (naturalize-pitch p)
+   (let ((o (ly:pitch-octave p))
+         (a (* 4 (ly:pitch-alteration p)))
+         ;; alteration, a, in quarter tone steps,
+         ;; for historical reasons
+         (n (ly:pitch-notename p)))
+     (cond
+      ((and (> a 1) (or (eqv? n 6) (eqv? n 2)))
+       (set! a (- a 2))
+       (set! n (+ n 1)))
+      ((and (< a -1) (or (eqv? n 0) (eqv? n 3)))
+       (set! a (+ a 2))
+       (set! n (- n 1))))
+     (cond
+      ((> a 2) (set! a (- a 4)) (set! n (+ n 1)))
+      ((< a -2) (set! a (+ a 4)) (set! n (- n 1))))
+     (if (< n 0) (begin (set! o (- o 1)) (set! n (+ n 7))))
+     (if (> n 6) (begin (set! o (+ o 1)) (set! n (- n 7))))
+     (ly:make-pitch o n (/ a 4))))
+
+#(define (naturalize music)
+   (let ((es (ly:music-property music 'elements))
+         (e (ly:music-property music 'element))
+         (p (ly:music-property music 'pitch)))
+     (if (pair? es)
+         (ly:music-set-property!
+          music 'elements
+          (map naturalize es)))
+     (if (ly:music? e)
+         (ly:music-set-property!
+          music 'element
+          (naturalize e)))
+     (if (ly:pitch? p)
+         (begin
+           (set! p (naturalize-pitch p))
+           (ly:music-set-property! music 'pitch p)))
+     music))
+
+naturalizeMusic =
+#(define-music-function (m)
+   (ly:music?)
+   (naturalize m))
+
+music = \relative c' { c4 d e g }
+
+\score {
+  \new Staff {
+    \transpose c ais { \music }
+    \naturalizeMusic \transpose c ais { \music }
+    \transpose c deses { \music }
+    \naturalizeMusic \transpose c deses { \music }
+  }
+  \layout { }
+}
index df6ce9d6c098260ec418a76c1ce22337da923153..3b209f08e2465aef6cf510c4feb954c1907bc3a2 100644 (file)
@@ -1,9 +1,10 @@
-%% DO NOT EDIT this file manually; it is automatically
-%% generated from LSR http://lsr.di.unimi.it
-%% Make any changes in LSR itself, or in Documentation/snippets/new/ ,
-%% and then run scripts/auxiliar/makelsr.py
-%%
-%% This file is in the public domain.
+% DO NOT EDIT this file manually; it is automatically
+% generated from Documentation/snippets/new
+% Make any changes in Documentation/snippets/new/
+% and then run scripts/auxiliar/makelsr.py
+%
+% This file is in the public domain.
+%% Note: this file works from version 2.19.22
 \version "2.19.22"
 
 \header {
@@ -42,10 +43,10 @@ In this manner, the most natural enharmonic notes are chosen.
          ;; for historical reasons
          (n (ly:pitch-notename p)))
      (cond
-      ((and (> a 1) (or (eq? n 6) (eq? n 2)))
+      ((and (> a 1) (or (eqv? n 6) (eqv? n 2)))
        (set! a (- a 2))
        (set! n (+ n 1)))
-      ((and (< a -1) (or (eq? n 0) (eq? n 3)))
+      ((and (< a -1) (or (eqv? n 0) (eqv? n 3)))
        (set! a (+ a 2))
        (set! n (- n 1))))
      (cond
index 69e30954b249ae6505482759999adbe87969248e..10c2b353dd9beaea60e31cfb4e97034ee0eb1737 100644 (file)
@@ -884,38 +884,44 @@ manuals can be found at @url{http://lilypond.org}}
 @divClass{column-center-top}
 @subheading What is Google Summer of Code?
 
-@uref{https://developers.google.com/open-source/gsoc/, GSoC} is a global
-program that offers students stipends to write code for free software
-and open source projects during the summer.  It is an excellent
+@uref{https://summerofcode.withgoogle.com/, GSoC} is a global program
+that offers students stipends to write code for free software and open
+source projects during the summer.  For three months students work to
+complete a given task as part of the project's community and under the
+guidance of experienced mentors.  The program is an excellent
 opportunity for students to gain experience with real-world software
 development and make a contribution that benefits everyone.  It brings
 new contributors to LilyPond and enables students who are already
 involved to become more involved.  LilyPond participates in GSoC as part
 of the @uref{http://www.gnu.org/, GNU project}.
 
-We have had GSoC participants in 2012, 2015 and 2016 and encourage students
-to apply for future summers.
+@strong{Note:} The accepted mentoring organizations will be announced on
+February 27, so only then we will officially know that we can
+participate in this year's program.
 
-If you have questions or would like to apply, send us an email on our
-developer mailing list (see @ref{Contact}).
+We have had GSoC participants in 2012, 2015 and 2016 and encourage
+students to apply for future summers.
+
+If you are interested to apply for the program with LilyPond as a
+project, please read the information below and don't hesitate to write
+us on our developer mailing list (see @ref{Contact}).  The student
+application window is March 20 to April 3, 2017, but we strongly
+encourage you to get in touch with our community ahead of that.
 
 @divEnd
 
 @divClass{column-center-middle-color2}
 @subheading Project Ideas List
 
-Below is a list of suggested projects for GSoC or for anyone who is
-interested in helping to improve LilyPond. (Last updated: November 2016)
-
-Mentor availability varies from project to project and from year to year.
-Send us an email on our developer mailing list (see @ref{Contact}), and
-we will help you find a mentor for a project that fits your interests
-and skills.
-
-If you have ideas for a GSoC project that is not listed below you can
-send us an email as well.  There are a number of areas where LilyPond
-could be improved, and our development team is always willing to help
-those who would like to tackle a project like those listed below.
+Below is a list of GSoC project ideas (last update: January 2017), but
+if you have other ideas for a project you may complete within the three
+months of the program you're welcome to make a suggestion on our
+developer mailing list (see @ref{Contact}).  There are a number of areas
+where LilyPond could be improved, and our development team is always
+willing to help those who would like to tackle a project similar to
+those listed below.  As mentor availability varies from project to
+project and from year to year it is wise to get in touch with us as
+early as possible.
 
 A full list of all the current open issues can be found
 @uref{http://sourceforge.net/p/testlilyissues/issues/, here}.
@@ -995,51 +1001,73 @@ it.
 @divEnd
 
 @divClass{column-center-middle-color3}
-@subheading Grace notes
-
-Fix problems with synchronization of grace notes.  Grace notes can
-interfere with LilyPond's timing and cause odd effects, especially when
-multiple staffs are used where some have grace notes and others don't.
-This is one of the longest-standing and one of the more embarrassing
-@uref{https://sourceforge.net/p/testlilyissues/issues/34/,bugs} in
-LilyPond.
+@subheading Contemporary Notation
+
+LilyPond is very good at creating non-standard notation.  Having to
+@emph{code} every graphical element instead of simply @emph{drawing}
+it may seem cumbersome but is in fact a strong asset.  New notational
+functionality can be provided with consistent appearance, automatic
+layout and a natural syntactic interface.
+
+Within the @uref{https://github.com/openlilylib/oll-core, openLilyLib}
+library system the student will create a fundamental infrastructure
+and building blocks to make creating contemporary notation easier.
+Additionally (at least) @emph{one} concrete package is developed to
+cover specific contemporary notation, such as for example the style
+of a given composer, extended playing techniques for a specific
+instrument or a certain category of effects.
 
 @strong{Difficulty:} medium
-@strong{Requirements:} C++, MIDI
-@strong{Recommended:} familiarity with LilyPond internals
-@strong{Potential Mentors:} Mike Solomon (not available for GSoC 2016),
-Carl Sorensen
+@strong{Requirements:} Scheme (interaction with LilyPond internals),
+contemporary notation techniques
+@strong{Recommended:} sense of building hierarchical frameworks
+@strong{Mentors:} @strong{NN,} Urs Liska
 
 @divEnd
 
 @divClass{column-center-middle-color3}
-@subheading Improve default beam positioning
-
-For regular, cross-staff, broken and kneed beams.  Beaming should depend
-on context and neighbor notes (see section 2.2 of
-@uref{http://imslp.org/wiki/Repository_of_Music-Notation_Mistakes_%28Coulon%2C_Jean-Pierre%29,
-this book}).  If possible also reduce beaming-computation time.
+@subheading Automated testing and documentation for openLilyLib
+
+@uref{https://github.com/openlilylib, openLilyLib} is an extension
+framework for LilyPond code providing a “snippets” repository and a
+suite of integrated packages such as for example page layout tools or
+scholarly annotations.  It is very powerful and promising, but to really
+get off the ground two features are missing: automated testing and
+documentation generation.
+
+Automated testing is necessary to ensure modifications to functionality
+don't break other functions within the library.  There is already some
+Automated Testing of the “snippets” repository with Github's Travis
+server, but this has to be reconsidered and extended to cover the
+standalone packages too.
+
+In order to be usable for a wider range of LilyPond users on a “consumer
+level” openLilyLib needs proper documentation.  This documentation has
+to be generated from the sources, so a system is needed that requires
+package authors to document the input files and provide additional usage
+examples, from which documentation is generated.  Ideally but not
+necessarily this is implemented as a Git hook, i.e. automatically upon
+each update to the repository.  We don't prescribe the tools and
+approaches to be used, but the most widely used language in the LilyPond
+domain is Python, so there would be some bias towards that.
+Alternatively a Scheme solution could be fine so generating the
+documentation would actually be triggered by “compiling” a certain
+LilyPond input file.  In general it is advisable to make use of proven
+concepts and tools from other languages.
+
+The eventual output of the documentation should be a static HTML site
+that can be viewed locally and/or uploaded to a website.  But it would
+be beneficial if the tool would first generate an intermediate
+representation (e.g. a JSON file with additional media files) from which
+a Single Page Application could retrieve content for display on
+openLilyLib's @uref{https://openlilylib.org, website}.  Development of
+such a SPA @emph{can} be part of the GSoC project, but is optional.
 
 @strong{Difficulty:} medium
-@strong{Requirements:} C++, experience with writing heuristics
-@strong{Recommended knowledge:} aesthetic sense
-@strong{Potential Mentors:} Mike Solomon (not available for GSoC 2016),
-Carl Sorensen
-
-@divEnd
-
-@divClass{column-center-middle-color3}
-@subheading Help improve compilation behavior
-
-Automatic code analysis tools, like valgrind memory leak detection or
-callgrind code profilers, provide valuable information about possible
-flaws in our C++ code.  Cleaning up warnings would allow us to automate
-the rejection of any patch which introduced extra warnings.
-
-@strong{Difficulty:} medium
-@strong{Requirements:} C++
-@strong{Potential Mentors:} Reinhold Kainhofer (not available for GSoC
-2016), Joe Neeman
+@strong{Requirements:} Python or Scheme, static website generator(s) or
+(Node.js based) dynamic web application technology. Continuous
+Integration (can be learned during the bonding period)
+@strong{Mentors:} Urs Liska, Matteo Ceccarello
 
 @divEnd
 
@@ -1078,29 +1106,87 @@ the MusicXML export project from GSoC 2015.
 
 @strong{Difficulty:} medium
 @strong{Requirements:} MusicXML, Python, Scheme, basic LilyPond knowledge
-@strong{Potential Mentors:} Reinhold Kainhofer, Mike Solomon (both not
-available for GSoC 2016)
+@strong{Recommended:} Familiarity with other scorewriters (for cross-testing)
+@strong{Mentor:} Jan-Peter Voigt
+
 
-Familiarity with other scorewriters (for cross-testing) would also help.
 
 @divEnd
 
-@divClass{column-center-middle-color3}
-@subheading Improve slurs and ties
+@divClass{column-center-middle-color2}
+@subheading Information for Applicants/Participants
 
-The engraving quality of slurs and ties is often unsatisfactory. Ties
-@q{broken} by clef or staff changes are not handled well.  The project
-could include collecting and sorting examples of bad output, deciding on
-the intended output and writing code to improve them.
+In order to have a satisfying experience with GSoC applicants are
+strongly advised to thoroughly read the following recommendations.  Some
+of these are relevant for the application process, others for the time
+within the project.
 
-@strong{Difficulty:} hard
-@strong{Requirements:} C++, experience with writing heuristics
-@strong{Recommended knowledge:} LilyPond knowledge, aesthetic sense
-@strong{Potential Mentors:} Mike Solomon, Janek Warchoł (both not available for
-GSoC 2016)
+@itemize
 
-@divEnd
+@item
+Read all applicable information on the program's website, particularly
+the
+@uref{https://developers.google.com/open-source/gsoc/resources/manual,
+students' manual}.  Make sure you fulfil all of Google's prerequisites
+and are willing to join the program as a full-time commitment over the
+coding period of three months.
+
+@item
+Please get in touch with us as soon as possible if you are interested in
+applying with a project.  Mentor availability may change without notice,
+project proposals may need fine-tuning, and many other reasons might
+require us to reject or ignore an application that hasn't been discussed
+before.
+
+@item
+We do not know in advance how many “slots” we will have available for
+projects, so please be aware that you may find yourself in competition
+with other applicants or not.  Interested or even enthusiastic response
+from our mentors is no guarantee of eventually being accepted, and
+@emph{not} being accepted does not necessarily indicate a negative
+evaluation of your application.  If we have to decide between different
+applicants there may be various aspects to consider.
+
+@item
+Integration in the LilyPond community is a fundamental part of GSoC, and
+we expect our students to make substantial efforts to become community
+members.  Within the @emph{bonding period} we expect you to write a blog
+post about your project (either on @uref{http://lilypondblog.org, Scores
+of Beauty} or on any other blog) and to be active on our mailing lists,
+introducing yourself but also communicating about unrelated tasks.  This
+goes beyond the mere setting up of a working environment and
+familiarizing yourself with the relevant code, but we think it is
+crucial for the GSoC project to be mutually satisfying.
 
+@item
+If you are accepted to the program you will have one mentor explicitly
+assigned to your project.  With this mentor you will have to agree upon
+a communication strategy, be it emails, chatrooms, issue trackers or
+voice/video chats.  Regular communication is absolutely crucial for the
+success of a GSoC project so you are stricly required to keep talking to
+your mentor.  But keep in mind that your mentor has explicitly taken
+over the responsibility for your project, and while unlike you he isn't
+paid for this activity you are still entitled to get regular attention
+from him.
+
+@item
+In order to get support from your mentor you have to give him a chance
+to follow your progress and efforts.  Therefore it is important to
+regularly commit your changes to the versioning repository you are
+working on.  Don't hesitate making unfinished code available because you
+are afraid of criticism, and don't suppress questions because you think
+they might be considered stupid.  But ideally your code should at any
+time be accompanied by compatible testing code.  Your mentor may not be
+able to properly assess your code by only @emph{reading} it without the
+opportunity to apply it in a real example.
+
+@end itemize
+
+There is a list of inactive projects in the @ref{Attic}.  We list
+projects there that are still considered valuable but for which there
+are currently no mentors available.
+
+@divEnd
 
 @node Authors
 @unnumberedsec Authors
@@ -1309,3 +1395,70 @@ Developers' changelogs by version:
 @miscLink{CHANGES-0.0,v0.0}
 
 @divEnd
+
+@divClass{column-center-middle-color2}
+@subheading Unused Google Summer of Code project suggestions
+
+The following list describes GSoC projects that had been proposed
+in recent years and which are still considered valuable but for
+which we currently don't have mentors available.
+
+@divEnd
+
+@divClass{column-center-middle-color3}
+@subheading Improve slurs and ties
+
+The engraving quality of slurs and ties is often unsatisfactory. Ties
+@q{broken} by clef or staff changes are not handled well.  The project
+could include collecting and sorting examples of bad output, deciding on
+the intended output and writing code to improve them.
+
+@strong{Difficulty:} hard
+@strong{Requirements:} C++, experience with writing heuristics
+@strong{Recommended knowledge:} LilyPond knowledge, aesthetic sense
+
+
+@divEnd
+
+@divClass{column-center-middle-color3}
+@subheading Grace notes
+
+Fix problems with synchronization of grace notes.  Grace notes can
+interfere with LilyPond's timing and cause odd effects, especially when
+multiple staffs are used where some have grace notes and others don't.
+This is one of the longest-standing and one of the more embarrassing
+@uref{https://sourceforge.net/p/testlilyissues/issues/34/,bugs} in
+LilyPond.
+
+@strong{Difficulty:} medium
+@strong{Requirements:} C++, MIDI
+@strong{Recommended:} familiarity with LilyPond internals
+
+@divEnd
+
+@divClass{column-center-middle-color3}
+@subheading Improve default beam positioning
+
+For regular, cross-staff, broken and kneed beams.  Beaming should depend
+on context and neighbor notes (see section 2.2 of
+@uref{http://imslp.org/wiki/Repository_of_Music-Notation_Mistakes_%28Coulon%2C_Jean-Pierre%29,
+this book}).  If possible also reduce beaming-computation time.
+
+@strong{Difficulty:} medium
+@strong{Requirements:} C++, experience with writing heuristics
+@strong{Recommended knowledge:} aesthetic sense
+
+@divEnd
+
+@divClass{column-center-middle-color3}
+@subheading Help improve compilation behavior
+
+Automatic code analysis tools, like valgrind memory leak detection or
+callgrind code profilers, provide valuable information about possible
+flaws in our C++ code.  Cleaning up warnings would allow us to automate
+the rejection of any patch which introduced extra warnings.
+
+@strong{Difficulty:} medium
+@strong{Requirements:} C++
+
+@divEnd
index 9ad5c848f9809167634c3a6fbfc935c5b0961f62..702926d0aa83ed32d2fd8af58eada3b730c0f2bb 100644 (file)
@@ -9,10 +9,10 @@
 @c used for news about the upcoming release; see CG on Release Work
 
 @newsItem
-@subheading LilyPond 2.19.54 released  @emph{January 4, 2017}
+@subheading LilyPond 2.19.55 released  @emph{February 12, 2017}
 
 We are happy to announce the release of LilyPond
-2.19.54.  This release includes a number of enhancements, and contains some
+2.19.55.  This release includes a number of enhancements, and contains some
 work in progress.  You will have access to the very latest features, but
 some may be incomplete, and you may encounter bugs and crashes.  If you
 require a stable version of LilyPond, we recommend using the 2.18
index fe0e1de4a12395bf17cc9550f2433c637620945c..93d8f8b2cfd5b0a8fc21f148c74cfd535f710520 100644 (file)
@@ -11,7 +11,7 @@
 @ifclear web_version
   @c no anchor links, just link to News page
 
-@ref{News, LilyPond 2.19.54 released - @emph{January 4, 2017}}
+@ref{News, LilyPond 2.19.55 released - @emph{February 12, 2017}}
 
 @ref{News, Two LilyPond projects in Google Summer of Code 2016 - @emph{April 23, 2016}}
 
@@ -23,8 +23,8 @@
 @ifset web_version
   @c anchor links, link to individual news items by their <a> tag
 
-@uref{news.html#LilyPond-2_002e19_002e54-released-January-4_002c-2017,
-  LilyPond 2.19.54 released - @emph{January 4, 2017}}
+@uref{news.html#LilyPond-2_002e19_002e55-released-February-12_002c-2017,
+  LilyPond 2.19.55 released - @emph{February 12, 2017}}
 
 @uref{news.html#Two-LilyPond-projects-in-Google-Summer-of-Code-2016-April-23_002c-2016,
   Two LilyPond projects in Google Summer of Code 2016 - @emph{April 23, 2016}}
index 20a91fa78020e3993e18c2b13e1ad09b2606d6ce..a7eab7446cf0602d2bb380964da7d0096f25046f 100644 (file)
@@ -26,6 +26,18 @@ NOTE:
   * don't duplicate entries from news-front.itexi
 @end ignore
 
+@newsItem
+@subheading LilyPond 2.19.54 released  @emph{January 4, 2017}
+
+We are happy to announce the release of LilyPond
+2.19.54.  This release includes a number of enhancements, and contains some
+work in progress.  You will have access to the very latest features, but
+some may be incomplete, and you may encounter bugs and crashes.  If you
+require a stable version of LilyPond, we recommend using the 2.18
+version.
+
+@newsEnd
+
 @newsItem
 @subheading LilyPond 2.19.53 released  @emph{December 17, 2016}
 
diff --git a/VERSION b/VERSION
index b2f2cc0fae39d8af542d070d5c742b2806f3b049..004381f83ef5693d7aad89e18c3f0d2d4028e3dc 100644 (file)
--- a/VERSION
+++ b/VERSION
@@ -1,7 +1,7 @@
 PACKAGE_NAME=LilyPond
 MAJOR_VERSION=2
 MINOR_VERSION=19
-PATCH_LEVEL=55
+PATCH_LEVEL=56
 MY_PATCH_LEVEL=
 VERSION_STABLE=2.18.2
-VERSION_DEVEL=2.19.54
+VERSION_DEVEL=2.19.55
index 6afa49715fa54bb861c6bdc77eaa3e45fb3d12b3..244db944b0c5348c8db302b2620f2cb02b2b2f20 100644 (file)
@@ -15,11 +15,17 @@ is not terminated upon encountering a rest. "
 <<
   \new Voice = "one" \relative {
     c''4\melisma 
-    c4 r c\melismaEnd c
+    c4 r c\melismaEnd c1
+    c4 \melisma
+    c4 r c\melismaEnd c1
+    c4 \melisma
+    c4 r c\melismaEnd c1
   }
   \new Lyrics \lyricsto "one" {
+    Test __ "default"
     \set extendersOverRests = ##t 
-
-    Test __ end
+    test __ \markup \typewriter "#t"
+    \set extendersOverRests = ##f
+    test __ \markup \typewriter "#f"
   }
 >>
index d97d215363db1d3f07414365b404e0122d408097..71bc1ff61d9da6f4f56d664cc293db24e502026c 100644 (file)
@@ -97,7 +97,7 @@ start and stop.")
        (ly:spanner-set-bound! spanner RIGHT item)))
 
 #(define (axis-offset-symbol axis)
-   (if (eq? axis X) 'X-offset 'Y-offset))
+   (if (eqv? axis X) 'X-offset 'Y-offset))
 
 #(define (set-axis! grob axis)
   (if (not (number? (ly:grob-property grob 'side-axis)))
@@ -105,7 +105,7 @@ start and stop.")
         (set! (ly:grob-property grob 'side-axis) axis)
         (ly:grob-chain-callback
          grob
-         (if (eq? axis X)
+         (if (eqv? axis X)
              ly:side-position-interface::x-aligned-side
              side-position-interface::y-aligned-side)
          (axis-offset-symbol axis)))))
index 1be735b0ed2dab1d7478370fb38d2daa59bf4be9..003b37ff318f56f11638bb099ffbfffe76efb7fc 100644 (file)
@@ -103,7 +103,8 @@ public:
   in grobs should always store ly_deep_copy ()s of those.
 */
 
-Accidental_engraver::Accidental_engraver ()
+Accidental_engraver::Accidental_engraver (Context *c)
+  : Engraver (c)
 {
   accidental_placement_ = 0;
   last_keysig_ = SCM_EOL;
@@ -314,7 +315,7 @@ Accidental_engraver::make_standard_accidental (Stream_event * /* note */,
   */
   for (vsize i = 0; i < left_objects_.size (); i++)
     {
-      if (scm_is_eq (left_objects_[i]->get_property ("side-axis"), scm_from_int (X_AXIS)))
+      if (ly_is_equal (left_objects_[i]->get_property ("side-axis"), scm_from_int (X_AXIS)))
         Side_position_interface::add_support (left_objects_[i], a);
     }
 
@@ -507,7 +508,7 @@ void
 Accidental_engraver::process_music ()
 {
   SCM sig = get_property ("keyAlterations");
-  if (last_keysig_ != sig)
+  if (!scm_is_eq (last_keysig_, sig))
     update_local_key_signature (sig);
 }
 
index 665c83a4cc51c6b5648df8ee06565aaf6f9a093e..50cebbbf99a06a4d00c48b5ba12eff5df07e5674 100644 (file)
@@ -88,7 +88,8 @@ Ambitus_engraver::create_ambitus ()
   is_typeset_ = false;
 }
 
-Ambitus_engraver::Ambitus_engraver ()
+Ambitus_engraver::Ambitus_engraver (Context *c)
+  : Engraver (c)
 {
   ambitus_ = 0;
   heads_.set (0, 0);
index d308a430686a6dc085685b4ac1f68304eb6621fe..e0face3d7a0d82fc4a8ee9c235d1cd1053a167be 100644 (file)
@@ -49,7 +49,8 @@ private:
   Stream_event *arpeggio_event_;
 };
 
-Arpeggio_engraver::Arpeggio_engraver ()
+Arpeggio_engraver::Arpeggio_engraver (Context *c)
+  : Engraver (c)
 {
   arpeggio_ = 0;
   arpeggio_event_ = 0;
index 3f03362b3b4645a7517aebb0a51e35ef6b97ac97..2c61f00959b3283568bf6550508949f688555f60 100644 (file)
@@ -147,7 +147,8 @@ Auto_beam_engraver::process_music ()
     }
 }
 
-Auto_beam_engraver::Auto_beam_engraver ()
+Auto_beam_engraver::Auto_beam_engraver (Context *c)
+  : Engraver (c)
 {
   forbid_ = 0;
   process_acknowledged_count_ = 0;
@@ -589,7 +590,8 @@ private:
   virtual bool test_moment (Direction, Moment, Moment);
 };
 
-Grace_auto_beam_engraver::Grace_auto_beam_engraver ()
+Grace_auto_beam_engraver::Grace_auto_beam_engraver (Context *c)
+  : Auto_beam_engraver (c)
 {
   last_grace_start_.main_part_.set_infinite (-1);
   // grace_part_ is zero -> test_moment is false, last_grace_position_
index 2a5f71e275cc15f30309ed0d141f0471fabb7882..d500c6ba64fea97a2f96e362143137ecd01a429e 100644 (file)
@@ -55,7 +55,8 @@ public:
 };
 
 
-Axis_group_engraver::Axis_group_engraver ()
+Axis_group_engraver::Axis_group_engraver (Context *c)
+  : Engraver (c)
 {
   staffline_ = 0;
   interesting_ = SCM_EOL;
index 38a193caf63dfc4659dc10a1245d2c9ab2785c69..ac6f85feb8e25bb810875d47567708194d762cd3 100644 (file)
@@ -946,7 +946,7 @@ Axis_group_interface::skyline_spacing (Grob *me)
       vector<Grob *> current_elts;
       current_elts.push_back (elements[i]);
       while (i + 1 < elements.size ()
-             && scm_is_eq (elements[i + 1]->get_property ("outside-staff-priority"), priority))
+             && ly_is_equal (elements[i + 1]->get_property ("outside-staff-priority"), priority))
         {
           if (!to_boolean (elements[i + 1]->get_property ("cross-staff")))
             current_elts.push_back (elements[i + 1]);
index 4f0f136db05b8ca6f5edf72bfd9ead489859b34f..610a9906f0213b520b07eb82f2f406e6ca426ecf 100644 (file)
@@ -49,7 +49,8 @@ Balloon_engraver::stop_translation_timestep ()
   events_.clear ();
 }
 
-Balloon_engraver::Balloon_engraver ()
+Balloon_engraver::Balloon_engraver (Context *c)
+  : Engraver (c)
 {
 }
 
index 8feb63dd134fa873d229fc4e3f4b10ecd98ca9c6..fb39ae4955c5f301f141bc32b527362cfa74b759 100644 (file)
@@ -47,7 +47,8 @@ private:
   vector<Spanner *> spanners_;
 };
 
-Bar_engraver::Bar_engraver ()
+Bar_engraver::Bar_engraver (Context *c)
+  : Engraver (c)
 {
   bar_ = 0;
 }
index 1af5f19da1777115acda72facd0dd63d630a1c68..44f155df6e24298ca81a6f20c45b8b63904abd74 100644 (file)
@@ -135,7 +135,8 @@ Bar_number_engraver::process_music ()
     }
 }
 
-Bar_number_engraver::Bar_number_engraver ()
+Bar_number_engraver::Bar_number_engraver (Context *c)
+  : Engraver (c)
 {
   text_ = 0;
   alternative_starting_bar_number_ = 0;
index 31f96b72b17b4f406d2f87720b6af847bab55f23..4494bb03c2d3fd2397a8deb5917840451975cce8 100644 (file)
@@ -49,7 +49,9 @@ public:
   TRANSLATOR_DECLARATIONS (Beam_collision_engraver);
 };
 
-Beam_collision_engraver::Beam_collision_engraver () {}
+Beam_collision_engraver::Beam_collision_engraver (Context *c)
+  : Engraver (c)
+{}
 
 bool
 Beam_collision_engraver::covered_grob_has_interface (Grob *covered_grob, Grob *beam)
index 9b4df64d9c9b9d1c055e1e1c6711f4d329be28b0..f252eea5e2a1037c715ac72ef3aaf700bea8a0c0 100644 (file)
@@ -100,7 +100,8 @@ Beam_engraver::valid_end_point ()
   return valid_start_point ();
 }
 
-Beam_engraver::Beam_engraver ()
+Beam_engraver::Beam_engraver (Context *c)
+  : Engraver (c)
 {
   beam_ = 0;
   finished_beam_ = 0;
@@ -349,7 +350,8 @@ protected:
   virtual bool valid_end_point ();
 };
 
-Grace_beam_engraver::Grace_beam_engraver ()
+Grace_beam_engraver::Grace_beam_engraver (Context *c)
+  : Beam_engraver (c)
 {
 }
 
index 0970e8b5e74831d5767b2e8367f7d00eb8c55fff..dad58500ca317b0dbe1ce6a52f6cabeada609ea0 100644 (file)
@@ -42,7 +42,8 @@ private:
   bool beam_;
 };
 
-Beam_performer::Beam_performer ()
+Beam_performer::Beam_performer (Context *c)
+  : Performer (c)
 {
   beam_ = false;
   start_ev_ = 0;
index 83c98a94e082a612a18d6c30c3d3935e090b7285..f9eaaa71f4bed96eb985f7f07782527dc9b7ad63 100644 (file)
@@ -107,7 +107,8 @@ Bend_engraver::acknowledge_note_head (Grob_info info)
                                                 now_mom ());
 }
 
-Bend_engraver::Bend_engraver ()
+Bend_engraver::Bend_engraver (Context *c)
+  : Engraver (c)
 {
   fall_ = 0;
   last_fall_ = 0;
index af0cb6263221e745f6b5d27d2dce49ba6fa9668c..c63f47dd078b49597c22ee8aeaef54368cb564d6 100644 (file)
@@ -152,7 +152,7 @@ LY_DEFINE (ly_book_header, "ly:book-header",
 {
   LY_ASSERT_SMOB (Book, book, 1);
   Book *b = unsmob<Book> (book);
-  return b->header_ ? b->header_ : SCM_BOOL_F;
+  return ly_is_module (b->header_) ? b->header_ : SCM_BOOL_F;
 }
 
 LY_DEFINE (ly_book_set_header_x, "ly:book-set-header!",
index 55a638da870283b10b8446695221264a581c8991..160f6fe7ec2b62244ba323960f08b605ac9249bf 100644 (file)
@@ -53,7 +53,8 @@ Break_align_engraver::stop_translation_timestep ()
   left_edge_ = 0;
 }
 
-Break_align_engraver::Break_align_engraver ()
+Break_align_engraver::Break_align_engraver (Context *c)
+  : Engraver (c)
 {
   column_alist_ = SCM_EOL;
   left_edge_ = 0;
index e2a546f6a676ed1ecbbbc85ef56414aea512e0a2..a1d7606445353ece111cbf221a4bc9eda9257f53 100644 (file)
@@ -73,7 +73,7 @@ Break_alignment_interface::ordered_elements (Grob *grob)
       for (vsize i = writable_elts.size (); i--;)
         {
           Grob *g = writable_elts[i];
-          if (g && sym == g->get_property ("break-align-symbol"))
+          if (g && scm_is_eq (sym, g->get_property ("break-align-symbol")))
             {
               new_elts.push_back (g);
               writable_elts.erase (writable_elts.begin () + i);
@@ -277,9 +277,10 @@ Break_alignable_interface::self_align_callback (SCM grob)
       SCM sym = scm_car (symbol_list);
       for (vsize i = 0; i < elements.size (); i++)
         {
-          if (elements[i]->get_property ("break-align-symbol") == sym)
+          if (scm_is_eq (sym, elements[i]->get_property ("break-align-symbol")))
             {
               if (Item::break_visible (elements[i])
+                  // TODO SCM: simplify syntax?
                   && !elements[i]->extent (elements[i], X_AXIS).is_empty ())
                 {
                   break_aligned_grob = i;
index ade1b15f297ea1dd4f32a1bfc1437c51fce8935e..917a47d4f6caa54a65c5ac6952b7a10093f121ed 100644 (file)
@@ -45,7 +45,8 @@ private:
   Grob *breathing_sign_;
 };
 
-Breathing_sign_engraver::Breathing_sign_engraver ()
+Breathing_sign_engraver::Breathing_sign_engraver (Context *c)
+  : Engraver (c)
 {
   breathing_sign_ = 0;
   breathing_sign_event_ = 0;
index 3a14ff4b07f44168ce5117712d7e99e73812cc91..3d989ccfb14de07ee33cf981f0e5e67ed338a3cb 100644 (file)
@@ -52,7 +52,8 @@ Chord_name_engraver::finalize ()
 {
 }
 
-Chord_name_engraver::Chord_name_engraver ()
+Chord_name_engraver::Chord_name_engraver (Context *c)
+  : Engraver (c)
 {
   rest_event_ = 0;
 }
index 7a17c1350e36567857acb983eeda04695df3827f..9e48a1a4908d5a21bf0c0e59a9242483979f4dd3 100644 (file)
@@ -66,7 +66,8 @@ protected:
   void acknowledge_stem (Grob_info);
 };
 
-Chord_tremolo_engraver::Chord_tremolo_engraver ()
+Chord_tremolo_engraver::Chord_tremolo_engraver (Context *c)
+  : Engraver (c)
 {
   beam_ = 0;
   repeat_ = 0;
index 00b3c3e55a736ef930d8d048afe30c2d74869df3..05c9420623b99047d49451c20528525bf0d32335 100644 (file)
@@ -62,7 +62,8 @@ Clef_engraver::derived_mark () const
   scm_gc_mark (prev_glyph_);
 }
 
-Clef_engraver::Clef_engraver ()
+Clef_engraver::Clef_engraver (Context *c)
+  : Engraver (c)
 {
   clef_ = 0;
   modifier_ = 0;
@@ -190,12 +191,13 @@ Clef_engraver::stop_translation_timestep ()
 {
   if (clef_)
     {
-      SCM vis = 0;
       if (to_boolean (clef_->get_property ("non-default")))
-        vis = get_property ("explicitClefVisibility");
+        {
+          SCM vis = get_property ("explicitClefVisibility");
 
-      if (vis)
-        clef_->set_property ("break-visibility", vis);
+          if (scm_is_vector (vis))
+            clef_->set_property ("break-visibility", vis);
+        }
 
       clef_ = 0;
 
index 0c84d1cb650019a32607e4744588715ea3b4d09e..e8ba45121229d414c83e0449ef07a5d2bd9b322d 100644 (file)
@@ -48,7 +48,8 @@ private:
   Spanner *finished_spanner_;
 };
 
-Cluster_spanner_engraver::Cluster_spanner_engraver ()
+Cluster_spanner_engraver::Cluster_spanner_engraver (Context *c)
+  : Engraver (c)
 {
   spanner_ = 0;
   finished_spanner_ = 0;
index ca6a52d320a09dde5c5ff326611bfe4309ded81b..15ee2d29239711fd3eda3b02413626078e2b52ab 100644 (file)
@@ -73,7 +73,8 @@ Collision_engraver::stop_translation_timestep ()
   note_columns_.clear ();
 }
 
-Collision_engraver::Collision_engraver ()
+Collision_engraver::Collision_engraver (Context *c)
+  : Engraver (c)
 {
   col_ = 0;
 }
index ef3a5012a26cbc5a77d192904ffb216d5082c4ab..18b51cd4ec9440217301156565d22dc11addf128 100644 (file)
@@ -301,7 +301,8 @@ Completion_heads_engraver::start_translation_timestep ()
                             ly_bool2scm (note_events_.size ()));
 }
 
-Completion_heads_engraver::Completion_heads_engraver ()
+Completion_heads_engraver::Completion_heads_engraver (Context *c)
+  : Engraver (c)
 {
   tie_column_ = 0;
 }
index 2b5693916e96ee25e02d0d1ff9a4882e50b51b1d..c3b8b10955d767404e34ee2d87bccc0a005e8e82 100644 (file)
@@ -253,7 +253,8 @@ Completion_rest_engraver::start_translation_timestep ()
                             ly_bool2scm (rest_events_.size ()));
 }
 
-Completion_rest_engraver::Completion_rest_engraver ()
+Completion_rest_engraver::Completion_rest_engraver (Context *c)
+  : Engraver (c)
 {
 }
 
index 3fdf6524c243f6745fa93883b7b46223528c1ca7..17cd90196eb5f02204b556ca0205dd81b7e85a8c 100644 (file)
@@ -46,7 +46,8 @@ private:
   vector<Grob *> hairpins_hanging_out_;
 };
 
-Concurrent_hairpin_engraver::Concurrent_hairpin_engraver ()
+Concurrent_hairpin_engraver::Concurrent_hairpin_engraver (Context *c)
+  : Engraver (c)
 {
 }
 
index 402bd80b6e8baf329b52b07c16275751f8c0b95b..72ddf6d37b32e816b0bf585a2fede4f41b429915 100644 (file)
@@ -291,11 +291,8 @@ Context_def::get_translator_names (SCM user_mod) const
 
       if (scm_is_eq (tag, ly_symbol2scm ("consists")))
         l1 = scm_cons (arg, l1);
-      else if (scm_is_eq (tag, ly_symbol2scm ("remove"))
-               && (scm_is_pair (arg)
-                   || ly_is_procedure (arg)
-                   || get_translator (arg)))
-        l1 = scm_delete_x (arg, l1);
+      else if (scm_is_eq (tag, ly_symbol2scm ("remove")))
+        l1 = scm_delq_x (arg, l1);
     }
 
   return l1;
index db6efe649ed5b3fa15c6155d51e8d8084e51b14f..3846e3102da6c8c0ce2572480ee49d878b70efd9 100644 (file)
@@ -21,7 +21,8 @@ protected:
   virtual void acknowledge_audio_element (Audio_element_info info);
 };
 
-Control_track_performer::Control_track_performer ()
+Control_track_performer::Control_track_performer (Context *c)
+  : Performer (c)
 {
   control_track_ = 0;
 }
index 53640afadc17264e62e765b6a1f238d592e5e548..cf7f0bd9681f7715b96f78b409f32ddb1121a153 100644 (file)
@@ -66,7 +66,8 @@ Cue_clef_engraver::derived_mark () const
   scm_gc_mark (prev_glyph_);
 }
 
-Cue_clef_engraver::Cue_clef_engraver ()
+Cue_clef_engraver::Cue_clef_engraver (Context *c)
+  : Engraver (c)
 {
   clef_ = 0;
   modifier_ = 0;
@@ -197,12 +198,13 @@ Cue_clef_engraver::stop_translation_timestep ()
 {
   if (clef_)
     {
-      SCM vis = 0;
       if (to_boolean (clef_->get_property ("non-default")))
-        vis = get_property ("explicitCueClefVisibility");
+        {
+          SCM vis = get_property ("explicitCueClefVisibility");
 
-      if (vis)
-        clef_->set_property ("break-visibility", vis);
+          if (scm_is_vector (vis))
+            clef_->set_property ("break-visibility", vis);
+        }
 
       clef_ = 0;
       modifier_ = 0;
index a21ad4eb787ee8c9a4a91047abad40ffaa802601..7d15aeaba85a77e91f5b772eeace86aafbd5fc1d 100644 (file)
@@ -52,7 +52,8 @@ private:
   vector<Pitch> pitches_;
 };
 
-Custos_engraver::Custos_engraver ()
+Custos_engraver::Custos_engraver (Context *c)
+  : Engraver (c)
 {
   custos_permitted_ = false;
 }
index a8b9898276c518ea263b3663e67d1df37b7bcdc5..f3d1d595057499d390e02fe72f76357d3f075816 100644 (file)
@@ -65,7 +65,8 @@ ADD_TRANSLATOR (Default_bar_line_engraver,
                 ""
                );
 
-Default_bar_line_engraver::Default_bar_line_engraver ()
+Default_bar_line_engraver::Default_bar_line_engraver (Context *c)
+  : Engraver (c)
 {
   last_moment_.main_part_ = Rational (-1);
 }
index c5c80015249791f858e82ba1499e820122be975a..2e905fe405f4377c92c5e2bfbf2d3ab0cbea3690 100644 (file)
@@ -37,7 +37,8 @@ protected:
   void stop_translation_timestep ();
 };
 
-Dot_column_engraver::Dot_column_engraver ()
+Dot_column_engraver::Dot_column_engraver (Context *c)
+  : Engraver (c)
 {
   dotcol_ = 0;
 }
index cbd6c718a9e944bcc70b245b64b88045575c4ed6..eb0f48722637577644b3274ce7c03e0747233fc8 100644 (file)
@@ -31,7 +31,8 @@ class Dots_engraver : public Engraver
   TRANSLATOR_DECLARATIONS (Dots_engraver);
 };
 
-Dots_engraver::Dots_engraver ()
+Dots_engraver::Dots_engraver (Context *c)
+  : Engraver (c)
 {
 }
 
index d1717f8314a96f68b67cb85367f8a79910673767..ec927c9eee5e733b117cf805dbb6c9b774dc4c77 100644 (file)
@@ -43,7 +43,8 @@ protected:
   void process_music ();
 };
 
-Double_percent_repeat_engraver::Double_percent_repeat_engraver ()
+Double_percent_repeat_engraver::Double_percent_repeat_engraver (Context *c)
+  : Engraver (c)
 {
   percent_event_ = 0;
 }
index 16b089cb703cca7877766b9e16ed202929357fbb..73bec0ed9f83f171ea060e9b74a7295ad4cf1c21 100644 (file)
@@ -49,7 +49,8 @@ protected:
   void stop_translation_timestep ();
 };
 
-Drum_notes_engraver::Drum_notes_engraver ()
+Drum_notes_engraver::Drum_notes_engraver (Context *c)
+  : Engraver (c)
 {
 }
 
@@ -62,12 +63,12 @@ Drum_notes_engraver::listen_note (Stream_event *ev)
 void
 Drum_notes_engraver::process_music ()
 {
-  SCM tab = 0;
+  if (events_.empty ())
+    return;
+
+  SCM tab = get_property ("drumStyleTable");
   for (vsize i = 0; i < events_.size (); i++)
     {
-      if (!tab)
-        tab = get_property ("drumStyleTable");
-
       Stream_event *ev = events_[i];
       Item *note = make_item ("NoteHead", ev->self_scm ());
 
index 93f648f3d765b4047afc23803e1e6eb8eda3a840..9fce62808fe910892b122b99831e53bb7370894d 100644 (file)
@@ -38,7 +38,8 @@ private:
   vector<Stream_event *> note_evs_;
 };
 
-Drum_note_performer::Drum_note_performer ()
+Drum_note_performer::Drum_note_performer (Context *c)
+  : Performer (c)
 {
 }
 
index c276e217593e7b209e1cce5f47b15a8610dd8e1b..ae3f968c58084d7dd94a16e31590b822b45d0ad4 100644 (file)
@@ -57,7 +57,8 @@ private:
   set<Spanner *> running_;
 };
 
-Dynamic_align_engraver::Dynamic_align_engraver ()
+Dynamic_align_engraver::Dynamic_align_engraver (Context *c)
+  : Engraver (c)
 {
   line_ = 0;
   ended_line_ = 0;
index 5d4ef33de3aee6f282176fd92d3f82baf23966dc..686fbc5a6869f4095ccc091c58d748e04a2b8a3d 100644 (file)
@@ -58,7 +58,8 @@ private:
   bool end_new_spanner_;
 };
 
-Dynamic_engraver::Dynamic_engraver ()
+Dynamic_engraver::Dynamic_engraver (Context *c)
+  : Engraver (c)
 {
   script_event_ = 0;
   current_span_event_ = 0;
index 23b7d43bfd4b104974691877bb08dbf71125daa3..2a2a1fbd2a2af41b63aa76b8bb68e5e42a865ab2 100644 (file)
@@ -123,8 +123,9 @@ private:
   State state_;
 };
 
-Dynamic_performer::Dynamic_performer ()
-  : script_event_ (0),
+Dynamic_performer::Dynamic_performer (Context *c)
+  : Performer (c),
+    script_event_ (0),
     next_grow_dir_ (CENTER),
     depart_dir_ (CENTER),
     state_ (STATE_INITIAL)
index daf055ccf71141ea0df2e2c8e2a5843e93d082d1..59c91306ef39496f5f729273686c0d58def2ab68 100644 (file)
@@ -81,7 +81,8 @@ Engraver::announce_end_grob (Grob *e, SCM cause)
   announce_end_grob (make_grob_info (e, cause));
 }
 
-Engraver::Engraver ()
+Engraver::Engraver (Context *c)
+  : Translator (c)
 {
 }
 
index d2fc2f398f9ac8856a0ef4b69cf2e5d3392edb20..b58379482935219386b277c199f7ee81250e43b7 100644 (file)
@@ -48,7 +48,8 @@ private:
   void typeset_all ();
 };
 
-Episema_engraver::Episema_engraver ()
+Episema_engraver::Episema_engraver (Context *c)
+  : Engraver (c)
 {
   finished_ = 0;
   current_event_ = 0;
index 39fa7788dedb87fa6a4ff5344c865f9c963383c3..624a6bc062e809b734849058c1d410f323bd72b8 100644 (file)
@@ -53,7 +53,8 @@ protected:
   void process_music ();
 };
 
-Extender_engraver::Extender_engraver ()
+Extender_engraver::Extender_engraver (Context *c)
+  : Engraver (c)
 {
   extender_ = 0;
   pending_extender_ = 0;
@@ -129,7 +130,7 @@ Extender_engraver::stop_translation_timestep ()
       else
         {
           if (pending_extender_
-              && !get_property ("extendersOverRests"))
+              && !to_boolean (get_property ("extendersOverRests")))
             {
               completize_extender (pending_extender_);
               pending_extender_ = 0;
index 9785f3fef47e763efc7acc2da7636ed7e20a7b72..b2a79262bb64727f7b4421dfb54981032f01e278 100644 (file)
@@ -132,7 +132,8 @@ protected:
   void process_music ();
 };
 
-Figured_bass_engraver::Figured_bass_engraver ()
+Figured_bass_engraver::Figured_bass_engraver (Context *c)
+  : Engraver (c)
 {
   alignment_ = 0;
   continuation_ = false;
index 66fabb1ffb6d4a0a316aeccb31bec741bfefd759..b35d037a35fb0ca8442a3fc3ad90db2b264e4e53 100644 (file)
@@ -49,7 +49,8 @@ protected:
   void stop_translation_timestep ();
 };
 
-Figured_bass_position_engraver::Figured_bass_position_engraver ()
+Figured_bass_position_engraver::Figured_bass_position_engraver (Context *c)
+  : Engraver (c)
 {
   positioner_ = 0;
   bass_figure_alignment_ = 0;
index a2a37143b37a81efc59482fda913b1b7c7eddf20..5662dfbf709b404b5478474ff176a77bd7b371e3 100644 (file)
@@ -42,7 +42,8 @@ protected:
   void stop_translation_timestep ();
 };
 
-Fingering_column_engraver::Fingering_column_engraver ()
+Fingering_column_engraver::Fingering_column_engraver (Context *c)
+  : Engraver (c)
 {
   for (LEFT_and_RIGHT (d))
     fingering_columns_[d] = 0;
index 8de44e96984ed22d18a504a1d5fe41bc9118d8bc..4f40bff00e7a1048aed2b02fdc63e088ad14fa29 100644 (file)
@@ -136,7 +136,8 @@ Fingering_engraver::stop_translation_timestep ()
   events_.clear ();
 }
 
-Fingering_engraver::Fingering_engraver ()
+Fingering_engraver::Fingering_engraver (Context *c)
+  : Engraver (c)
 {
 }
 
index 4dfd24d01444a561a2485f6001aeb9f14f57c8d3..3889a89e3b793fbb2c903a232a0fe7c78aeeabcb 100644 (file)
@@ -31,7 +31,8 @@ protected:
 private:
 };
 
-Font_size_engraver::Font_size_engraver ()
+Font_size_engraver::Font_size_engraver (Context *c)
+  : Engraver (c)
 {
   size = 0.0;
 }
index e80d9b64cec69b8016a4a2aca5cb5bdfb4f924f5..ea5c4781b55532da20566082a7e6b2dc5b386349 100644 (file)
@@ -49,7 +49,8 @@ Footnote_engraver::finalize ()
   annotated_spanners_.clear ();
 }
 
-Footnote_engraver::Footnote_engraver ()
+Footnote_engraver::Footnote_engraver (Context *c)
+  : Engraver (c)
 {
 }
 
index 9cfdef24c82566634160bc4d22ba655e2be1e9e2..c5e4b7b06e4096ea394170a89d5aaf778d189641 100644 (file)
@@ -33,7 +33,8 @@ public:
   void start_translation_timestep ();
 };
 
-Forbid_line_break_engraver::Forbid_line_break_engraver ()
+Forbid_line_break_engraver::Forbid_line_break_engraver (Context *c)
+  : Engraver (c)
 {
 }
 
index 18843fc87c6d3c2d9829c6b29f1f337d85cd14f2..28b4bd1931f208e544ee219ee2eb7a65556d10ab 100644 (file)
@@ -62,7 +62,8 @@ Fretboard_engraver::derived_mark () const
   scm_gc_mark (last_placements_);
 }
 
-Fretboard_engraver::Fretboard_engraver ()
+Fretboard_engraver::Fretboard_engraver (Context *c)
+  : Engraver (c)
 {
   fret_board_ = 0;
   last_placements_ = SCM_BOOL_F;
index 756f174512417ef14a58e3722d2ec84ebb72356a..99fbdfe6c8ce17838c2f58a90f1eba3517995a4d 100644 (file)
@@ -33,11 +33,12 @@ using namespace std;
 #include "music-function.hh"
 #include "paper-score.hh"
 #include "performance.hh"
+#include "protected-scm.hh"
 #include "spanner.hh"
 #include "stream-event.hh"
 #include "unpure-pure-container.hh"
 
-static SCM doc_hash_table;
+static Protected_scm doc_hash_table;
 
 void
 ly_check_name (const string &cxx, const string &scm_name)
@@ -58,8 +59,8 @@ ly_add_function_documentation (SCM func,
   if (doc == "")
     return;
 
-  if (!doc_hash_table)
-    doc_hash_table = scm_permanent_object (scm_c_make_hash_table (59));
+  if (!doc_hash_table.is_bound ())
+    doc_hash_table = scm_c_make_hash_table (59);
 
   string s = string (" - ") + "LilyPond procedure: " + fname + " " + varlist
              + "\n" + doc;
index 878e7f88b355539a7f29e1cf75aa3e3e701108be..50e0386c62abe69c30dbdf263cf3c358aebcac8c 100644 (file)
@@ -53,7 +53,8 @@ private:
   vector<vsize> note_column_2;
 };
 
-Glissando_engraver::Glissando_engraver ()
+Glissando_engraver::Glissando_engraver (Context *c)
+  : Engraver (c)
 {
   event_ = 0;
   start_glissandi_ = false;
index 57ccb1e0fa4d18202fff38f18cc002a38b0f77f8..59550ba8326c17c9c2bd5bb74360020ccd40573f 100644 (file)
@@ -41,7 +41,8 @@ protected:
   void grace_change (SCM);
 };
 
-Grace_engraver::Grace_engraver ()
+Grace_engraver::Grace_engraver (Context *c)
+  : Engraver (c)
 {
   grace_settings_ = SCM_EOL;
   last_moment_ = Moment (Rational (-1, 1));
index 445d2b0f81a7504c44df39d87efbeebd1b4be4ba..57b934953933ff0ccf30fe40f3388086aae1d27c 100644 (file)
@@ -38,7 +38,8 @@ protected:
   void stop_translation_timestep ();
 };
 
-Grace_spacing_engraver::Grace_spacing_engraver ()
+Grace_spacing_engraver::Grace_spacing_engraver (Context *c)
+  : Engraver (c)
 {
   grace_spacing_ = 0;
 }
index 4e4fc135c406010197d1ead57183781728827e08..ad8b423eb58ec4d51d74b350369601067d35bf99 100644 (file)
@@ -42,7 +42,8 @@
  * engravers for Gregorian chant will be added in the future, such as
  * Medicaea_ligature_engraver or Hufnagel_ligature_engraver.
  */
-Gregorian_ligature_engraver::Gregorian_ligature_engraver ()
+Gregorian_ligature_engraver::Gregorian_ligature_engraver (Context *c)
+  : Coherent_ligature_engraver (c)
 {
   pes_or_flexa_req_ = 0;
 }
index efecf676228f01de4c5d225f68231d5a7b3f749c..d5f0335a480f7cff62b0a2d9a6e3e3bb90d66331 100644 (file)
@@ -35,7 +35,8 @@ protected:
   void stop_translation_timestep ();
 };
 
-Grid_line_span_engraver::Grid_line_span_engraver ()
+Grid_line_span_engraver::Grid_line_span_engraver (Context *c)
+  : Engraver (c)
 {
   spanline_ = 0;
 }
index d67fb191b6463605ae35440913b6bd7d6deab823..dd8ff1bdd9ea5c18dff4085cd11ec11d04cef730 100644 (file)
@@ -44,7 +44,8 @@ Grid_point_engraver::process_music ()
     }
 }
 
-Grid_point_engraver::Grid_point_engraver ()
+Grid_point_engraver::Grid_point_engraver (Context *c)
+  : Engraver (c)
 {
 }
 
index 3d5fa39a074314ddd4413e4ad3a2c75113b0be36..11a5576169761bf4c4c436d7deb92e3b96bce9bc 100644 (file)
 
 #include "lily-guile.hh"
 #include "std-string.hh"
+#include "protected-scm.hh"
 
-static SCM all_ifaces;
+static Protected_scm all_ifaces;
 
 void
 internal_add_interface (SCM a, SCM b, SCM c)
 {
-  if (!all_ifaces)
-    {
-      SCM tab = scm_c_make_hash_table (59);
-      all_ifaces = tab;
-      scm_permanent_object (tab);
-    }
+  if (!all_ifaces.is_bound ())
+    all_ifaces = scm_c_make_hash_table (59);
 
   SCM entry = scm_list_3 (a, b, c);
 
index 25392a43556d8746b6742cded90cb9e30da521a9..a9fa75eda51d9708252519adc7f7e34b89ad9927 100644 (file)
@@ -50,7 +50,8 @@ protected:
   vector<Grob_pq_entry> started_now_;
 };
 
-Grob_pq_engraver::Grob_pq_engraver ()
+Grob_pq_engraver::Grob_pq_engraver (Context *c)
+  : Engraver (c)
 {
 }
 
@@ -144,7 +145,7 @@ Grob_pq_engraver::start_translation_timestep ()
       busy = scm_cdr (busy);
     }
 
-  if (start_busy != busy)
+  if (!scm_is_eq (start_busy, busy))
     context ()->set_property ("busyGrobs", busy);
 }
 
index d50146a2d0ddaf0061104d33252b73166d36077b..6dd34c17855f564989dcf79ccedfa9da3a6f018a 100644 (file)
@@ -43,7 +43,8 @@ public:
   void listen_note_grouping (Stream_event *);
 };
 
-Horizontal_bracket_engraver::Horizontal_bracket_engraver ()
+Horizontal_bracket_engraver::Horizontal_bracket_engraver (Context *c)
+  : Engraver (c)
 {
   pop_count_ = 0;
   push_count_ = 0;
index 19ff388963d2273934eb9a5356b1da005557aefe..20d2a7c9380d3d4cd13fbb8cbae1d2a9f98ab916 100644 (file)
@@ -51,7 +51,8 @@ protected:
   void process_music ();
 };
 
-Hyphen_engraver::Hyphen_engraver ()
+Hyphen_engraver::Hyphen_engraver (Context *c)
+  : Engraver (c)
 {
   hyphen_ = 0;
   finished_hyphen_ = 0;
index 78bfef8897e626c20daaf07353f3b6243c8f5348..fb509dcb2260115ab74339f7174b85b7aca5fdd7 100644 (file)
@@ -24,6 +24,9 @@
 class Coherent_ligature_engraver : public Ligature_engraver
 {
 public:
+  Coherent_ligature_engraver(Context *c)
+    : Ligature_engraver (c)
+  {}
   // no TRANSLATOR_DECLARATIONS (Coherent_ligature_engraver) needed
   // since this class is abstract
   TRANSLATOR_INHERIT (Ligature_engraver);
index 074b5313898e9c0ef0e0945dc6ac2bbe33df7487..cecc42ce5e8010a4b6550afb95221a5b387c33ad 100644 (file)
@@ -80,7 +80,7 @@ public:
   */
   DECLARE_CLASSNAME (Engraver);
   DECLARE_TRANSLATOR_CALLBACKS (Engraver);
-  Engraver ();
+  Engraver (Context *);
 };
 
 #define make_item(x, cause) internal_make_item (ly_symbol2scm (x), cause, __FILE__, __LINE__, __FUNCTION__)
index fcac99c32230806387c2677779e0f7b01b68a08c..f2a1334ae93c89d834700bb7b3a8959f2e34ccbe 100644 (file)
@@ -32,7 +32,7 @@ public:
   TRANSLATOR_INHERIT(Coherent_ligature_engraver);
   DECLARE_TRANSLATOR_CALLBACKS (Gregorian_ligature_engraver);
 protected:
-  Gregorian_ligature_engraver ();
+  Gregorian_ligature_engraver (Context *);
 
   void listen_pes_or_flexa (Stream_event *ev);
   virtual void build_ligature (Spanner *ligature,
index a46c3fe22a0c393ab83577561d4c6558acf79b23..6e117a2ea3f244f7531634442a95091b8637a66c 100644 (file)
@@ -26,7 +26,7 @@
 class Ligature_engraver : public Engraver
 {
 protected:
-  Ligature_engraver ();
+  Ligature_engraver (Context *c);
   void stop_translation_timestep ();
   virtual void finalize ();
 
index 6de69e16b92157352f6bd7955196ece89cd2cc93..5550fd405f6fbe9e90fe19a2e8382d80602d05cb 100644 (file)
@@ -171,6 +171,7 @@ class Time_scaled_music_iterator;
 class Time_signature_performer;
 class Timing_translator;
 class Translator;
+class Translator_creator;
 class Translator_group;
 
 #endif /* LILY_PROTO_HH */
index 70354fdbf2d845f9fe2a571339170b2c0681b43b..a19334b9bf15bb3ccdab7ee4b6298d42345ec316 100644 (file)
@@ -33,6 +33,9 @@ public:
   DECLARE_CLASSNAME (Performer);
   friend class Performer_group;
   Performer_group *get_daddy_performer () const;
+  Performer (Context *c)
+    : Translator (c)
+  { }
 
 protected:
   virtual void announce_element (Audio_element_info);
index f0f1a612378271ef1219059bf99e98438ea97736..55dcd846464836d9b945878132db74c229640009 100644 (file)
 
 #include "lily-guile.hh"
 
-void note_property_access (SCM *table, SCM sym);
-extern SCM context_property_lookup_table;
-extern SCM grob_property_lookup_table;
-extern SCM prob_property_lookup_table;
+class Protected_scm;
+
+void note_property_access (Protected_scm *table, SCM sym);
+extern Protected_scm context_property_lookup_table;
+extern Protected_scm grob_property_lookup_table;
+extern Protected_scm prob_property_lookup_table;
 extern bool profile_property_accesses;
 
 #endif /* PROFILE_HH */
index 0115cb9f9ff6e2d388dd2fc714ec5639cdcc180c..db8a151ff558854e31ad52e421a74bba7ccb228b 100644 (file)
@@ -54,6 +54,7 @@ public:
   Protected_scm &operator = (Protected_scm const &);
   operator const SCM & () const;
   operator SCM & ();
+  bool is_bound () const;  // SCM_UNBNDP balks at Protected_scm
 };
 
 #endif /* PROTECTED_SCM_HH */
index 11caf9f9c283861eff90d4a93c2eddaf6257f9ba..79e01a7e1de3a243cce7674c8966fb88e090309b 100644 (file)
@@ -41,7 +41,7 @@ class Scheme_engraver : Preinit_Scheme_engraver, public Engraver
 {
 public:
   TRANSLATOR_FAMILY_DECLARATIONS (Scheme_engraver);
-  Scheme_engraver (SCM definition);
+  Scheme_engraver (SCM definition, Context *c);
 
 protected:
   ~Scheme_engraver ();
@@ -60,9 +60,6 @@ private:
   }
 
   SCM init_acknowledgers (SCM alist);
-  // For now no description.  In future, something derived from the
-  // definition might make sense.
-  SCM translator_description () const { return SCM_EOL; }
 
   bool must_be_last_;
 };
index 8af67c0f766f039184e6ba00500d43044a58a0e7..a55c7f47e4a26bd968220cd8a748e7c35dc1de11 100644 (file)
@@ -90,6 +90,7 @@ public:
   bool is_empty () const;
   bool is_empty (Axis) const;
   Stencil in_color (Real r, Real g, Real b) const;
+  Stencil with_outline (Stencil const &ol) const;
   static SCM skylines_from_stencil (SCM, Real, Axis);
 };
 
index 09ab16865815e322e02ecd476540555d4ee81101..91bd59fe4aef5c72efe334a9687a04dd2d1626ad 100644 (file)
 #include "std-vector.hh"
 #include "protected-scm.hh"
 
+// The Translator_creator class is only for translators defined in C.
+// Its elements are callable entities taking a context argument and
+// returning a corresponding translator.
+//
+// Other translator-creating entities may be alists and functions returning
+// such alists.  Information for those, such as created grobs/properties
+// is attached via object properties.
+
+// Smob rather than Simple_smob since we want an entity for
+// property lookup.
+
+class Translator_creator : public Smob<Translator_creator>
+{
+  Translator_creator (Translator_creator const &); // don't define
+  Translator * (*allocate_)(Context *);
+  template <class T>
+  static Translator *allocate (Context *ctx);
+
+  Translator_creator (Translator * (*allocate)(Context *))
+    : allocate_(allocate)
+  {
+    smobify_self ();
+  }
+public:
+  // This is stupid, but constructors cannot have explicit template
+  // argument lists.
+  template <class T>
+  static Translator_creator *alloc()
+  {
+    return new Translator_creator(&allocate<T>);
+  }
+  SCM call (SCM ctx);
+  LY_DECLARE_SMOB_PROC (&Translator_creator::call, 1, 0, 0);
+};
+
+template <class T> Translator *
+Translator_creator::allocate (Context *ctx)
+{
+  return new T(ctx);
+}
+
 #define TRANSLATOR_FAMILY_DECLARATIONS(NAME)                            \
   public:                                                               \
-  VIRTUAL_COPY_CONSTRUCTOR (Translator, NAME);                          \
+  DECLARE_CLASSNAME (NAME);                                             \
   virtual void fetch_precomputable_methods (SCM methods[]);             \
   DECLARE_TRANSLATOR_CALLBACKS (NAME);                                  \
   TRANSLATOR_INHERIT (Translator);                                      \
   public:                                                               \
   TRANSLATOR_FAMILY_DECLARATIONS (NAME);                                \
   static Drul_array<Protected_scm> acknowledge_static_array_drul_;      \
-  static SCM static_description_;                                       \
   static Protected_scm listener_list_;                                  \
   static SCM static_get_acknowledger (SCM sym, Direction start_end);    \
   virtual SCM get_acknowledger (SCM sym, Direction start_end)           \
     return static_get_acknowledger (sym, start_end);                    \
   }                                                                     \
 public:                                                                 \
-  NAME ();                                                              \
+  NAME (Context *);                                                     \
   static void boot ();                                                  \
-  virtual SCM static_translator_description () const;                   \
-  virtual SCM translator_description () const;                          \
+  static SCM static_translator_description ();                          \
   virtual SCM get_listener_list () const                                \
   {                                                                     \
     return listener_list_;                                              \
@@ -106,14 +145,14 @@ public:
   SCM mark_smob () const;
   static const char * const type_p_name_;
   virtual ~Translator ();
-private:
-  void init ();
 
-public:
   Context *context () const { return daddy_context_; }
 
-  Translator ();
-  Translator (Translator const &);
+protected:
+  Translator (Context *);
+private:
+  Translator (Translator const &); // not copyable
+public:
 
   SCM internal_get_property (SCM symbol) const;
 
@@ -137,10 +176,9 @@ public:
   Global_context *get_global_context () const;
 
   DECLARE_CLASSNAME (Translator);
-  virtual Translator *clone () const = 0;
+
   virtual void fetch_precomputable_methods (SCM methods[]) = 0;
   virtual SCM get_listener_list () const = 0;
-  virtual SCM translator_description () const = 0;
   virtual SCM get_acknowledger (SCM sym, Direction start_end) = 0;
 
 protected:                      // should be private.
@@ -167,22 +205,22 @@ protected:                      // should be private.
 
   virtual void derived_mark () const;
   static SCM event_class_symbol (const char *ev_class);
-  SCM static_translator_description (const char *grobs,
-                                     const char *desc,
-                                     SCM listener_list,
-                                     const char *read,
-                                     const char *write) const;
+  static SCM
+  static_translator_description (const char *grobs,
+                                 const char *desc,
+                                 SCM listener_list,
+                                 const char *read,
+                                 const char *write);
 
   friend class Translator_group;
 };
 
-void add_translator (Translator *trans);
-
-Translator *get_translator (SCM s);
-
 SCM
 generic_get_acknowledger (SCM sym, SCM ack_hash);
 
+void add_translator_creator (SCM creator, SCM name, SCM description);
+
+SCM get_translator_creator (SCM s);
 Moment get_event_length (Stream_event *s, Moment now);
 Moment get_event_length (Stream_event *s);
 
index 80a7466cd18c0a6e4a41d3bfebd57143890a1f96..9bd6163fea45eec75a60c3cbdb8682517ba50caf 100644 (file)
    A macro to automate administration of translators.
 */
 #define ADD_THIS_TRANSLATOR(T)                                          \
-  SCM T::static_description_ = SCM_EOL;                                 \
   static void _ ## T ## _adder ()                                       \
   {                                                                     \
     T::boot ();                                                         \
-    T *t = new T;                                                       \
-    T::static_description_ =                                            \
-      scm_permanent_object (t->static_translator_description ());       \
-    add_translator (t);                                                 \
-  }                                                                     \
-  SCM T::translator_description () const                                \
-  {                                                                     \
-    return static_description_;                                         \
+    add_translator_creator (Translator_creator::alloc<T>()->unprotect (), \
+                            scm_from_ascii_symbol (#T),                 \
+                            T::static_translator_description ());       \
   }                                                                     \
   ADD_GLOBAL_CTOR (_ ## T ## _adder);                                   \
   /* end define */
 
-#define DEFINE_TRANSLATOR_LISTENER_LIST(T) \
-  Protected_scm T::listener_list_ (SCM_EOL)
+#define DEFINE_TRANSLATOR_LISTENER_LIST(T)                              \
+  Protected_scm T::listener_list_ (SCM_EOL);                            \
+  /* end define */
 
 #define DEFINE_ACKNOWLEDGERS(classname) \
   Drul_array<Protected_scm> classname::acknowledge_static_array_drul_;  \
@@ -61,9 +56,9 @@
   }                                                                     \
   /* end define */
 
-#define DEFINE_TRANSLATOR_DOC(classname, desc, grobs, read, write)              \
+#define DEFINE_TRANSLATOR_DOC(classname, desc, grobs, read, write)      \
   SCM                                                                   \
-  classname::static_translator_description () const                     \
+  classname::static_translator_description ()                           \
   {                                                                     \
     return Translator::static_translator_description (grobs, desc, listener_list_, read, write); \
   }
   {                                                                     \
     ptrs[START_TRANSLATION_TIMESTEP] =                                  \
       method_finder <&T::start_translation_timestep> ();                \
-                                                                       \
-    ptrs[STOP_TRANSLATION_TIMESTEP] =                                  \
+                                                                        \
+    ptrs[STOP_TRANSLATION_TIMESTEP] =                                   \
       method_finder <&T::stop_translation_timestep> ();                 \
                                                                         \
-    ptrs[PROCESS_MUSIC] =                                              \
+    ptrs[PROCESS_MUSIC] =                                               \
       method_finder <&T::process_music> ();                             \
-                                                                       \
-    ptrs[PROCESS_ACKNOWLEDGED] =                                       \
+                                                                        \
+    ptrs[PROCESS_ACKNOWLEDGED] =                                        \
       method_finder <&T::process_acknowledged> ();                      \
   }
 
@@ -115,6 +110,11 @@ void add_acknowledger (SCM ptr,
 /*
   Implement the method cl::listen_##m, and make it listen to stream
   events of class m.
+
+  At macro call time, neither creator instances (which are anonymous
+  and only accessible via the translator registry) nor translator
+  instances exist, so the only named place where we can store it is in
+  a static member of the translator class.
  */
 #define ADD_LISTENER_FOR(cl, m, ev)                                     \
   listener_list_ = scm_acons                                            \
index ec37d6bcbffc2b18d638e76cf1ead798526e8e47..8ba26f31beaf97d7b7a2e5d454c19c85e599e276 100644 (file)
@@ -59,7 +59,8 @@ Instrument_name_engraver::derived_mark () const
   scm_gc_mark (short_text_);
 }
 
-Instrument_name_engraver::Instrument_name_engraver ()
+Instrument_name_engraver::Instrument_name_engraver (Context *c)
+  : Engraver (c)
 {
   text_spanner_ = 0;
 
index 59cbb4f13cd4102eee7d9cc00af1844f55eb70b1..cfc3cd5c825e2ddc491048a177ad08ed668b7113 100644 (file)
@@ -44,7 +44,8 @@ Instrument_switch_engraver::derived_mark () const
   scm_gc_mark (cue_name_);
 }
 
-Instrument_switch_engraver::Instrument_switch_engraver ()
+Instrument_switch_engraver::Instrument_switch_engraver (Context *c)
+  : Engraver (c)
 {
   cue_name_ = SCM_EOL;
   text_ = 0;
index 8931a819c6ff45150ccb229fdec3d06b8c457426..6875cd022fa68cf9e57eb4328c6d5af9f81952ed 100644 (file)
@@ -37,7 +37,8 @@ public:
   virtual void finalize ();
 };
 
-Keep_alive_together_engraver::Keep_alive_together_engraver ()
+Keep_alive_together_engraver::Keep_alive_together_engraver (Context *c)
+  : Engraver (c)
 {
 }
 
index 115902e89db2b789f80e3d257b471c7a75f07143..a61d7701d768dbb4c28246ac72743c3d7265303a 100644 (file)
@@ -56,7 +56,8 @@ Key_engraver::finalize ()
 {
 }
 
-Key_engraver::Key_engraver ()
+Key_engraver::Key_engraver (Context *c)
+  : Engraver (c)
 {
   key_event_ = 0;
   item_ = 0;
@@ -147,7 +148,8 @@ void
 Key_engraver::process_music ()
 {
   if (key_event_
-      || get_property ("lastKeyAlterations") != get_property ("keyAlterations"))
+      || !scm_is_eq (get_property ("lastKeyAlterations"),
+                     get_property ("keyAlterations")))
     create_key (false);
 }
 
index 219454115a04dc673f2ce903d04d2be68afded22..5de378eda49832c11a8366d155044b23373912ac 100644 (file)
@@ -42,7 +42,8 @@ private:
   Audio_key *audio_;
 };
 
-Key_performer::Key_performer ()
+Key_performer::Key_performer (Context *c)
+  : Performer (c)
 {
   key_ev_ = 0;
   audio_ = 0;
index ff9e7b942b48f4fbcb1407f5f91c41d56e3ec828..162674df2efd378bc138224661fde167330b7517 100644 (file)
@@ -45,7 +45,8 @@ private:
   void fold_up_primitives (vector<Grob_info> const &primitives, Real padding, Real &min_length);
 };
 
-Kievan_ligature_engraver::Kievan_ligature_engraver ()
+Kievan_ligature_engraver::Kievan_ligature_engraver (Context *c)
+  : Coherent_ligature_engraver (c)
 {
 
 }
index e84ea36bca7b72cbbe263b3361afdd0813a6f642..2d2e2dd2e87ee0e06ae9aaa93e4072e4396d4e3f 100644 (file)
@@ -39,7 +39,8 @@ public:
   TRANSLATOR_DECLARATIONS (Laissez_vibrer_engraver);
 };
 
-Laissez_vibrer_engraver::Laissez_vibrer_engraver ()
+Laissez_vibrer_engraver::Laissez_vibrer_engraver (Context *c)
+  : Engraver (c)
 {
   event_ = 0;
   lv_column_ = 0;
index 869720cca4f8811a835c7ec00af5dd717348c706..cde6f5817cde603cca91c6d5b214cd7a739d35ac 100644 (file)
@@ -44,7 +44,8 @@ protected:
   void stop_translation_timestep ();
 };
 
-Ledger_line_engraver::Ledger_line_engraver ()
+Ledger_line_engraver::Ledger_line_engraver (Context *c)
+  : Engraver (c)
 {
   span_ = 0;
 }
index 4919071d97b92a05c01bdc960f8cc7a3e8d2002e..9e50962ddcb2473a0158068bb26f13e67ff81568 100644 (file)
@@ -53,7 +53,8 @@ Ligature_bracket_engraver::listen_ligature (Stream_event *ev)
   ASSIGN_EVENT_ONCE (events_drul_[d], ev);
 }
 
-Ligature_bracket_engraver::Ligature_bracket_engraver ()
+Ligature_bracket_engraver::Ligature_bracket_engraver (Context *c)
+  : Engraver (c)
 {
   ligature_ = 0;
   finished_ligature_ = 0;
index f3bac03c76955f62a913224224d3966aacc2016c..08d3b419962ab833b4ead2389083662d0a87f0a0 100644 (file)
@@ -82,7 +82,8 @@
  * would require to have a single, complicated Ligature_engraver that
  * consists of all the code...  This needs further thoughts.
  */
-Ligature_engraver::Ligature_engraver ()
+Ligature_engraver::Ligature_engraver (Context *c)
+  : Engraver (c)
 {
   ligature_ = 0;
   finished_ligature_ = 0;
index 08c9306693a303f83ed31dc1c51c62c013d08422..bad1203266f75b43842e6bdea358b6a734dc339f 100644 (file)
@@ -49,7 +49,8 @@ private:
   Context *get_voice_context ();
 };
 
-Lyric_engraver::Lyric_engraver ()
+Lyric_engraver::Lyric_engraver (Context *c)
+  : Engraver (c)
 {
   text_ = 0;
   last_text_ = 0;
index 6a25d62a3f99e44fd8fbff912e20b0e2e70e61d0..9ba25c5bf1f1e6c839c4a7d05b319ba8a40251be 100644 (file)
@@ -36,7 +36,8 @@ private:
   Audio_text *audio_;
 };
 
-Lyric_performer::Lyric_performer ()
+Lyric_performer::Lyric_performer (Context *c)
+  : Performer (c)
 {
   audio_ = 0;
 }
index a849ec11ce0dddd77f57c586efc0db2c8a68a3f7..2242a44f22c4ac7d045b0e434e85f4985bde0473 100644 (file)
@@ -58,7 +58,8 @@ protected:
   void acknowledge_break_alignment (Grob_info);
 };
 
-Mark_engraver::Mark_engraver ()
+Mark_engraver::Mark_engraver (Context *c)
+  : Engraver (c)
 {
   text_ = 0;
   final_text_ = 0;
index 2ab7a7bcc6092d8aa4fb5fc7ab6c029f652924eb..c91fdc63418f748af80fdd4ddd0a421758226520 100644 (file)
@@ -114,7 +114,8 @@ Measure_grouping_engraver::process_music ()
     }
 }
 
-Measure_grouping_engraver::Measure_grouping_engraver ()
+Measure_grouping_engraver::Measure_grouping_engraver (Context *c)
+  : Engraver (c)
 {
   grouping_ = 0;
 }
index a97d13755f08e777948a70394ebbd15f7c2e437b..65f464c357e16982085603a0d86013508342159d 100644 (file)
@@ -37,7 +37,8 @@ protected:
   void process_music ();
 };
 
-Melody_engraver::Melody_engraver ()
+Melody_engraver::Melody_engraver (Context *c)
+  : Engraver (c)
 {
   stem_ = 0;
   melody_item_ = 0;
index 874b2ebb35e2eacae7e99b9a7f08238e12e05318..482538c720588537f16291fc2b243b46514fe7ad 100644 (file)
@@ -73,7 +73,8 @@ private:
                            Real &min_length);
 };
 
-Mensural_ligature_engraver::Mensural_ligature_engraver ()
+Mensural_ligature_engraver::Mensural_ligature_engraver (Context *c)
+  : Coherent_ligature_engraver (c)
 {
   brew_ligature_primitive_proc
     = Mensural_ligature::brew_ligature_primitive_proc;
index 241a2da44aa0a7b990504dadc2765b97b59825c3..6cd2bfde25e73ff844e875ba6fc6b12519a2bc08 100644 (file)
@@ -53,7 +53,8 @@ protected:
   void listen_tempo_change (Stream_event *);
 };
 
-Metronome_mark_engraver::Metronome_mark_engraver ()
+Metronome_mark_engraver::Metronome_mark_engraver (Context *c)
+  : Engraver (c)
 {
   text_ = 0;
   support_ = 0;
index 2aff5d0039b8cea294172d1427e3419270f39ba7..91eddbfb6978565965cee0f0fe7f4c4eb24cd378 100644 (file)
@@ -63,7 +63,8 @@ private:
   };
 };
 
-Midi_control_change_performer::Midi_control_change_performer ()
+Midi_control_change_performer::Midi_control_change_performer (Context *c)
+  : Performer (c)
 {
 }
 
index 04ef91fc881a5744ae84615bdf2aadfe042738c5..d66779f6ffedf76071dc29b471749098bcff33c4 100644 (file)
@@ -65,8 +65,9 @@ private:
   bool first_time_;
 };
 
-Multi_measure_rest_engraver::Multi_measure_rest_engraver ()
-  : rest_ev_ (0),
+Multi_measure_rest_engraver::Multi_measure_rest_engraver (Context *c)
+  : Engraver (c),
+    rest_ev_ (0),
     mmrest_ (0),
     start_measure_ (0),
     last_command_item_ (0),
@@ -145,7 +146,7 @@ Multi_measure_rest_engraver::initialize_grobs ()
           Grob *last = 0;
           for (vsize i = 0; i < text_.size (); i++)
             {
-              if (scm_is_eq (dir, text_[i]->get_property ("direction")))
+              if (ly_is_equal (dir, text_[i]->get_property ("direction")))
                 {
                   if (last)
                     Side_position_interface::add_support (text_[i], last);
index 8b9da5596d02d5d217c397bd2b47b9b1be5c346d..ae75ff795273da024d404a76d144f10da52613bd 100644 (file)
@@ -237,7 +237,7 @@ Prob::transpose (Pitch delta)
                && scm_is_pair (val))
         new_val = ly_transpose_key_alist (val, delta.smobbed_copy ());
 
-      if (val != new_val)
+      if (!scm_is_eq (val, new_val))
         scm_set_cdr_x (entry, new_val);
     }
 }
index 047a547525ee9ac70bf484bf46bec633d8858c3b..06a3a8da9666669d7ab2d95672f167158887fe1b 100644 (file)
@@ -364,7 +364,8 @@ New_fingering_engraver::position_all ()
   articulations_.clear ();
 }
 
-New_fingering_engraver::New_fingering_engraver ()
+New_fingering_engraver::New_fingering_engraver (Context *c)
+  : Engraver (c)
 {
   stem_ = 0;
 }
index b09fe6636139ebe3a658decf524086b04437057c..f2d3ad8684346d826fc830c9462767254c8b13f9 100644 (file)
@@ -51,7 +51,8 @@ private:
   Grob *last_head_;
 };
 
-Note_head_line_engraver::Note_head_line_engraver ()
+Note_head_line_engraver::Note_head_line_engraver (Context *c)
+  : Engraver (c)
 {
   line_ = 0;
   follow_ = false;
index 5839a827eb3129045c9e5330d41dacf203ab0d67..7c82106623933eecfe502f34006149dc012b6661 100644 (file)
@@ -46,7 +46,8 @@ protected:
   void stop_translation_timestep ();
 };
 
-Note_heads_engraver::Note_heads_engraver ()
+Note_heads_engraver::Note_heads_engraver (Context *c)
+  : Engraver (c)
 {
 }
 
index 2b8fa87000c8331f6c6a02e137a176e95fb83636..1333feb4a65b380976b8bd890dc2d5f2ecb8aa09 100644 (file)
@@ -69,7 +69,8 @@ Note_name_engraver::stop_translation_timestep ()
   events_.clear ();
 }
 
-Note_name_engraver::Note_name_engraver ()
+Note_name_engraver::Note_name_engraver (Context *c)
+  : Engraver (c)
 {
 }
 
index 468210d20d0852f26a7d576dfc483defe42a277f..44efd745742744e43afa4c7e1033503058ab9ce4 100644 (file)
@@ -196,6 +196,7 @@ ADD_TRANSLATOR (Note_performer,
                 ""
                );
 
-Note_performer::Note_performer ()
+Note_performer::Note_performer (Context *c)
+  : Performer (c)
 {
 }
index 414e1ee7610cee80c76e1ead38768c21e9fbd5cb..653aa8db023f80ad804cae7c4d2ab235cbd38e51 100644 (file)
@@ -55,7 +55,8 @@ Note_spacing_engraver::derived_mark () const
     scm_gc_mark (i->first->self_scm ());
 }
 
-Note_spacing_engraver::Note_spacing_engraver ()
+Note_spacing_engraver::Note_spacing_engraver (Context *c)
+  : Engraver (c)
 {
   spacing_ = 0;
   last_spacing_ = 0;
index e681e73af6b65a661454712f47a4b535a72f6328..e9bcbe94d5ffdb3f53bd5b9da14a749e7f067dbb 100644 (file)
@@ -52,7 +52,8 @@ Ottava_spanner_engraver::derived_mark () const
   scm_gc_mark (last_ottavation_);
 }
 
-Ottava_spanner_engraver::Ottava_spanner_engraver ()
+Ottava_spanner_engraver::Ottava_spanner_engraver (Context *c)
+  : Engraver (c)
 {
   finished_ = 0;
   span_ = 0;
@@ -63,7 +64,7 @@ void
 Ottava_spanner_engraver::process_music ()
 {
   SCM ott = get_property ("ottavation");
-  if (ott != last_ottavation_)
+  if (!scm_is_eq (ott, last_ottavation_))
     {
       finished_ = span_;
       span_ = 0;
index 370d6e1c1f011400f0b8a8763083a0763e1a21f3..ccef5051f111403bc87cd5f9bf77ca23f403ff60 100644 (file)
@@ -75,7 +75,8 @@ Output_property_engraver::stop_translation_timestep ()
   props_.clear ();
 }
 
-Output_property_engraver::Output_property_engraver ()
+Output_property_engraver::Output_property_engraver (Context *c)
+  : Engraver (c)
 {
 }
 
index ef9e095d6abe144f189e39b34709d2cb490a7406..fb476848983f6a6ff0ce60ea10c014fd9e294fa0 100644 (file)
@@ -651,7 +651,7 @@ Page_breaking::make_pages (vector<vsize> lines_per_page, SCM systems)
       SCM lines = scm_caar (s);
       SCM config = scm_cdar (s);
 
-      bool bookpart_last_page = (s == systems_configs_fncounts);
+      bool bookpart_last_page = scm_is_eq (s, systems_configs_fncounts);
       SCM page = draw_page (lines, config, page_num, bookpart_last_page);
       /* collect labels */
       SCM page_num_scm = scm_from_int (page_num);
@@ -760,7 +760,7 @@ Page_breaking::find_chunks_and_breaks (Break_predicate is_break, Prob_break_pred
 
               bool last = (j == cols.size () - 1);
               bool break_point = is_break && is_break (cols[j]);
-              bool chunk_end = cols[j]->get_property ("page-break-permission") == force_sym;
+              bool chunk_end = scm_is_eq (cols[j]->get_property ("page-break-permission"), force_sym);
               Break_position cur_pos = Break_position (i,
                                                        line_breaker_columns.size (),
                                                        cols[j],
index 8f1951223c4e8a4721047f848ec296ebc50a5e3f..479ac72bf72ec1152a3b4bd78affeae26fe78262 100644 (file)
@@ -449,7 +449,7 @@ Page_layout_problem::Page_layout_problem (Paper_book *pb, SCM page_scm, SCM syst
 
   for (SCM s = systems; scm_is_pair (s); s = scm_cdr (s))
     {
-      bool first = (s == systems);
+      bool first = scm_is_eq (s, systems);
 
       if (Grob *g = unsmob<Grob> (scm_car (s)))
         {
index c77dc9b2a5de516ad7cf827c7793c8e310dc3cb2..b294dce7d7f803ca9b083d4a75235870178d2b01 100644 (file)
@@ -107,7 +107,8 @@ public:
   void finalize ();
 };
 
-Page_turn_engraver::Page_turn_engraver ()
+Page_turn_engraver::Page_turn_engraver (Context *c)
+  : Engraver (c)
 {
   repeat_begin_ = Moment (-1);
   repeat_begin_rest_length_ = 0;
index 3a672198b538df5a880c19b1032db80adb1af946..c17ed576f1895c0a91febb29164ea9987dda1b0f 100644 (file)
@@ -514,7 +514,7 @@ Paper_book::get_system_specs ()
               SCM footnotes = get_footnotes (unsmob<Stencil> (t)->expr ());
               ps->set_property ("footnotes", footnotes);
               ps->set_property ("is-title", SCM_BOOL_T);
-              if (list == texts)
+              if (scm_is_eq (list, texts))
                 first = ps;
               else
                 {
index 0e32f6e6444200d8b7dbe9887c53c08b5ad26690..6dd29300130878be798fc0bfb9670035874d02a7 100644 (file)
@@ -34,7 +34,8 @@
 
 #include "translator.icc"
 
-Paper_column_engraver::Paper_column_engraver ()
+Paper_column_engraver::Paper_column_engraver (Context *c)
+  : Engraver (c)
 {
   last_moment_.main_part_ = Rational (-1, 1);
   command_column_ = 0;
index da3807c31d6f4ddb33fb75edf69c24ec3baf8175..5462027928693c15aa9a85d00ccca134b8945173 100644 (file)
@@ -209,7 +209,8 @@ Paper_column::break_align_width (Grob *me, SCM align_syms)
           extract_grob_set (me, "elements", elts);
           for (vsize i = 0; i < elts.size (); i++)
             {
-              if (elts[i]->get_property ("break-align-symbol") == align_sym
+              if (scm_is_eq (align_sym, elts[i]->get_property ("break-align-symbol"))
+                  // TODO SCM: there must be a simpler way to put this.
                   && !elts[i]->extent (elts[i], X_AXIS).is_empty ())
                 {
                   align = elts[i];
index dcbd506a4a5326ec6fd8524f13fd5298ac07a453..c9b9ec62a481047adb88ba7c5a432903ad1a5f27 100644 (file)
@@ -35,7 +35,8 @@ protected:
   void acknowledge_grob (Grob_info);
 };
 
-Parenthesis_engraver::Parenthesis_engraver ()
+Parenthesis_engraver::Parenthesis_engraver (Context *c)
+  : Engraver (c)
 {
 }
 
index 065713de1a8f56ee7e6b115e31b2e51e1018cd98..35d858c46f6dbef1c383c3588bc7dba697fc914b 100644 (file)
@@ -2719,8 +2719,8 @@ context_mod:
        | context_def_mod embedded_scm
        {
                if (!scm_is_string ($2)
-                   && ly_symbol2scm ("consists") != $1
-                   && ly_symbol2scm ("remove") != $1)
+                   && !scm_is_eq ($1, ly_symbol2scm ("consists"))
+                   && !scm_is_eq ($1, ly_symbol2scm ("remove")))
                {
                        $$ = SCM_EOL;
                        parser->parser_error (@1, _ ("only \\consists and \\remove take non-string argument."));
index 33c10f59660cb77ff2a674656168ae7d1d19a951..9646d7a355a6a46bdf6c6bcb12b36614d9f904b8 100644 (file)
@@ -66,7 +66,8 @@ Part_combine_engraver::listen_note (Stream_event *)
   note_found_ = true;
 }
 
-Part_combine_engraver::Part_combine_engraver ()
+Part_combine_engraver::Part_combine_engraver (Context *c)
+  : Engraver (c)
 {
   text_ = 0;
   new_event_ = 0;
index b620cdccb561d49fc684917d58116b3be5a1c534..da0b9b2964279f21d69113646a149ccbf78bac1f 100644 (file)
@@ -57,7 +57,8 @@ protected:
   void process_music ();
 };
 
-Percent_repeat_engraver::Percent_repeat_engraver ()
+Percent_repeat_engraver::Percent_repeat_engraver (Context *c)
+  : Engraver (c)
 {
   percent_ = 0;
   percent_counter_ = 0;
index 18f20f5430bc23c2422f9731893e126fc3e32310..aeee14a1ee5d3ede63d92ee69fd5cb3d91df0fdd 100644 (file)
@@ -58,7 +58,8 @@ Phrasing_slur_engraver::object_name () const
   return "phrasing slur";
 }
 
-Phrasing_slur_engraver::Phrasing_slur_engraver ()
+Phrasing_slur_engraver::Phrasing_slur_engraver (Context *c)
+  : Slur_engraver (c)
 {
 }
 
index 7c120a1bc19f861cea5c14a7603326d629a5469b..0d07872db08b18eeb82ad7aef6a1d6747879908a 100644 (file)
@@ -100,7 +100,8 @@ private:
   Spanner *make_line_spanner (Pedal_type t, SCM);
 };
 
-Piano_pedal_align_engraver::Piano_pedal_align_engraver ()
+Piano_pedal_align_engraver::Piano_pedal_align_engraver (Context *c)
+  : Engraver (c)
 {
 }
 
index cbdf5244d11e223d3c8aea157ac0d8acee5daf8d..2a2d2aa8ec5b417081fb09f8f1a31ba8e7de9f19 100644 (file)
@@ -181,7 +181,8 @@ init_pedal_types ()
 
 ADD_SCM_INIT_FUNC (Piano_pedal_engraver_init_pedal_types_, init_pedal_types);
 
-Piano_pedal_engraver::Piano_pedal_engraver ()
+Piano_pedal_engraver::Piano_pedal_engraver (Context *c)
+  : Engraver (c)
 {
 }
 
index a8273980e924d61ca558444ec949475102b6c536..4a24625e04b8160a8def7bccd35e796985b64c53 100644 (file)
@@ -56,7 +56,8 @@ private:
   Pedal_info info_alist_[NUM_PEDAL_TYPES];
 };
 
-Piano_pedal_performer::Piano_pedal_performer ()
+Piano_pedal_performer::Piano_pedal_performer (Context *c)
+  : Performer (c)
 {
 }
 
index 0750c594950e7dd7ce5f9bcea9166345a1b9875f..a5ccfa483ea70269f9c0c286abc52d2b04e474d5 100644 (file)
@@ -39,7 +39,8 @@ Pitch_squash_engraver::acknowledge_note_head (Grob_info i)
     i.grob ()->set_property ("staff-position", newpos);
 }
 
-Pitch_squash_engraver::Pitch_squash_engraver ()
+Pitch_squash_engraver::Pitch_squash_engraver (Context *c)
+  : Engraver (c)
 {
 }
 
index 1ec4da9aebdd26c07c31725230d8f20d650937b0..0ab6bc989b8e4d54267285eef772dc8b367a4519 100644 (file)
@@ -55,7 +55,8 @@ private:
   void make_trill (Stream_event *);
 };
 
-Pitched_trill_engraver::Pitched_trill_engraver ()
+Pitched_trill_engraver::Pitched_trill_engraver (Context *c)
+  : Engraver (c)
 {
   trill_head_ = 0;
   trill_group_ = 0;
index 03c84eca4d081a943add1ce4d014514d8de6c4d0..a9424da91f5479da82a5c9cf699dec332119e0f5 100644 (file)
@@ -67,7 +67,7 @@ LY_DEFINE (ly_prob_type_p, "ly:prob-type?",
            "Is @var{obj} the specified prob-type?")
 {
   Prob *prob = unsmob<Prob> (obj);
-  return scm_from_bool (prob && prob->type () == type);
+  return scm_from_bool (prob && scm_is_eq (prob->type (), type));
 }
 
 LY_DEFINE (ly_make_prob, "ly:make-prob",
index 025bea809bbcc83620771ae535aefbdd9c4f0b04..a109c4bf4feb9ecb06cb9a755cc6d3c3f089ee38 100644 (file)
 */
 
 #include "profile.hh"
+#include "protected-scm.hh"
 
-void note_property_access (SCM *table, SCM sym);
-
-SCM context_property_lookup_table;
-SCM grob_property_lookup_table;
-SCM prob_property_lookup_table;
+Protected_scm context_property_lookup_table;
+Protected_scm grob_property_lookup_table;
+Protected_scm prob_property_lookup_table;
 
 LY_DEFINE (ly_property_lookup_stats, "ly:property-lookup-stats",
            1, 0, 0, (SCM sym),
@@ -31,26 +30,26 @@ LY_DEFINE (ly_property_lookup_stats, "ly:property-lookup-stats",
            " @var{sym}.  Choices are @code{prob}, @code{grob}, and"
            " @code{context}.")
 {
-  if (scm_is_eq (sym, ly_symbol2scm ("context")))
-    return context_property_lookup_table ? context_property_lookup_table
-           : scm_c_make_hash_table (1);
-  if (scm_is_eq (sym, ly_symbol2scm ("prob")))
-    return prob_property_lookup_table ? prob_property_lookup_table
-           : scm_c_make_hash_table (1);
-  if (scm_is_eq (sym, ly_symbol2scm ("grob")))
-    return grob_property_lookup_table ? grob_property_lookup_table
-           : scm_c_make_hash_table (1);
+  if (context_property_lookup_table.is_bound ()
+      && scm_is_eq (sym, ly_symbol2scm ("context")))
+    return context_property_lookup_table;
+  if (prob_property_lookup_table.is_bound ()
+      && scm_is_eq (sym, ly_symbol2scm ("prob")))
+    return prob_property_lookup_table;
+  if (grob_property_lookup_table.is_bound ()
+      && scm_is_eq (sym, ly_symbol2scm ("grob")))
+    return grob_property_lookup_table;
   return scm_c_make_hash_table (1);
 }
 
 void
-note_property_access (SCM *table, SCM sym)
+note_property_access (Protected_scm *table, SCM sym)
 {
   /*
     Statistics: which properties are looked up?
   */
-  if (!*table)
-    *table = scm_permanent_object (scm_c_make_hash_table (259));
+  if (!table->is_bound ())
+    *table = scm_c_make_hash_table (259);
 
   SCM hashhandle = scm_hashq_get_handle (*table, sym);
   if (scm_is_false (hashhandle))
index 3934217fb3c9b64ade82becc20aaff47e036ef6d..88d16e167f94e904b99e0a6f111776e9c05d70f4 100644 (file)
@@ -30,6 +30,7 @@ using namespace std;
 #include "string-convert.hh"
 #include "warn.hh"
 #include "lily-imports.hh"
+#include "protected-scm.hh"
 
 bool debug_skylines;
 bool debug_property_callbacks;
@@ -45,7 +46,7 @@ bool profile_property_accesses = false;
 bool do_internal_type_checking_global;
 bool strict_infinity_checking = false;
 
-static SCM option_hash;
+static Protected_scm option_hash;
 
 void
 internal_set_option (SCM var,
@@ -190,8 +191,8 @@ LY_DEFINE (ly_add_option, "ly:add-option", 3, 0, 0,
            "Add a program option @var{sym}.  @var{val} is the default"
            " value and @var{description} is a string description.")
 {
-  if (!option_hash)
-    option_hash = scm_permanent_object (scm_c_make_hash_table (11));
+  if (!option_hash.is_bound ())
+    option_hash = scm_c_make_hash_table (11);
   LY_ASSERT_TYPE (ly_is_symbol, sym, 1);
   LY_ASSERT_TYPE (scm_is_string, description, 3);
 
index a9fabdc4f2e6fa69803b4c2aaa2c3583039d2154..3a16254187a05b0b7880a53ec9250c47071e8aee 100644 (file)
@@ -86,3 +86,11 @@ Protected_scm::operator SCM & ()
 
   return *SCM_CARLOC (object_);
 }
+
+bool
+Protected_scm::is_bound () const
+{
+  if (SCM_CONSP (object_))
+    return !SCM_UNBNDP (SCM_CAR (object_));
+  return !SCM_UNBNDP (object_);
+}
index 3bd0fa1091482d4e12a9f32707492c0630e9823b..cea3936161c4c62357250ca9ca664b7a00275bcb 100644 (file)
@@ -41,7 +41,8 @@ protected:
   void finalize ();
 };
 
-Pure_from_neighbor_engraver::Pure_from_neighbor_engraver ()
+Pure_from_neighbor_engraver::Pure_from_neighbor_engraver (Context *c)
+  : Engraver (c)
 {
 }
 
index d11b633fd5cb4b92ffb32af56f83c340056892bd..00e0c8abe259a4f0fcf5a29165cac81455705099 100644 (file)
@@ -51,7 +51,8 @@ Repeat_acknowledge_engraver::initialize ()
   context ()->set_property ("repeatCommands", SCM_EOL);
 }
 
-Repeat_acknowledge_engraver::Repeat_acknowledge_engraver ()
+Repeat_acknowledge_engraver::Repeat_acknowledge_engraver (Context *c)
+  : Engraver (c)
 {
 }
 
index fb2c8bb58465ca0c80ebc3d6f0de9cfa13652dcf..aebed3fdbab2db162214d758a497a80ab105a51e 100644 (file)
@@ -39,7 +39,8 @@ public:
   TRANSLATOR_DECLARATIONS (Repeat_tie_engraver);
 };
 
-Repeat_tie_engraver::Repeat_tie_engraver ()
+Repeat_tie_engraver::Repeat_tie_engraver (Context *c)
+  : Engraver (c)
 {
   event_ = 0;
   semi_tie_column_ = 0;
index 56a6783fbfa34d338eac0366b6ecf5e9a90d864d..70984ae2ad1b9ddbe9516730fb443370c7b1f713 100644 (file)
@@ -45,7 +45,8 @@ public:
   TRANSLATOR_DECLARATIONS (Rest_collision_engraver);
 };
 
-Rest_collision_engraver::Rest_collision_engraver ()
+Rest_collision_engraver::Rest_collision_engraver (Context *c)
+  : Engraver (c)
 {
   rest_collision_ = 0;
 }
index d691c2e98c7f9e2001706845c9ca3cf15b590df1..8902e3591121c0adfc98a969c7af5da6e6eae4b1 100644 (file)
@@ -45,7 +45,8 @@ public:
 /*
   Should merge with Note_head_engraver
 */
-Rest_engraver::Rest_engraver ()
+Rest_engraver::Rest_engraver (Context *c)
+  : Engraver (c)
 {
   rest_event_ = 0;
   rest_ = 0;
index 04281231d52825410a3606900a52f36147b31d5b..e307b512de092653ce91d6f54000161c175b07f4 100644 (file)
@@ -68,7 +68,8 @@ protected:
   void stop_translation_timestep ();
 };
 
-Rhythmic_column_engraver::Rhythmic_column_engraver ()
+Rhythmic_column_engraver::Rhythmic_column_engraver (Context *c)
+  : Engraver (c)
 {
 
   stem_ = 0;
index d0abfb1bd062f73a7330147b406e5d0cc2fed12a..42ab3f036783cbc1c8489d6517b689cb33d7dd98 100644 (file)
@@ -64,7 +64,8 @@ Scheme_engraver::fetch_precomputable_methods (SCM ptrs[])
     ptrs[i] = precomputable_methods_[i];
 }
 
-Scheme_engraver::Scheme_engraver (SCM definition)
+Scheme_engraver::Scheme_engraver (SCM definition, Context *c)
+  : Engraver (c)
 {
   precomputable_methods_[START_TRANSLATION_TIMESTEP]
     = callable (ly_symbol2scm ("start-translation-timestep"), definition);
index 6310f3b5403e5b56a98d984f3b3e735bb0c42cc4..e94e233882ab45d4b87aeb20575604db8755611b 100644 (file)
@@ -40,7 +40,8 @@ protected:
   void stop_translation_timestep ();
 };
 
-Script_column_engraver::Script_column_engraver ()
+Script_column_engraver::Script_column_engraver (Context *c)
+  : Engraver (c)
 {
   script_column_ = 0;
 }
index 94aa8908e70a1dfc3c2dfc791358491edb99e9d9..a12560bf8e19426eaec8f254b782a8e6108ccefb 100644 (file)
@@ -77,8 +77,8 @@ Script_column::row_before_line_breaking (SCM smob)
         {
           affect_all_grobs.push_back (sc);
         }
-      else if (sc->get_property_data ("Y-offset")
-               != Side_position_interface::y_aligned_side_proc)
+      else if (!scm_is_eq (sc->get_property_data ("Y-offset"),
+                           Side_position_interface::y_aligned_side_proc))
         {
           head_scripts_map[sc->get_parent (Y_AXIS)].push_back (sc);
         }
@@ -112,8 +112,8 @@ Script_column::before_line_breaking (SCM smob)
       /*
         Don't want to consider scripts horizontally next to notes.
       */
-      if (sc->get_property_data ("X-offset")
-          != Side_position_interface::x_aligned_side_proc)
+      if (!scm_is_eq (sc->get_property_data ("X-offset"),
+                      Side_position_interface::x_aligned_side_proc))
         staff_sided.push_back (sc);
     }
 
index 8a7b122f1fb0c0be00bab174937f95d627f0206a..1e989ae55d7800aee0e3e5ba7b5e52ab229c3cb6 100644 (file)
@@ -67,7 +67,8 @@ public:
   TRANSLATOR_DECLARATIONS (Script_engraver);
 };
 
-Script_engraver::Script_engraver ()
+Script_engraver::Script_engraver (Context *c)
+  : Engraver (c)
 {
 }
 
index 20af8d1cbb20326dd041db1461b2facaf4dc89ce..30ded2b8345c72db47ff227d8240d38bee021d55 100644 (file)
@@ -45,7 +45,8 @@ protected:
   void stop_translation_timestep ();
 };
 
-Script_row_engraver::Script_row_engraver ()
+Script_row_engraver::Script_row_engraver (Context *c)
+  : Engraver (c)
 {
   script_row_ = 0;
 }
index 5eb1407a31787a4babd78271edffd528570f9dc4..234008d9830bcac736edd19ad69459a3a7931b67 100644 (file)
@@ -69,7 +69,8 @@ public:
   TRANSLATOR_DECLARATIONS (Separating_line_group_engraver);
 };
 
-Separating_line_group_engraver::Separating_line_group_engraver ()
+Separating_line_group_engraver::Separating_line_group_engraver (Context *c)
+  : Engraver (c)
 {
 }
 
index bf64413a8a4eb28badd8d1e969d6ecd5b4601703..cf4fd5849e35601ad8cf839394d7f6d6ba407c8e 100644 (file)
@@ -470,7 +470,7 @@ get_line_forces (vector<Grob *> const &columns,
                 force[b * breaks.size () + c] = infinity_f;
               break;
             }
-          if (end < cols.size () && cols[end].break_permission_ == force_break)
+          if (end < cols.size () && scm_is_eq (cols[end].break_permission_, force_break))
             break;
         }
     }
index b1bdf9c0dac4746b26634d7bb4da9690073a98f9..aa80c2e2e544afc7e69330a5e10a09ace6ea37d1 100644 (file)
@@ -39,7 +39,8 @@ protected:
   void process_music ();
 };
 
-Slash_repeat_engraver::Slash_repeat_engraver ()
+Slash_repeat_engraver::Slash_repeat_engraver (Context *c)
+  : Engraver (c)
 {
   slash_ = 0;
 }
index 80ceb5f431fdf700dddc2000b95044ac9ff3f023..2309f114de1948d134d2fb03a0a79989a0618807 100644 (file)
@@ -53,7 +53,8 @@ Slur_engraver::object_name () const
   return "slur";
 }
 
-Slur_engraver::Slur_engraver ()
+Slur_engraver::Slur_engraver (Context *c)
+  : Engraver (c)
 {
 }
 
index 47fed784fe6c64335b1b926f033a372599405cbf..6c8a433226bcf4691884ec5b976fde7365fb9218 100644 (file)
@@ -47,7 +47,8 @@ private:
   bool slur_;
 };
 
-Slur_performer::Slur_performer ()
+Slur_performer::Slur_performer (Context *c)
+  : Performer (c)
 {
   slur_ = false;
   start_ev_ = 0;
index d77a55b757af67725ac237d49eeffdcb129fb793..00dc8227609b68fd2eb067d317399d1b678057b2 100644 (file)
@@ -93,7 +93,8 @@ protected:
   void stop_spanner ();
 };
 
-Spacing_engraver::Spacing_engraver ()
+Spacing_engraver::Spacing_engraver (Context *c)
+  : Engraver (c)
 {
   spacing_ = 0;
   start_section_ = 0;
index 9cece4a6fe336bd26d050168fa974f4c8db67737..dac5b91ab59cd643b423cd7dcfe886da8510d040 100644 (file)
@@ -50,7 +50,8 @@ private:
   vector<Grob *> note_columns_;
 };
 
-Span_arpeggio_engraver::Span_arpeggio_engraver ()
+Span_arpeggio_engraver::Span_arpeggio_engraver (Context *c)
+  : Engraver (c)
 {
   span_arpeggio_ = 0;
 }
index e74528535bfa0f2dd48dd8b0834e38bace2fd6b1..55ef59e32e40f656388f06b27f7cdf42a6a03b06 100644 (file)
@@ -46,7 +46,8 @@ protected:
   void process_acknowledged ();
 };
 
-Span_bar_engraver::Span_bar_engraver ()
+Span_bar_engraver::Span_bar_engraver (Context *c)
+  : Engraver (c)
 {
   spanbar_ = 0;
   make_spanbar_ = false;
index a0c10f8594ae1165cbe74fcdd3b077ad94c0cd86..914e73ed4b89ebecc735e1c531a53be3be8eaed1 100644 (file)
@@ -62,7 +62,8 @@ protected:
   virtual void derived_mark () const;
 };
 
-Span_bar_stub_engraver::Span_bar_stub_engraver ()
+Span_bar_stub_engraver::Span_bar_stub_engraver (Context *c)
+  : Engraver (c)
 {
   axis_groups_ = SCM_EOL;
 }
index 8d64b40ce8134672fcc1e53dfa28daedbfcfab4a..98bf1934d0ee6b1edfdbd20e87f0b09b1eb3ef7b 100644 (file)
@@ -62,7 +62,8 @@ Spanner_break_forbid_engraver::acknowledge_unbreakable_spanner (Grob_info gi)
     running_spanners_.push_back (gi.spanner ());
 }
 
-Spanner_break_forbid_engraver::Spanner_break_forbid_engraver ()
+Spanner_break_forbid_engraver::Spanner_break_forbid_engraver (Context *c)
+  : Engraver (c)
 {
 }
 
index f3593cbbf534d8774a57abdd1158960384c63aad..f73657afe184bfec6820190186c53759d0c04458 100644 (file)
@@ -455,11 +455,8 @@ Spanner::calc_normalized_endpoints (SCM smob)
       Real total_width = 0.0;
       vector<Real> span_data;
 
-      if (!orig->is_broken ())
-        span_data.push_back (orig->spanner_length ());
-      else
-        for (vsize i = 0; i < orig->broken_intos_.size (); i++)
-          span_data.push_back (orig->broken_intos_[i]->spanner_length ());
+      for (vsize i = 0; i < orig->broken_intos_.size (); i++)
+        span_data.push_back (orig->broken_intos_[i]->spanner_length ());
 
       vector<Interval> unnormalized_endpoints;
 
index a389df2efdb5921a60b56814a7a2c2f210bb495f..19a5eef4c5ff87ffc4fc18a84f2f0af14fce3286 100644 (file)
@@ -26,7 +26,8 @@
 SCM
 Spring::equal_p (SCM a, SCM b)
 {
-  return a == b ? SCM_BOOL_T : SCM_BOOL_F;
+  // TODO SCM: This could be made simpler.
+  return scm_is_eq (a, b) ? SCM_BOOL_T : SCM_BOOL_F;
 }
 
 LY_DEFINE (ly_make_spring, "ly:make-spring",
index 88680943d3d0937139645d0a6a8cf075f1e24bce..97711c89b55c75ba594b709295033f60dd88f9bd 100644 (file)
@@ -30,7 +30,8 @@ public:
   void acknowledge_end_staff_symbol (Grob_info);
 };
 
-Staff_collecting_engraver::Staff_collecting_engraver ()
+Staff_collecting_engraver::Staff_collecting_engraver (Context *c)
+  : Engraver (c)
 {
 }
 
index 592c6a7e016f4fd82e6be3d998318625dfb4fd42..1af71efd86db801f06c6b6222e8e7d73e8eae730 100644 (file)
@@ -112,8 +112,9 @@ ADD_TRANSLATOR (Staff_performer,
                 /* write */
                 "");
 
-Staff_performer::Staff_performer ()
-  : channel_ (-1),
+Staff_performer::Staff_performer (Context *c)
+  : Performer (c),
+    channel_ (-1),
     instrument_ (0),
     instrument_name_ (0),
     name_ (0),
index c8f528f0f541c6d6536bbff52e6a0474e2d4966b..fad9f0437900d5765301d6eb82376b9ce714d38e 100644 (file)
@@ -68,7 +68,8 @@ Staff_symbol_engraver::~Staff_symbol_engraver ()
     }
 }
 
-Staff_symbol_engraver::Staff_symbol_engraver ()
+Staff_symbol_engraver::Staff_symbol_engraver (Context *c)
+  : Engraver (c)
 {
   finished_span_ = 0;
   first_start_ = true;
index 39eae99831fb5c5c4f1ae353691523cd9e7aadd5..53ec89358f56359cad37b12d14b4d711d5dc6343 100644 (file)
@@ -40,7 +40,8 @@ protected:
   void stop_translation_timestep ();
 };
 
-Stanza_number_align_engraver::Stanza_number_align_engraver ()
+Stanza_number_align_engraver::Stanza_number_align_engraver (Context *c)
+  : Engraver (c)
 {
 }
 
index 0a4539e8f1679059ee81676ca5e8d08797473152..4b7eaa5a8a3e760e199f3270246e55a622a12bc8 100644 (file)
@@ -47,7 +47,8 @@ Stanza_number_engraver::derived_mark () const
   all aligned.
 */
 
-Stanza_number_engraver::Stanza_number_engraver ()
+Stanza_number_engraver::Stanza_number_engraver (Context *c)
+  : Engraver (c)
 {
   text_ = 0;
   last_stanza_ = SCM_EOL;
@@ -59,7 +60,7 @@ Stanza_number_engraver::process_music ()
   SCM stanza = get_property ("stanza");
 
   if (Text_interface::is_markup (stanza)
-      && stanza != last_stanza_)
+      && !scm_is_eq (stanza, last_stanza_))
     {
       last_stanza_ = stanza;
 
index 8907c34bc3bcfd68b1e5375fa86d950f7d6d9eb1..199d9fd17ea735d1a1c2308324938d694268e208 100644 (file)
@@ -56,7 +56,8 @@ protected:
   void kill_unused_flags ();
 };
 
-Stem_engraver::Stem_engraver ()
+Stem_engraver::Stem_engraver (Context *c)
+  : Engraver (c)
 {
   tremolo_ev_ = 0;
   stem_ = 0;
index 06aabb992f943494b09561e3aa039d1bfbae5843..8d804196202368c1eaf1043cac78de4e91253fb2 100644 (file)
 */
 
 #include "stencil.hh"
+#include "protected-scm.hh"
 
-static SCM heads;
+static Protected_scm heads (SCM_EOL);
 
 void register_stencil_head (SCM symbol)
 {
-  if (!heads)
-    heads = scm_permanent_object (scm_cons (SCM_EOL, SCM_EOL));
-
   scm_set_object_property_x (symbol, ly_symbol2scm ("stencil-head?"), SCM_BOOL_T);
-  scm_set_cdr_x (heads, scm_cons (symbol, scm_cdr (heads)));
+  heads = scm_cons (symbol, heads);
 }
 
 bool
@@ -39,6 +37,5 @@ is_stencil_head (SCM symbol)
 SCM
 all_stencil_heads ()
 {
-  return scm_cdr (heads);
+  return heads;
 }
-
index 1b9aa5181b4e2426c915e7db3106e52052b003c5..b44258b6b1973c19d117626ba769a232467dd7e4 100644 (file)
@@ -894,9 +894,8 @@ stencil_dispatcher (vector<Box> &boxes,
 vector<Transform_matrix_and_expression>
 stencil_traverser (PangoMatrix trans, SCM expr)
 {
-  if (scm_is_null (expr))
-    return vector<Transform_matrix_and_expression> ();
-  else if (scm_is_eq (expr, ly_string2scm ("")))
+  if (scm_is_null (expr)
+      || (scm_is_string (expr) && scm_is_true (scm_string_null_p (expr))))
     return vector<Transform_matrix_and_expression> ();
   else if (scm_is_eq (scm_car (expr), ly_symbol2scm ("combine-stencil")))
     {
@@ -946,6 +945,8 @@ stencil_traverser (PangoMatrix trans, SCM expr)
     return stencil_traverser (trans, scm_cadr (expr));
   else if (scm_is_eq (scm_car (expr), ly_symbol2scm ("output-attributes")))
     return stencil_traverser (trans, scm_caddr (expr));
+  else if (scm_is_eq (scm_car (expr), ly_symbol2scm ("with-outline")))
+    return stencil_traverser (trans, scm_cadr (expr));
   else
     {
       vector<Transform_matrix_and_expression> out;
index 25fad0d8429ef6c327ac2a08b57f959789015827..15f44c0f820efbf6bfc5c87c0fc7bcc4f92bd4e1 100644 (file)
@@ -121,6 +121,10 @@ interpret_stencil_expression (SCM expr,
 
           return;
         }
+      else if (scm_is_eq (head, ly_symbol2scm ("with-outline")))
+        {
+          expr = scm_caddr (expr);
+        }
       else
         {
           (*func) (func_arg,
index 5c43189e0bc713305d51245cee254b97021300d0..da9f0a8214afcdf7d9fc74d8c9691542ad74a7ac 100644 (file)
@@ -555,3 +555,14 @@ LY_DEFINE (ly_stencil_scale, "ly:stencil-scale",
   q->scale (scm_to_double (x), scm_to_double (y));
   return new_s;
 }
+
+LY_DEFINE (ly_stencil_outline, "ly:stencil-outline",
+           2, 0, 0, (SCM stil, SCM outline),
+           "Return a stencil with the stencil expression (inking)"
+           " of stencil @var{stil} but with outline and dimensions"
+           " from stencil @var{outline}.")
+{
+  Stencil s = *LY_ASSERT_SMOB (Stencil, stil, 1);
+  Stencil o = *LY_ASSERT_SMOB (Stencil, outline, 2);
+  return s.with_outline (o).smobbed_copy ();
+}
index 5e568c98dbd8efb38dd963f15a8313a242759b0d..dc5549f6314393a0c3393fd088d62cee50db1b70 100644 (file)
@@ -415,3 +415,13 @@ Stencil::translated (Offset z) const
   s.translate (z);
   return s;
 }
+
+Stencil
+Stencil::with_outline (Stencil const &ol) const
+{
+  Stencil new_stencil (ol.extent_box (),
+                       scm_list_3 (ly_symbol2scm ("with-outline"),
+                                   ol.expr (),
+                                   expr ()));
+  return new_stencil;
+}
index 2979e11a1918ed653e06108490ee190dab613cd3..b7a210e86956e01ed9a66f63d73dabcd60b7c4f7 100644 (file)
@@ -176,7 +176,8 @@ protected:
   virtual void finalize ();
 };
 
-System_start_delimiter_engraver::System_start_delimiter_engraver ()
+System_start_delimiter_engraver::System_start_delimiter_engraver (Context *c)
+  : Engraver (c)
 {
   nesting_ = 0;
 }
index 4294a2e5fe5279ff19a4df3e2031d8a77598de93..18a1e122f6eee8318005c52ba642e292254dd01e 100644 (file)
@@ -57,7 +57,8 @@ protected:
   void stop_translation_timestep ();
 };
 
-Tab_note_heads_engraver::Tab_note_heads_engraver ()
+Tab_note_heads_engraver::Tab_note_heads_engraver (Context *c)
+  : Engraver (c)
 {
 }
 
index cde9e82bbb20373d6edc10427a38ffa8f4716802..843fc4eba68032b1ccc16bfa77944d03495575a1 100644 (file)
@@ -36,7 +36,8 @@ Tab_staff_symbol_engraver::acknowledge_staff_symbol (Grob_info gi)
     gi.grob ()->set_property ("line-count", scm_from_int (k));
 }
 
-Tab_staff_symbol_engraver::Tab_staff_symbol_engraver ()
+Tab_staff_symbol_engraver::Tab_staff_symbol_engraver (Context *c)
+  : Engraver (c)
 {
 }
 
index 58c5203ef089a41ccb413a8c3040db0fbe50690b..75a7b5b2ea710bd42ec5283eb7b8de6549045e30 100644 (file)
@@ -51,7 +51,8 @@ protected:
   void stop_translation_timestep ();
 };
 
-Tab_tie_follow_engraver::Tab_tie_follow_engraver ()
+Tab_tie_follow_engraver::Tab_tie_follow_engraver (Context *c)
+  : Engraver (c)
 {
 }
 
index 683f133d6466c28ae3774448777f9e397f3fe4b4..967ae60e7067b7e6b803d85a81479690331f898c 100644 (file)
@@ -47,7 +47,8 @@ Tempo_performer::derived_mark () const
   scm_gc_mark (last_tempo_);
 }
 
-Tempo_performer::Tempo_performer ()
+Tempo_performer::Tempo_performer (Context *c)
+  : Performer (c)
 {
   last_tempo_ = SCM_EOL;
   audio_ = 0;
index 982b61a287461559c024b87911696bdf69b1870c..6bbcdc379479006055ef417679bc7cac439c095c 100644 (file)
@@ -105,7 +105,8 @@ Text_engraver::stop_translation_timestep ()
   scripts_.clear ();
 }
 
-Text_engraver::Text_engraver ()
+Text_engraver::Text_engraver (Context *c)
+  : Engraver (c)
 {
 }
 
index f63e19a0593083f9fbb1d869d24ea05696d30823..1b66b68f121139530e98d60b42f32fdc553b7666 100644 (file)
@@ -47,7 +47,8 @@ private:
   void typeset_all ();
 };
 
-Text_spanner_engraver::Text_spanner_engraver ()
+Text_spanner_engraver::Text_spanner_engraver (Context *c)
+  : Engraver (c)
 {
   finished_ = 0;
   current_event_ = 0;
index 2a016b31be8a08317422b17faa22b39cd5d84684..98eac4b19b81355b595133986f4bbf47565f40a5 100644 (file)
@@ -94,7 +94,8 @@ public:
   TRANSLATOR_DECLARATIONS (Tie_engraver);
 };
 
-Tie_engraver::Tie_engraver ()
+Tie_engraver::Tie_engraver (Context *c)
+  : Engraver (c)
 {
   event_ = 0;
   tie_column_ = 0;
index e93b3e6b0c6047fea2c2de8d33705b9a3098e0c4..1f95023eb6ab0962146dd13b54ce07f08b665717 100644 (file)
@@ -56,7 +56,8 @@ public:
   TRANSLATOR_DECLARATIONS (Tie_performer);
 };
 
-Tie_performer::Tie_performer ()
+Tie_performer::Tie_performer (Context *c)
+  : Performer (c)
 {
   event_ = 0;
 }
index d57b35bf6eae9bb95c04d2d0d1dde3d85c9f6764..e4e76e17d685154c2868ab75c2efd8d8feae5dbe 100644 (file)
@@ -53,7 +53,8 @@ Time_signature_engraver::derived_mark () const
   scm_gc_mark (time_cause_);
 }
 
-Time_signature_engraver::Time_signature_engraver ()
+Time_signature_engraver::Time_signature_engraver (Context *c)
+  : Engraver (c)
 {
   time_signature_ = 0;
   time_cause_ = SCM_EOL;
@@ -73,8 +74,7 @@ Time_signature_engraver::process_music ()
     return;
 
   SCM fr = get_property ("timeSignatureFraction");
-  if (last_time_fraction_ != fr
-      && scm_is_pair (fr))
+  if (!scm_is_eq (last_time_fraction_, fr) && scm_is_pair (fr))
     {
       time_signature_ = make_item ("TimeSignature", time_cause_);
       time_signature_->set_property ("fraction", fr);
index 3a3bbd2ca328de3c563bdc5314483c0bcea50d90..75c3ef5d086a87ddf99e6eed3e8dca81dda59e85 100644 (file)
@@ -44,7 +44,8 @@ Time_signature_performer::derived_mark () const
   scm_gc_mark (prev_fraction_);
 }
 
-Time_signature_performer::Time_signature_performer ()
+Time_signature_performer::Time_signature_performer (Context *c)
+  : Performer (c)
 {
   prev_fraction_ = SCM_BOOL_F;
   audio_ = 0;
index 4716eceb24c489d05ff30feb19a304a449f80f2f..67c2ffeed1a34fded9052512ed206bac5abb53c8 100644 (file)
@@ -145,7 +145,8 @@ Timing_translator::measure_length () const
     return Rational (1);
 }
 
-Timing_translator::Timing_translator ()
+Timing_translator::Timing_translator (Context *c)
+  : Translator (c)
 {
 }
 
index 67fa95a610b139608d94482ae54d6afb202221b3..af33d78a2f006caed03ddf3b2d32e98cf6993734 100644 (file)
   along with LilyPond.  If not, see <http://www.gnu.org/licenses/>.
 */
 
+#include "context.hh"
 #include "translator.hh"
-
+#include "lily-imports.hh"
 #include "international.hh"
 #include "scm-hash.hh"
 #include "warn.hh"
 #include "protected-scm.hh"
 
-/*
-  should delete these after exit.
-*/
+SCM
+Translator_creator::call (SCM ctx)
+{
+  return (allocate_ (LY_ASSERT_SMOB (Context, ctx, 1)))->unprotect ();
+}
 
 Protected_scm global_translator_dict;
+Protected_scm global_translator_dict_rev;
 
 LY_DEFINE (get_all_translators, "ly:get-all-translators", 0, 0, 0, (),
            "Return a list of all translator objects that may be"
@@ -44,21 +48,65 @@ LY_DEFINE (get_all_translators, "ly:get-all-translators", 0, 0, 0, (),
 }
 
 void
-add_translator (Translator *t)
+add_translator_creator (SCM creator, SCM name, SCM description)
 {
   Scheme_hash_table *dict = unsmob<Scheme_hash_table> (global_translator_dict);
   if (!dict)
     {
       global_translator_dict = Scheme_hash_table::make_smob ();
+      global_translator_dict_rev =
+        scm_make_weak_key_hash_table (scm_from_int (119));
       dict = unsmob<Scheme_hash_table> (global_translator_dict);
     }
+  dict->set (name, creator);
+  scm_hashq_set_x (global_translator_dict_rev, creator, scm_cons (name, description));
+}
 
-  SCM k = ly_symbol2scm (t->class_name ());
-  dict->set (k, t->unprotect ());
+LY_DEFINE (ly_translator_name, "ly:translator-name",
+           1, 0, 0, (SCM creator),
+           "Return the type name of the translator definition @var{creator}."
+           "  The name is a symbol.")
+{
+  SCM res = global_translator_dict_rev.is_bound ()
+    ? scm_hashq_ref (global_translator_dict_rev, creator, SCM_BOOL_F)
+    : SCM_BOOL_F;
+  SCM_ASSERT_TYPE (scm_is_pair (res),
+                   creator, SCM_ARG1, __FUNCTION__, "translator definition");
+  return scm_car (res);
+}
+
+LY_DEFINE (ly_translator_description, "ly:translator-description",
+           1, 0, 0, (SCM creator),
+           "Return an alist of properties of translator definition @var{creator}.")
+{
+  SCM res = global_translator_dict_rev.is_bound ()
+    ? scm_hashq_ref (global_translator_dict_rev, creator, SCM_BOOL_F)
+    : SCM_BOOL_F;
+  SCM_ASSERT_TYPE (scm_is_pair (res),
+                   creator, SCM_ARG1, __FUNCTION__, "translator definition");
+  return scm_cdr (res);
+}
+
+LY_DEFINE (ly_register_translator, "ly:register-translator",
+           2, 1, 0, (SCM creator, SCM name, SCM description),
+           "Register a translator @var{creator} (usually a descriptive"
+           " alist or a function/closure returning one when given a"
+           " context argument) with the given symbol @var{name} and"
+           " the given @var{description} alist.")
+{
+  SCM_ASSERT_TYPE (ly_is_procedure (creator) || scm_is_pair (creator),
+                   creator, SCM_ARG1, __FUNCTION__, "translator creator");
+  LY_ASSERT_TYPE (ly_is_symbol, name, 2);
+  if (SCM_UNBNDP (description))
+    description = SCM_EOL;
+  else
+    LY_ASSERT_TYPE (ly_is_list, description, 3);
+  add_translator_creator (creator, name, description);
+  return SCM_UNSPECIFIED;
 }
 
-Translator *
-get_translator (SCM sym)
+SCM
+get_translator_creator (SCM sym)
 {
   SCM v = SCM_BOOL_F;
   Scheme_hash_table *dict = unsmob<Scheme_hash_table> (global_translator_dict);
@@ -68,8 +116,7 @@ get_translator (SCM sym)
   if (scm_is_false (v))
     {
       warning (_f ("unknown translator: `%s'", ly_symbol2string (sym).c_str ()));
-      return 0;
     }
 
-  return unsmob<Translator> (v);
+  return v;
 }
index a9f1690f62998712b5bfe0a7470c437f838025f1..538a1d7b05cdc13df399a60f9e61814a5ec7a868 100644 (file)
@@ -162,48 +162,32 @@ Translator_group::create_child_translator (SCM sev)
 
   for (SCM s = trans_names; scm_is_pair (s); s = scm_cdr (s))
     {
-      SCM definition = scm_car (s);
-      bool is_scheme = false;
-
-      Translator *type = 0;
-      if (ly_is_symbol (definition))
-        type = get_translator (definition);
-      else if (ly_is_pair (definition))
-        {
-          is_scheme = true;
-        }
-      else if (ly_is_procedure (definition))
+      SCM trans = scm_car (s);
+
+      if (ly_is_symbol (trans))
+        trans = get_translator_creator (trans);
+      if (ly_is_procedure (trans))
+        trans = scm_call_1 (trans, cs);
+      if (ly_cheap_is_list (trans))
+        trans = (new Scheme_engraver (trans, new_context))->unprotect ();
+      Translator *instance = unsmob<Translator> (trans);
+      if (!instance)
         {
-          // `definition' is a procedure, which takes the context as
-          // an argument and evaluates to an a-list scheme engraver
-          // definition.
-          definition = scm_call_1 (definition, cs);
-          is_scheme = true;
+          warning (_f ("cannot find: `%s'", ly_scm_write_string (trans).c_str ()));
+          continue;
         }
 
-      if (!is_scheme && !type)
-        warning (_f ("cannot find: `%s'", ly_symbol2string (scm_car (s)).c_str ()));
-      else
+      if (instance->must_be_last ())
         {
-          Translator *instance = is_scheme ? new Scheme_engraver (definition)
-            : type->clone ();
-
-          SCM str = instance->self_scm ();
-
-          if (instance->must_be_last ())
-            {
-              SCM cons = scm_cons (str, SCM_EOL);
-              if (scm_is_pair (trans_list))
-                scm_set_cdr_x (scm_last_pair (trans_list), cons);
-              else
-                trans_list = cons;
-            }
+          SCM cons = scm_cons (trans, SCM_EOL);
+          if (scm_is_pair (trans_list))
+            scm_set_cdr_x (scm_last_pair (trans_list), cons);
           else
-            trans_list = scm_cons (str, trans_list);
-
-          instance->daddy_context_ = new_context;
-          instance->unprotect ();
+            trans_list = cons;
         }
+      else
+        trans_list = scm_cons (trans, trans_list);
+
     }
 
   /* Filter unwanted translator types. Required to make
index 3aaf92fc3d70dad84ac2aa44694b6e668bbad8d7..5499b5e2e21371d385c57f55044b3680a23fa445 100644 (file)
 #include "translator-group.hh"
 #include "moment.hh"
 
-LY_DEFINE (ly_translator_name, "ly:translator-name",
-           1, 0, 0, (SCM trans),
-           "Return the type name of the translator object @var{trans}."
-           "  The name is a symbol.")
-{
-  LY_ASSERT_SMOB (Translator, trans, 1);
-  Translator *tr = unsmob<Translator> (trans);
-  char const *nm = tr->class_name ();
-  return ly_symbol2scm (nm);
-}
-
-LY_DEFINE (ly_translator_description, "ly:translator-description",
-           1, 0, 0, (SCM me),
-           "Return an alist of properties of translator @var{me}.")
-{
-  LY_ASSERT_SMOB (Translator, me, 1);
-  Translator *tr = unsmob<Translator> (me);
-  return tr->translator_description ();
-}
-
 LY_DEFINE (ly_translator_context, "ly:translator-context",
            1, 0, 0, (SCM trans),
            "Return the context of the translator object @var{trans}.")
index bdc55f0f05467a4d4cb5fd56b548deb9995329c2..e57e1c391af53eec7dc93253da33fe28d5cff8e7 100644 (file)
@@ -32,13 +32,6 @@ Translator::~Translator ()
 {
 }
 
-void
-Translator::init ()
-{
-  daddy_context_ = 0;
-  smobify_self ();
-}
-
 void
 Translator::process_music ()
 {
@@ -49,15 +42,10 @@ Translator::process_acknowledged ()
 {
 }
 
-Translator::Translator ()
+Translator::Translator (Context *c)
+  : daddy_context_ (c)
 {
-  init ();
-}
-
-Translator::Translator (Translator const &)
-  : Smob<Translator> ()
-{
-  init ();
+  smobify_self ();
 }
 
 Moment
@@ -160,7 +148,7 @@ Translator::static_translator_description (const char *grobs,
                                            const char *desc,
                                            SCM listener_list,
                                            const char *read,
-                                           const char *write) const
+                                           const char *write)
 {
   SCM static_properties = SCM_EOL;
 
index 6634b5ea43be9cee202f9772cdeb79f00f6f765a..ff4612ac666fc6ed8ea4a3790fad427c6e18fe75 100644 (file)
@@ -55,7 +55,8 @@ private:
   void typeset_all ();
 };
 
-Trill_spanner_engraver::Trill_spanner_engraver ()
+Trill_spanner_engraver::Trill_spanner_engraver (Context *c)
+  : Engraver (c)
 {
   finished_ = 0;
   current_event_ = 0;
index 92e018aeceae7ed2f9475c0e7e20c226c806ca0d..61f623c54638d435d90b71212ac429b7cb48bf3c 100644 (file)
@@ -267,7 +267,8 @@ Tuplet_engraver::finalize ()
       }
 }
 
-Tuplet_engraver::Tuplet_engraver ()
+Tuplet_engraver::Tuplet_engraver (Context *c)
+  : Engraver (c)
 {
 }
 
index 5f97b1e4cbdb11a84bfb469f864e31a01f2b8d0c..ed66637abeec3357fe7d6c9eaec4d2f13917bbea 100644 (file)
@@ -32,7 +32,8 @@ protected:
   void acknowledge_grob (Grob_info);
 };
 
-Tweak_engraver::Tweak_engraver ()
+Tweak_engraver::Tweak_engraver (Context *c)
+  : Engraver (c)
 {
 }
 
index 6c34e9eb61ba3e42351e4df8d24409283ec1ec6f..1785d4478b407b142b839c82f766e277d6f555ea 100644 (file)
@@ -84,7 +84,8 @@ protected:
                                 vector<Grob_info> const &primitives);
 };
 
-Vaticana_ligature_engraver::Vaticana_ligature_engraver ()
+Vaticana_ligature_engraver::Vaticana_ligature_engraver (Context *c)
+  : Gregorian_ligature_engraver (c)
 {
   brew_ligature_primitive_proc
     = Vaticana_ligature::brew_ligature_primitive_proc;
index 0226173a2e115ec81d153212a5c3317cee6755c2..921b35a47113ace9436136ed08664610127af9fc 100644 (file)
@@ -71,7 +71,8 @@ ADD_TRANSLATOR (Vertical_align_engraver,
                 ""
                );
 
-Vertical_align_engraver::Vertical_align_engraver ()
+Vertical_align_engraver::Vertical_align_engraver (Context *c)
+  : Engraver (c)
 {
   valign_ = 0;
   id_to_group_hashtab_ = SCM_EOL;
index 2f95ac7ac11b861216e75a77d7d63857f6373fab..8d6a16f1ee6f4d8d3f8f953ef4119103db988b05 100644 (file)
@@ -62,7 +62,8 @@ Volta_engraver::derived_mark () const
   scm_gc_mark (start_string_);
 }
 
-Volta_engraver::Volta_engraver ()
+Volta_engraver::Volta_engraver (Context *c)
+  : Engraver (c)
 {
   start_string_ = SCM_EOL;
   volta_bracket_ = 0;
index abf5900cef33f9ccd50ea5a39b10db9dfdb5c6f4..d42a565682373e5f69ae14b57d9344ec32e51993 100644 (file)
@@ -23,7 +23,7 @@ That's it.  For more information, visit http://lilypond.org .
 
 %}
 
-\version "2.19.54"  % necessary for upgrading to future LilyPond versions.
+\version "2.19.55"  % necessary for upgrading to future LilyPond versions.
 
 \header{
   title = "A scale in LilyPond"
index 32b0cb885b40e02abae5289efbbde13c3b4a6f00..5a3410be99cbab3ce1bb5e9fdd6d27fff53d2bf5 100644 (file)
@@ -32,7 +32,7 @@ Good luck with LilyPond!  Happy engraving.
 
 %}
 
-\version "2.19.54"  % necessary for upgrading to future LilyPond versions.
+\version "2.19.55"  % necessary for upgrading to future LilyPond versions.
 
 \header{
   title = "A scale in LilyPond"
index 1dc0e5566b1868a8153501e4be362487e40641fe..2b418cee7b265e13083e5aeec1eae4595ab61425 100644 (file)
 #(define (ac:up note)
   (let* ((pitch (ly:music-property note 'pitch))
          (notename (ly:pitch-notename pitch))
-         (new-notename (if (eq? notename 6) 0 (+ 1 notename)))
+         (new-notename (if (eqv? notename 6) 0 (+ 1 notename)))
          (alterations (ly:music-property ac:current-key 'pitch-alist))
          (new-alteration (cdr (assq new-notename alterations)))
-         (new-octave (if (eq? new-notename 0) (+ 1 (ly:pitch-octave pitch))
+         (new-octave (if (eqv? new-notename 0) (+ 1 (ly:pitch-octave pitch))
                       (ly:pitch-octave pitch)))
        )
    (set! (ly:music-property note 'pitch)(ly:make-pitch new-octave new-notename new-alteration))))
 #(define (ac:down note)
   (begin  (let* ((pitch (ly:music-property note 'pitch))
          (notename (ly:pitch-notename pitch))
-         (new-notename (if (eq? notename 0) 6 (- notename 1)))
+         (new-notename (if (eqv? notename 0) 6 (- notename 1)))
          (alterations (ly:music-property ac:current-key 'pitch-alist))
          (new-alteration (cdr (assq new-notename alterations)))
-         (new-octave (if (eq? new-notename 6) (- (ly:pitch-octave pitch) 1)
+         (new-octave (if (eqv? new-notename 6) (- (ly:pitch-octave pitch) 1)
                       (ly:pitch-octave pitch)))
        )
    (set! (ly:music-property note 'pitch)(ly:make-pitch new-octave new-notename new-alteration))))
 
        ((SlurEvent)
         (let ((direction (ly:music-property e 'span-direction)))
-         (set! ac:inSlur (eq? direction -1))
-         (set! at-end-of-slur (eq? direction 1))
+         (set! ac:inSlur (eqv? direction -1))
+         (set! at-end-of-slur (eqv? direction 1))
          (loop factor newelements tail actions)))
 
        ((TrillSpanEvent)
         (let ((direction (ly:music-property e 'span-direction)))
-         (set! ac:inTrill (eq? direction -1))
+         (set! ac:inTrill (eqv? direction -1))
          (if ac:inTrill
           (loop factor newelements tail (cons 'trill actions))
           (loop factor (cons e newelements) tail actions))))
 
        ((PhrasingSlurEvent)
         (let ((direction (ly:music-property e 'span-direction)))
-         (set! ac:inPhrasingSlur (eq? direction -1))
+         (set! ac:inPhrasingSlur (eqv? direction -1))
          (loop factor newelements tail actions)))
 
        (else (loop factor (cons e newelements) tail actions))))))))
           (len (ly:duration-log ac:currentDuration))
           (dots (ly:duration-dot-count ac:currentDuration)))
 
-         (if (not (eq? num denom))
+         (if (not (eqv? num denom))
           (make-sequential-music
            (list (ac:to128 music)
            (make-music 'EventChord 'elements
@@ -1013,7 +1013,7 @@ articulate = #(define-music-function (music)
          (grace-orig-len (ly:music-length grace))
          (main-orig-len (ly:music-length main))
          (numerator (ly:moment-main-numerator maindur))
-         (factor (if (eq? (remainder numerator 3) 0)
+         (factor (if (eqv? (remainder numerator 3) 0)
                   (ly:make-moment 1/3) (ly:make-moment 1/2))))
    (ly:music-compress grace
     (ly:moment-mul factor (ly:moment-div main-orig-len grace-orig-len)))
index d7eba42a4b03159d4b14860031596db4930111ff..9fe65613454f9c987b9b3d601b4a7afd3c7f2a17 100644 (file)
@@ -104,7 +104,8 @@ a starting spanner event, or a symbol list in the form
 form of a spanner event, @var{property} may also have the form
 @samp{Grob.property} for specifying a directed tweak.")
   (if (ly:music? item)
-      (if (eq? (ly:music-property item 'span-direction) START)
+      (if (or (eqv? (ly:music-property item 'span-direction) START)
+              (music-is-of-type? item 'tie-event))
           (tweak property (value-for-spanner-piece arg) item)
           (begin
             (ly:music-warning item (_ "not a spanner"))
index 9fa6395e86b282884fe34c1fd1446264aa488c83..d26e44234ed3e659b7825075e9ae8b8ba590f4be 100644 (file)
@@ -6,10 +6,10 @@
 #, fuzzy
 msgid ""
 msgstr ""
-"Project-Id-Version: lilypond 2.19.54\n"
+"Project-Id-Version: lilypond 2.19.55\n"
 "Report-Msgid-Bugs-To: http://post.gmane.org/post.php?group=gmane.comp.gnu."
 "lilypond.bugs\n"
-"POT-Creation-Date: 2017-01-03 14:31+0000\n"
+"POT-Creation-Date: 2017-02-12 12:08+0000\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -925,7 +925,7 @@ msgstr ""
 msgid "Encountered unprocessed marker %s\n"
 msgstr ""
 
-#: abc2ly.py:1389 convert-ly.py:85 lilypond-book.py:122 midi2ly.py:1052
+#: abc2ly.py:1389 convert-ly.py:85 lilypond-book.py:122 midi2ly.py:1061
 #, python-format
 msgid "%s [OPTION]... FILE"
 msgstr ""
@@ -938,16 +938,16 @@ msgid ""
 msgstr ""
 
 #: abc2ly.py:1398 convert-ly.py:92 etf2ly.py:1208 lilypond-book.py:231
-#: midi2ly.py:1103 musicxml2ly.py:2774 main.cc:184
+#: midi2ly.py:1112 musicxml2ly.py:2774 main.cc:184
 msgid "show version number and exit"
 msgstr ""
 
 #: abc2ly.py:1401 convert-ly.py:96 etf2ly.py:1204 lilypond-book.py:140
-#: midi2ly.py:1070 musicxml2ly.py:2755 main.cc:163
+#: midi2ly.py:1079 musicxml2ly.py:2755 main.cc:163
 msgid "show this help and exit"
 msgstr ""
 
-#: abc2ly.py:1404 etf2ly.py:1209 midi2ly.py:1079
+#: abc2ly.py:1404 etf2ly.py:1209 midi2ly.py:1088
 msgid "write output to FILE"
 msgstr ""
 
@@ -968,7 +968,7 @@ msgstr ""
 #. or if there is a LilyPond users list or forum in your language
 #. "Report bugs in English via %s or in YOUR_LANG via URI"
 #: abc2ly.py:1416 convert-ly.py:157 etf2ly.py:1218 lilypond-book.py:258
-#: midi2ly.py:1115 musicxml2ly.py:2917 main.cc:318
+#: midi2ly.py:1124 musicxml2ly.py:2917 main.cc:318
 #, c-format, python-format
 msgid "Report bugs via %s"
 msgstr ""
@@ -1050,7 +1050,7 @@ msgstr ""
 msgid "make a numbered backup [default: filename.ext~]"
 msgstr ""
 
-#: convert-ly.py:152 etf2ly.py:1212 lilypond-book.py:234 midi2ly.py:1104
+#: convert-ly.py:152 etf2ly.py:1212 lilypond-book.py:234 midi2ly.py:1113
 #: main.cc:186
 msgid "show warranty and copyright"
 msgstr ""
@@ -1109,7 +1109,7 @@ msgid ""
 "file.\n"
 msgstr ""
 
-#: etf2ly.py:1210 midi2ly.py:1075 midi2ly.py:1080 musicxml2ly.py:2867
+#: etf2ly.py:1210 midi2ly.py:1084 midi2ly.py:1089 musicxml2ly.py:2867
 #: main.cc:169 main.cc:181
 msgid "FILE"
 msgstr ""
@@ -1216,7 +1216,7 @@ msgstr ""
 msgid "write snippet output files with the same base name as their source file"
 msgstr ""
 
-#: lilypond-book.py:223 midi2ly.py:1098 musicxml2ly.py:2780
+#: lilypond-book.py:223 midi2ly.py:1107 musicxml2ly.py:2780
 msgid "be verbose"
 msgstr ""
 
@@ -1318,7 +1318,7 @@ msgstr ""
 msgid "warning: "
 msgstr ""
 
-#: midi2ly.py:92 midi2ly.py:1132
+#: midi2ly.py:92 midi2ly.py:1141
 msgid "error: "
 msgstr ""
 
@@ -1326,85 +1326,85 @@ msgstr ""
 msgid "Exiting... "
 msgstr ""
 
-#: midi2ly.py:840
+#: midi2ly.py:849
 msgid "found more than 5 voices on a staff, expect bad output"
 msgstr ""
 
-#: midi2ly.py:1040
+#: midi2ly.py:1049
 #, python-format
 msgid "%s output to `%s'..."
 msgstr ""
 
-#: midi2ly.py:1053
+#: midi2ly.py:1062
 #, python-format
 msgid "Convert %s to LilyPond input.\n"
 msgstr ""
 
-#: midi2ly.py:1058
+#: midi2ly.py:1067
 msgid "print absolute pitches"
 msgstr ""
 
-#: midi2ly.py:1060 midi2ly.py:1088
+#: midi2ly.py:1069 midi2ly.py:1097
 msgid "DUR"
 msgstr ""
 
-#: midi2ly.py:1061
+#: midi2ly.py:1070
 msgid "quantise note durations on DUR"
 msgstr ""
 
-#: midi2ly.py:1064
+#: midi2ly.py:1073
 msgid "debug printing"
 msgstr ""
 
-#: midi2ly.py:1067
+#: midi2ly.py:1076
 msgid "print explicit durations"
 msgstr ""
 
-#: midi2ly.py:1072
+#: midi2ly.py:1081
 msgid "prepend FILE to output"
 msgstr ""
 
-#: midi2ly.py:1076
+#: midi2ly.py:1085
 msgid "set key: ALT=+sharps|-flats; MINOR=1"
 msgstr ""
 
-#: midi2ly.py:1077
+#: midi2ly.py:1086
 msgid "ALT[:MINOR]"
 msgstr ""
 
-#: midi2ly.py:1082
+#: midi2ly.py:1091
 msgid "preview of first 4 bars"
 msgstr ""
 
-#: midi2ly.py:1086
+#: midi2ly.py:1095
 msgid "suppress progress messages and warnings about excess voices"
 msgstr ""
 
-#: midi2ly.py:1087
+#: midi2ly.py:1096
 msgid "quantise note starts on DUR"
 msgstr ""
 
-#: midi2ly.py:1091
+#: midi2ly.py:1100
 msgid "use s instead of r for rests"
 msgstr ""
 
-#: midi2ly.py:1093
+#: midi2ly.py:1102
 msgid "DUR*NUM/DEN"
 msgstr ""
 
-#: midi2ly.py:1096
+#: midi2ly.py:1105
 msgid "allow tuplet durations DUR*NUM/DEN"
 msgstr ""
 
-#: midi2ly.py:1106
+#: midi2ly.py:1115
 msgid "treat every text as a lyric"
 msgstr ""
 
-#: midi2ly.py:1109
+#: midi2ly.py:1118
 msgid "Examples"
 msgstr ""
 
-#: midi2ly.py:1133
+#: midi2ly.py:1142
 msgid "no files specified on command line."
 msgstr ""
 
@@ -1746,12 +1746,12 @@ msgstr ""
 msgid "suppressed warning: %s"
 msgstr ""
 
-#: accidental-engraver.cc:180
+#: accidental-engraver.cc:181
 #, c-format
 msgid "accidental typesetting list must begin with context-name: %s"
 msgstr ""
 
-#: accidental-engraver.cc:207
+#: accidental-engraver.cc:208
 #, c-format
 msgid "procedure or context-name expected for accidental rule, found %s"
 msgstr ""
@@ -1805,15 +1805,15 @@ msgid ""
 "asked to compute volume at +%f for dynamic span of duration %f starting at %s"
 msgstr ""
 
-#: axis-group-engraver.cc:154
+#: axis-group-engraver.cc:155
 msgid "Axis_group_engraver: vertical group already has a parent"
 msgstr ""
 
-#: axis-group-engraver.cc:155
+#: axis-group-engraver.cc:156
 msgid "are there two Axis_group_engravers?"
 msgstr ""
 
-#: axis-group-engraver.cc:156
+#: axis-group-engraver.cc:157
 msgid "removing this vertical group"
 msgstr ""
 
@@ -1831,23 +1831,23 @@ msgstr ""
 msgid "barcheck failed at: %s"
 msgstr ""
 
-#: beam-engraver.cc:147
+#: beam-engraver.cc:148
 msgid "already have a beam"
 msgstr ""
 
-#: beam-engraver.cc:234
+#: beam-engraver.cc:235
 msgid "unterminated beam"
 msgstr ""
 
-#: beam-engraver.cc:281 chord-tremolo-engraver.cc:148
+#: beam-engraver.cc:282 chord-tremolo-engraver.cc:149
 msgid "stem must have Rhythmic structure"
 msgstr ""
 
-#: beam-engraver.cc:292
+#: beam-engraver.cc:293
 msgid "stem does not fit in beam"
 msgstr ""
 
-#: beam-engraver.cc:293
+#: beam-engraver.cc:294
 msgid "beam was started here"
 msgstr ""
 
@@ -1887,11 +1887,11 @@ msgstr ""
 msgid "none of these in my family"
 msgstr ""
 
-#: chord-tremolo-engraver.cc:87
+#: chord-tremolo-engraver.cc:88
 msgid "No tremolo to end"
 msgstr ""
 
-#: chord-tremolo-engraver.cc:108
+#: chord-tremolo-engraver.cc:109
 msgid "unterminated chord tremolo"
 msgstr ""
 
@@ -1969,31 +1969,31 @@ msgstr ""
 msgid "dot `%s' not found"
 msgstr ""
 
-#: dynamic-engraver.cc:166
+#: dynamic-engraver.cc:167
 #, c-format
 msgid ""
 "unknown crescendo style: %s\n"
 "defaulting to hairpin."
 msgstr ""
 
-#: dynamic-engraver.cc:231 slur-engraver.cc:185
+#: dynamic-engraver.cc:232 slur-engraver.cc:186
 #, c-format
 msgid "unterminated %s"
 msgstr ""
 
-#: episema-engraver.cc:74
+#: episema-engraver.cc:75
 msgid "already have an episema"
 msgstr ""
 
-#: episema-engraver.cc:87
+#: episema-engraver.cc:88
 msgid "cannot find start of episema"
 msgstr ""
 
-#: episema-engraver.cc:136
+#: episema-engraver.cc:137
 msgid "unterminated episema"
 msgstr ""
 
-#: extender-engraver.cc:167 extender-engraver.cc:176
+#: extender-engraver.cc:168 extender-engraver.cc:177
 msgid "unterminated extender"
 msgstr ""
 
@@ -2045,7 +2045,7 @@ msgstr ""
 msgid "Building font database..."
 msgstr ""
 
-#: footnote-engraver.cc:87
+#: footnote-engraver.cc:88
 msgid "Must be footnote-event."
 msgstr ""
 
@@ -2063,7 +2063,7 @@ msgstr ""
 msgid "g_spawn_sync failed (%d): %s: %s"
 msgstr ""
 
-#: glissando-engraver.cc:157
+#: glissando-engraver.cc:158
 msgid "unterminated glissando"
 msgstr ""
 
@@ -2080,23 +2080,23 @@ msgstr ""
 msgid "elapsed time: %.2f seconds"
 msgstr ""
 
-#: gregorian-ligature-engraver.cc:70
+#: gregorian-ligature-engraver.cc:71
 #, c-format
 msgid "\\%s ignored"
 msgstr ""
 
-#: gregorian-ligature-engraver.cc:75
+#: gregorian-ligature-engraver.cc:76
 #, c-format
 msgid "implied \\%s added"
 msgstr ""
 
 #. ligature may not start with 2nd head of pes or flexa
-#: gregorian-ligature-engraver.cc:224
+#: gregorian-ligature-engraver.cc:225
 msgid "cannot apply `\\~' on first head of ligature"
 msgstr ""
 
 #. (pitch == prev_pitch)
-#: gregorian-ligature-engraver.cc:236
+#: gregorian-ligature-engraver.cc:237
 msgid "cannot apply `\\~' on heads with identical pitch"
 msgstr ""
 
@@ -2124,23 +2124,23 @@ msgstr ""
 msgid "Asking for broken bound padding at a non-broken bound."
 msgstr ""
 
-#: hairpin.cc:257
+#: hairpin.cc:264
 msgid "decrescendo too small"
 msgstr ""
 
-#: horizontal-bracket-engraver.cc:61
+#: horizontal-bracket-engraver.cc:62
 msgid "do not have that many brackets"
 msgstr ""
 
-#: horizontal-bracket-engraver.cc:70
+#: horizontal-bracket-engraver.cc:71
 msgid "conflicting note group events"
 msgstr ""
 
-#: hyphen-engraver.cc:103
+#: hyphen-engraver.cc:104
 msgid "removing unterminated hyphen"
 msgstr ""
 
-#: hyphen-engraver.cc:117
+#: hyphen-engraver.cc:118
 msgid "unterminated hyphen; removing"
 msgstr ""
 
@@ -2158,12 +2158,12 @@ msgstr ""
 msgid "position unknown"
 msgstr ""
 
-#: keep-alive-together-engraver.cc:93
+#: keep-alive-together-engraver.cc:94
 #, c-format
 msgid "unknown remove-layer value `%s'"
 msgstr ""
 
-#: key-engraver.cc:197
+#: key-engraver.cc:199
 msgid "Incomplete keyAlterationOrder for key signature"
 msgstr ""
 
@@ -2176,31 +2176,31 @@ msgstr ""
 msgid "alteration not found"
 msgstr ""
 
-#: ligature-bracket-engraver.cc:71 ligature-engraver.cc:109
+#: ligature-bracket-engraver.cc:72 ligature-engraver.cc:110
 msgid "cannot find start of ligature"
 msgstr ""
 
-#: ligature-bracket-engraver.cc:84 ligature-engraver.cc:136
+#: ligature-bracket-engraver.cc:85 ligature-engraver.cc:137
 msgid "already have a ligature"
 msgstr ""
 
-#: ligature-engraver.cc:114
+#: ligature-engraver.cc:115
 msgid "no right bound"
 msgstr ""
 
-#: ligature-engraver.cc:145
+#: ligature-engraver.cc:146
 msgid "no left bound"
 msgstr ""
 
-#: ligature-engraver.cc:189
+#: ligature-engraver.cc:190
 msgid "unterminated ligature"
 msgstr ""
 
-#: ligature-engraver.cc:216
+#: ligature-engraver.cc:217
 msgid "ignoring rest: ligature may not contain rest"
 msgstr ""
 
-#: ligature-engraver.cc:217
+#: ligature-engraver.cc:218
 msgid "ligature was started here"
 msgstr ""
 
@@ -2507,45 +2507,45 @@ msgid "exception caught: %s"
 msgstr ""
 
 #. FIXME: constant error message.
-#: mark-engraver.cc:149
+#: mark-engraver.cc:150
 msgid "rehearsalMark must have integer value"
 msgstr ""
 
-#: mark-engraver.cc:155
+#: mark-engraver.cc:156
 msgid "mark label must be a markup object"
 msgstr ""
 
-#: mensural-ligature-engraver.cc:93
+#: mensural-ligature-engraver.cc:94
 msgid "ligature with less than 2 heads -> skipping"
 msgstr ""
 
-#: mensural-ligature-engraver.cc:120
+#: mensural-ligature-engraver.cc:121
 msgid "cannot determine pitch of ligature primitive -> skipping"
 msgstr ""
 
-#: mensural-ligature-engraver.cc:134
+#: mensural-ligature-engraver.cc:135
 msgid "single note ligature - skipping"
 msgstr ""
 
-#: mensural-ligature-engraver.cc:145
+#: mensural-ligature-engraver.cc:146
 msgid "prime interval within ligature -> skipping"
 msgstr ""
 
-#: mensural-ligature-engraver.cc:156
+#: mensural-ligature-engraver.cc:157
 msgid "mensural ligature: duration none of Mx, L, B, S -> skipping"
 msgstr ""
 
-#: mensural-ligature-engraver.cc:199
+#: mensural-ligature-engraver.cc:200
 msgid "semibrevis must be followed by another one -> skipping"
 msgstr ""
 
-#: mensural-ligature-engraver.cc:209
+#: mensural-ligature-engraver.cc:210
 msgid ""
 "semibreves can only appear at the beginning of a ligature,\n"
 "and there may be only zero or two of them"
 msgstr ""
 
-#: mensural-ligature-engraver.cc:229
+#: mensural-ligature-engraver.cc:230
 msgid ""
 "invalid ligatura ending:\n"
 "when the last note is a descending brevis,\n"
@@ -2553,7 +2553,7 @@ msgid ""
 "or the ligatura must be LB or SSB"
 msgstr ""
 
-#: mensural-ligature-engraver.cc:389
+#: mensural-ligature-engraver.cc:390
 msgid "unexpected case fall-through"
 msgstr ""
 
@@ -2595,7 +2595,7 @@ msgid ""
 "usable-duration-logs must be a non-empty list.  Falling back to whole rests."
 msgstr ""
 
-#: music.cc:154
+#: music.cc:153
 #, c-format
 msgid "octave check failed; expected \"%s\", found: \"%s\""
 msgstr ""
@@ -2625,7 +2625,7 @@ msgstr ""
 msgid "none of note heads `%s' or `%s' found"
 msgstr ""
 
-#: note-heads-engraver.cc:75
+#: note-heads-engraver.cc:76
 msgid "NoteEvent without pitch"
 msgstr ""
 
@@ -2720,12 +2720,12 @@ msgstr ""
 msgid "Replace font name from %s to %s."
 msgstr ""
 
-#: open-type-font.cc:321
+#: open-type-font.cc:320
 #, c-format
 msgid "FT_Get_Glyph_Name () Freetype error: %s"
 msgstr ""
 
-#: open-type-font.cc:469 pango-font.cc:261
+#: open-type-font.cc:468 pango-font.cc:260
 #, c-format
 msgid "FT_Get_Glyph_Name () error: %s"
 msgstr ""
@@ -2852,24 +2852,24 @@ msgstr ""
 msgid "\tprevious break: %d"
 msgstr ""
 
-#: pango-font.cc:250
+#: pango-font.cc:249
 #, c-format
 msgid "no glyph for character U+%0X in font `%s'"
 msgstr ""
 
-#: pango-font.cc:277
+#: pango-font.cc:276
 #, c-format
 msgid ""
 "Glyph has no name, but font supports glyph naming.\n"
 "Skipping glyph U+%0X, file %s"
 msgstr ""
 
-#: pango-font.cc:327
+#: pango-font.cc:326
 #, c-format
 msgid "no PostScript font name for font `%s'"
 msgstr ""
 
-#: pango-font.cc:377
+#: pango-font.cc:376
 msgid "FreeType face has no PostScript font name"
 msgstr ""
 
@@ -2883,7 +2883,7 @@ msgstr ""
 msgid "program option -dpreview not supported by backend `%s'"
 msgstr ""
 
-#: paper-column-engraver.cc:273
+#: paper-column-engraver.cc:274
 msgid ""
 "forced break was overridden by some other event, should you be using bar "
 "checks?"
@@ -2912,7 +2912,7 @@ msgstr ""
 msgid "Conversion of string `%s' to UTF-16be failed: %s"
 msgstr ""
 
-#: percent-repeat-engraver.cc:147
+#: percent-repeat-engraver.cc:148
 msgid "unterminated percent repeat"
 msgstr ""
 
@@ -2937,23 +2937,23 @@ msgstr ""
 msgid "Segment type of the Type 1 (PFB) font is unknown."
 msgstr ""
 
-#: piano-pedal-engraver.cc:276
+#: piano-pedal-engraver.cc:277
 #, c-format
 msgid "expect 3 strings for piano pedals, found: %ld"
 msgstr ""
 
-#: piano-pedal-engraver.cc:291 piano-pedal-engraver.cc:302
-#: piano-pedal-performer.cc:104
+#: piano-pedal-engraver.cc:292 piano-pedal-engraver.cc:303
+#: piano-pedal-performer.cc:105
 #, c-format
 msgid "cannot find start of piano pedal: `%s'"
 msgstr ""
 
-#: piano-pedal-engraver.cc:337
+#: piano-pedal-engraver.cc:338
 #, c-format
 msgid "cannot find start of piano pedal bracket: `%s'"
 msgstr ""
 
-#: program-option-scheme.cc:223
+#: program-option-scheme.cc:224
 #, c-format
 msgid "no such internal option: %s"
 msgstr ""
@@ -3085,11 +3085,11 @@ msgid "errors found, ignoring music expression"
 msgstr ""
 
 #. FIXME:
-#: script-engraver.cc:114
+#: script-engraver.cc:115
 msgid "do not know how to interpret articulation:"
 msgstr ""
 
-#: script-engraver.cc:115
+#: script-engraver.cc:116
 msgid " scheme encoding: "
 msgstr ""
 
@@ -3097,24 +3097,24 @@ msgstr ""
 msgid "direction must not be CENTER in ly:skyline-pair::skyline"
 msgstr ""
 
-#: slur-engraver.cc:121
+#: slur-engraver.cc:122
 #, c-format
 msgid "direction of %s invalid: %d"
 msgstr ""
 
 #. We already have an old slur, so give a warning
 #. and completely ignore the new slur.
-#: slur-engraver.cc:238
+#: slur-engraver.cc:239
 #, c-format
 msgid "already have %s"
 msgstr ""
 
-#: slur-engraver.cc:255
+#: slur-engraver.cc:256
 #, c-format
 msgid "%s without a cause"
 msgstr ""
 
-#: slur-engraver.cc:320
+#: slur-engraver.cc:321
 #, c-format
 msgid "cannot end %s"
 msgstr ""
@@ -3129,24 +3129,24 @@ msgstr ""
 msgid "expected to read %d characters, got %d"
 msgstr ""
 
-#: staff-performer.cc:273
+#: staff-performer.cc:274
 msgid "MIDI channel wrapped around"
 msgstr ""
 
-#: staff-performer.cc:274
+#: staff-performer.cc:275
 msgid "remapping modulo 16"
 msgstr ""
 
-#: stem-engraver.cc:100
+#: stem-engraver.cc:101
 msgid "tremolo duration is too long"
 msgstr ""
 
-#: stem-engraver.cc:152
+#: stem-engraver.cc:153
 #, c-format
 msgid "adding note head to incompatible stem (type = %d/%d)"
 msgstr ""
 
-#: stem-engraver.cc:155
+#: stem-engraver.cc:156
 msgid "maybe input should specify polyphonic voices"
 msgstr ""
 
@@ -3170,23 +3170,23 @@ msgstr ""
 msgid "Markup depth exceeds maximal value of %d; Markup: %s"
 msgstr ""
 
-#: text-spanner-engraver.cc:71
+#: text-spanner-engraver.cc:72
 msgid "cannot find start of text spanner"
 msgstr ""
 
-#: text-spanner-engraver.cc:84
+#: text-spanner-engraver.cc:85
 msgid "already have a text spanner"
 msgstr ""
 
-#: text-spanner-engraver.cc:131
+#: text-spanner-engraver.cc:132
 msgid "unterminated text spanner"
 msgstr ""
 
-#: tie-engraver.cc:120
+#: tie-engraver.cc:121
 msgid "unterminated tie"
 msgstr ""
 
-#: tie-engraver.cc:376
+#: tie-engraver.cc:377
 msgid "lonely tie"
 msgstr ""
 
@@ -3200,7 +3200,7 @@ msgstr ""
 msgid "strange time signature found: %d/%d"
 msgstr ""
 
-#: translator-ctors.cc:70
+#: translator-ctors.cc:118
 #, c-format
 msgid "unknown translator: `%s'"
 msgstr ""
@@ -3210,17 +3210,17 @@ msgstr ""
 msgid "fatal error.  Couldn't find type: %s"
 msgstr ""
 
-#: translator-group.cc:185
+#: translator-group.cc:176
 #, c-format
 msgid "cannot find: `%s'"
 msgstr ""
 
-#: translator.cc:305
+#: translator.cc:293
 #, c-format
 msgid "Two simultaneous %s events, junking this one"
 msgstr ""
 
-#: translator.cc:306
+#: translator.cc:294
 #, c-format
 msgid "Previous %s event here"
 msgstr ""
@@ -3229,26 +3229,26 @@ msgstr ""
 msgid "No tuplet to end"
 msgstr ""
 
-#: vaticana-ligature-engraver.cc:384
+#: vaticana-ligature-engraver.cc:385
 #, c-format
 msgid ""
 "ignored prefix(es) `%s' of this head according to restrictions of the "
 "selected ligature style"
 msgstr ""
 
-#: vaticana-ligature-engraver.cc:450
+#: vaticana-ligature-engraver.cc:451
 msgid ""
 "Ambiguous use of dots in ligature: there are multiple dotted notes with the "
 "same pitch.  The ligature should be split."
 msgstr ""
 
-#: vaticana-ligature-engraver.cc:508
+#: vaticana-ligature-engraver.cc:509
 msgid ""
 "This ligature has a dotted head followed by a non-dotted head.  The ligature "
 "should be split after the last dotted head before this head."
 msgstr ""
 
-#: vaticana-ligature-engraver.cc:720
+#: vaticana-ligature-engraver.cc:721
 #, c-format
 msgid "Vaticana_ligature_engraver: setting `spacing-increment = %f': ptr =%ul"
 msgstr ""
@@ -3261,24 +3261,24 @@ msgstr ""
 msgid "ascending vaticana style flexa"
 msgstr ""
 
-#: vertical-align-engraver.cc:100
+#: vertical-align-engraver.cc:101
 msgid "Ignoring Vertical_align_engraver in VerticalAxisGroup"
 msgstr ""
 
 #. fixme: be more verbose.
-#: volta-engraver.cc:110
+#: volta-engraver.cc:111
 msgid "cannot end volta spanner"
 msgstr ""
 
-#: volta-engraver.cc:120
+#: volta-engraver.cc:121
 msgid "already have a volta spanner, ending that one prematurely"
 msgstr ""
 
-#: volta-engraver.cc:124
+#: volta-engraver.cc:125
 msgid "also already have an ended spanner"
 msgstr ""
 
-#: volta-engraver.cc:125
+#: volta-engraver.cc:126
 msgid "giving up"
 msgstr ""
 
@@ -3596,27 +3596,27 @@ msgstr ""
 msgid "no systems found in \\score markup, does it have a \\layout block?"
 msgstr ""
 
-#: define-markup-commands.scm:3122
+#: define-markup-commands.scm:3127
 #, scheme-format
 msgid "Cannot find glyph ~a"
 msgstr ""
 
-#: define-markup-commands.scm:3598
+#: define-markup-commands.scm:3603
 #, scheme-format
 msgid "no brace found for point size ~S "
 msgstr ""
 
-#: define-markup-commands.scm:3599
+#: define-markup-commands.scm:3604
 #, scheme-format
 msgid "defaulting to ~S pt"
 msgstr ""
 
-#: define-markup-commands.scm:3858
+#: define-markup-commands.scm:3863
 #, scheme-format
 msgid "not a valid duration string: ~a"
 msgstr ""
 
-#: define-markup-commands.scm:4071
+#: define-markup-commands.scm:4076
 #, scheme-format
 msgid "not a valid duration string: ~a - ignoring"
 msgstr ""
@@ -3685,7 +3685,7 @@ msgstr ""
 msgid "cannot find description for property ~S (~S)"
 msgstr ""
 
-#: flag-styles.scm:154
+#: flag-styles.scm:156
 #, scheme-format
 msgid "flag stroke `~a' or `~a' not found"
 msgstr ""
index 19af006386168d2927bafa111d13e2848fdbd626..75bdc008e5dd4976232eb9fdcdb4090ade9ee74c 100644 (file)
@@ -2,7 +2,7 @@ depth = ..
 
 SUBDIRS=auxiliar
 
-STEPMAKE_TEMPLATES=python-module install-out po
+STEPMAKE_TEMPLATES=python-module install-out po
 
 include $(depth)/make/stepmake.make
 
@@ -19,8 +19,6 @@ INSTALLATION_OUT_DIR=$(local_lilypond_libdir)/python
 INSTALLATION_OUT_DIR1=$(local_lilypond_datadir)/python
 INSTALLATION_OUT_FILES1=$(OUT_PY_MODULES) $(OUT_PYC_MODULES)
 
-$(outdir)/midi.lo: $(outdir)/config.hh
-
 default: $(outdir)/relocate-preamble.py
 
 $(outdir)/relocate-preamble.py: $(depth)/VERSION
diff --git a/python/midi.c b/python/midi.c
deleted file mode 100644 (file)
index c7baeda..0000000
+++ /dev/null
@@ -1,469 +0,0 @@
-/*
-  This file is part of LilyPond, the GNU music typesetter.
-
-  Copyright (C) 2001--2015 Han-Wen Nienhuys <hanwen@xs4all.nl>
-            Jan Nieuwenhuizen <janneke@gnu.org>
-
-
-  LilyPond is free software: you can redistribute it and/or modify
-  it under the terms of the GNU General Public License as published by
-  the Free Software Foundation, either version 3 of the License, or
-  (at your option) any later version.
-
-  LilyPond is distributed in the hope that it will be useful,
-  but WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-  GNU General Public License for more details.
-
-  You should have received a copy of the GNU General Public License
-  along with LilyPond.  If not, see <http://www.gnu.org/licenses/>.
-*/
-
-/*
-
-python
-import midi
-s = open ("s.midi").read ()
-midi.parse_track (s)
-midi.parse (s)
-
-
-returns a MIDI file as the tuple
-
- ((format, division), TRACKLIST) 
-
-each track is an EVENTLIST, where EVENT is
-
-  (time, (type, ARG1, [ARG2]))
-
-*/
-
-#include <Python.h>
-
-char *
-compat_itoa (int i)
-{
-  static char buffer[9];
-  snprintf (buffer, 8, "%d", i);
-  return buffer;
-}
-
-/* PyMIDINIT_FUNC isn't defined in Python < 2.3 */
-#ifndef PyMODINIT_FUNC
-#       if defined(__cplusplus)
-#               define PyMODINIT_FUNC extern "C" void
-#       else /* __cplusplus */
-#               define PyMODINIT_FUNC void
-#       endif /* __cplusplus */
-#endif
-
-#if 0
-int x = 0;
-int *track = &x;
-#define urg_debug_print(f, args...) fprintf (stderr, "%s:%d: track: %p: " f, __FUNCTION__, __LINE__, *track, ##args)
-#define debug_print(f, args...) fprintf (stderr, f, ##args)
-#else
-#define debug_print(f, args...)
-#endif
-
-static PyObject *Midi_error;
-static PyObject *Midi_warning;
-
-static PyObject *
-midi_error (char const *func, char *s, char *t)
-{
-  char *dest = (char*) malloc (sizeof (char)
-                              * (strlen (func) + strlen (s) + strlen (t) + 1));
-  strcpy (dest, func);
-  strcat (dest, s);
-  strcat (dest, t);
-  PyErr_SetString (Midi_error, dest);
-  free (dest);
-  
-  return 0;
-}
-
-static PyObject *
-midi_warning (char const *s)
-{
-  PyErr_SetString (Midi_warning, s);
-  return 0;
-}
-
-
-typedef struct message {
-  unsigned char msg;
-  char * description;
-} message_t;
-
-message_t channelVoiceMessages[] = {
-  {0x80, "NOTE_OFF"},
-  {0x90, "NOTE_ON"},
-  {0xA0, "POLYPHONIC_KEY_PRESSURE"},
-  {0xB0, "CONTROLLER_CHANGE"},
-  {0xC0, "PROGRAM_CHANGE"},
-  {0xD0, "CHANNEL_KEY_PRESSURE"},
-  {0xE0, "PITCH_BEND"},
-  {0,0}
-};
-
-message_t channelModeMessages[] = {
-  {0x78, "ALL_SOUND_OFF"},
-  {0x79, "RESET_ALL_CONTROLLERS"},
-  {0x7A, "LOCAL_CONTROL"},
-  {0x7B, "ALL_NOTES_OFF"},
-  {0x7C, "OMNI_MODE_OFF"},
-  {0x7D, "OMNI_MODE_ON"},
-  {0x7E, "MONO_MODE_ON"},
-  {0x7F, "POLY_MODE_ON"},
-  {0,0}
-};
-
-message_t metaEvents[] = {
-  {0x00, "SEQUENCE_NUMBER"},
-  {0x01, "TEXT_EVENT"},
-  {0x02, "COPYRIGHT_NOTICE"},
-  {0x03, "SEQUENCE_TRACK_NAME"},
-  {0x04, "INSTRUMENT_NAME"},
-  {0x05, "LYRIC"},
-  {0x06, "MARKER"},
-  {0x07, "CUE_POINT"},
-  {0x20, "MIDI_CHANNEL_PREFIX"},
-  {0x21, "MIDI_PORT"},
-  {0x2F, "END_OF_TRACK"},
-  {0x51, "SET_TEMPO"},
-  {0x54, "SMTPE_OFFSET"},
-  {0x58, "TIME_SIGNATURE"},
-  {0x59, "KEY_SIGNATURE"},
-  {0x7F, "SEQUENCER_SPECIFIC_META_EVENT"},
-  {0xFF, "META_EVENT"},
-  {0,0}
-};
-
-void
-add_constants (PyObject *dict)
-{
-  message_t * p[] = {metaEvents, channelModeMessages, channelVoiceMessages ,0};
-  int i,j;
-  for ( j =0; p[j]; j++)
-    for ( i = 0; p[j][i].description; i++)
-      PyDict_SetItemString (dict, p[j][i].description, Py_BuildValue ("i", p[j][i].msg));
-}
-
-unsigned long int
-get_number (unsigned char ** str, unsigned char * end_str, int length)
-{
-  /* # MIDI uses big-endian for everything */
-  long sum = 0;
-  int i = 0;
-  
-  for (; i < length &&
-        ((*str) + i < end_str); i++)
-    sum = (sum << 8) + (unsigned char) (*str)[i];
-
-  *str += length;
-  debug_print ("%ld:\n", sum);
-  return sum;
-}
-
-unsigned long int
-get_variable_length_number (unsigned char **str, unsigned char * end_str)
-{
-  long sum = 0;
-
-  while (*str < end_str)
-    {
-      unsigned char x = **str;
-      (*str) ++;
-      sum = (sum << 7) + (x & 0x7F);
-      if (!(x & 0x80))
-       break;
-    }
-  debug_print ("%ld:\n", sum);
-  return sum;
-}
-
-PyObject *
-read_one_byte (unsigned char **track, unsigned char *end, 
-              unsigned char x)
-{
-  PyObject *pyev = Py_BuildValue ("(i)", x);
-  debug_print ("%x:%s", x, "event\n");
-
-  return pyev;
-}
-
-PyObject *
-read_two_bytes (unsigned char **track, unsigned char *end, 
-               unsigned char x)
-{
-  PyObject *pyev = Py_BuildValue ("(ii)", x, (*track)[0]);
-  *track += 1;
-  debug_print ("%x:%s", x, "event\n");
-  return pyev;
-}
-
-PyObject *
-read_three_bytes (unsigned char **track, unsigned char *end, 
-                 unsigned char x)
-{
-  PyObject *pyev = Py_BuildValue ("(iii)", x, (*track)[0],
-                                 (*track)[1]);
-
-  *track += 2;
-  debug_print ("%x:%s", x, "event\n");
-  return pyev;
-}
-
-PyObject *
-read_string (unsigned char **track, unsigned char *end) 
-{
-  unsigned long length = get_variable_length_number (track, end);
-  if (length > end - *track)
-    length = end - *track;
-
-  *track += length;
-  return Py_BuildValue ("s#", ((*track) -length), length);
-}
-
-typedef PyObject* (*Read_midi_event)
-  (unsigned char **track, unsigned char *end, 
-   unsigned char x);
-
-
-static PyObject *
-read_f0_byte (unsigned char **track, unsigned char *end, 
-             unsigned char x)
-             
-{
-  debug_print ("%x:%s", x, "event\n");
-  if (x == 0xff)
-    {
-      unsigned char z = (*track)[0 ];
-      *track += 1;
-      debug_print ("%x:%s", z, "f0-event\n");
-
-      return Py_BuildValue ("(iiO)", x, z, read_string (track, end));
-    }
-
-  return Py_BuildValue ("(iO)", x, read_string (track, end));
-}
-
-Read_midi_event read_midi_event [16] =
-{
-  read_one_byte,  //  0
-  read_one_byte,  // 10
-  read_one_byte,  // 20
-  read_one_byte,  // 30
-  read_one_byte,  // 40
-  read_one_byte,  // 50
-  read_one_byte,  // 60 data entry.
-  read_two_bytes, // 70 all notes off
-  read_three_bytes, // 80 note off
-  read_three_bytes, // 90 note on
-  read_three_bytes, // a0 poly aftertouch
-  read_three_bytes, // b0 control
-  read_two_bytes,  // c0 prog change
-  read_two_bytes, // d0 ch aftertouch
-  read_three_bytes, // e0 pitchwheel range 
-  read_f0_byte,   // f0
-};
-
-
-static PyObject *
-read_event (unsigned char **track, unsigned char *end, PyObject *time,
-           unsigned char *running_status)
-{
-  int rsb_skip = ((**track & 0x80)) ? 1 :0;
-
-  unsigned char x = (rsb_skip) ? (*track)[0]: *running_status;
-
-  PyObject * bare_event = 0;
-  debug_print ("%x:%s", x, "event\n");
-  *running_status = x;
-  *track += rsb_skip;
-  
-  //  printf ("%x %x %d next %x\n", x, (*track)[0], rsb_skip, (*track)[1]);
-  bare_event = (*read_midi_event[x >> 4]) (track, end, x);
-  if (bare_event)
-    return Py_BuildValue ("(OO)", time, bare_event);
-  else
-    return NULL;
-}
-
-static PyObject *
-midi_parse_track (unsigned char **track, unsigned char *track_end, int clocks_max)
-{
-  unsigned int time = 0;
-  unsigned long track_len, track_size;
-  PyObject *pytrack = 0;
-
-  debug_print ("%s", "\n");
-  
-  track_size = track_end - *track;
-
-  debug_print ("%s", "\n");
-  if (memcmp (*track, "MTrk", 4))
-    {
-      *track[4] = 0;
-      return midi_error (__FUNCTION__,  ": MTrk expected, got: ", *(char**)track);
-    }
-  
-  *track += 4;
-
-  track_len = get_number (track, *track + 4, 4);
-
-  debug_print ("track_len: %lu\n", track_len);
-  debug_print ("track_size: %lu\n", track_size);
-  debug_print ("track begin: %p\n", track);
-  debug_print ("track end: %p\n", track + track_len);
-  
-  if (track_len > track_size)
-    return midi_error (__FUNCTION__,  ": track length corrupt: ", compat_itoa (track_len));
-
-  pytrack = PyList_New (0);
-
-  if (*track + track_len < track_end)
-    track_end = *track + track_len;
-
-  {  
-    PyObject *pytime = PyInt_FromLong (0L);
-    unsigned char running_status = 0;
-       
-    while (*track < track_end)
-      {
-       long dt = get_variable_length_number(track, track_end);
-       PyObject *pyev = 0;
-
-       time += dt;
-       if (dt)
-         pytime = PyInt_FromLong (time);
-       if (clocks_max && time > clocks_max)
-         break;
-       pyev = read_event (track, track_end, pytime,
-                          &running_status);
-       if (pyev)
-         PyList_Append (pytrack, pyev);
-      }
-  }
-  
-  *track = track_end;
-  return pytrack;
-}
-
-
-static PyObject *
-pymidi_parse_track (PyObject *self, PyObject *args)
-{
-  unsigned char *track, *track_end;
-  int track_size;
-  int clocks_max;
-
-  debug_print ("%s", "\n");
-  if (!PyArg_ParseTuple (args, "s#|i", &track, &track_size, &clocks_max))
-    return 0;
-  debug_print ("clocks_max: %d\n", clocks_max);
-
-  if (track_size < 0)
-    return midi_error (__FUNCTION__,   ": negative track size: ", compat_itoa (track_size));
-
-  track_end = track + track_size;
-  
-  return midi_parse_track (&track, track_end, clocks_max);
-}
-
-static PyObject *
-midi_parse (unsigned char **midi,unsigned  char *midi_end, int clocks_max)
-{
-  PyObject *pymidi = 0;
-  unsigned long header_len;
-  unsigned format, tracks;
-  int division;
-  int i;
-  
-  debug_print ("%s", "\n");
-
-  /* Header */
-  header_len = get_number (midi, *midi + 4, 4);
-  
-  if (header_len < 6)
-    return midi_error (__FUNCTION__,  ": header too short: ", compat_itoa (header_len));
-    
-  format = get_number (midi, *midi + 2, 2);
-  tracks = get_number (midi, *midi + 2, 2);
-
-  if (tracks > 256)
-    return midi_error (__FUNCTION__,  ": too many tracks: ", compat_itoa (tracks));
-  
-  division = get_number (midi, *midi + 2, 2) * 4;
-
-
-  /*
-  if (division < 0)
-    return midi_error (cannot handle non-metrical time");
-    ;
-  */
-  *midi += header_len - 6;
-
-  pymidi = PyList_New (0);
-
-  /* Tracks */
-  for (i = 0; i < tracks; i++)
-    PyList_Append (pymidi, midi_parse_track (midi, midi_end, clocks_max));
-
-  pymidi = Py_BuildValue ("(OO)", Py_BuildValue ("(ii)", format, division),
-                         pymidi);
-  return pymidi;
-}
-
-static PyObject *
-pymidi_parse (PyObject *self, PyObject *args)
-{
-  unsigned char *midi, *midi_end;
-  unsigned long midi_size;
-  int clocks_max;
-  
-  debug_print ("%s", "\n");
-  if (!PyArg_ParseTuple (args, "s#|i", &midi, &midi_size, &clocks_max))
-    return 0;
-  debug_print ("clocks_max: %d\n", clocks_max);
-
-  if (memcmp (midi, "MThd", 4))
-    {
-      midi[4] = 0;
-      return midi_error (__FUNCTION__,  ": MThd expected, got: ", (char*)midi);
-    }
-
-  midi += 4;
-
-  midi_end = midi + midi_size;
-
-  return midi_parse (&midi, midi_end, clocks_max);
-}
-
-static PyMethodDef MidiMethods[] = 
-{
-  {"parse",  pymidi_parse, METH_VARARGS},
-  {"parse_track",  pymidi_parse_track, METH_VARARGS},
-  {0, 0}        /* Sentinel */
-};
-
-PyMODINIT_FUNC
-initmidi (void)
-{
-  PyObject *m, *d;
-  m = Py_InitModule ("midi", MidiMethods);
-  d = PyModule_GetDict (m);
-  
-  Midi_error = PyString_FromString ("midi.error");
-  PyDict_SetItemString (d, "error", Midi_error);
-  add_constants (d);
-  Midi_warning = PyString_FromString ("midi.warning");
-  PyDict_SetItemString (d, "warning", Midi_warning);
-
-  /*
-    FIXME.
-   */
-  (void) midi_warning;
-}
diff --git a/python/midi.py b/python/midi.py
new file mode 100644 (file)
index 0000000..45c2553
--- /dev/null
@@ -0,0 +1,199 @@
+# This file is part of LilyPond, the GNU music typesetter.
+#
+# Copyright (C) 2001--2012 Han-Wen Nienhuys <hanwen@xs4all.nl>
+#           Jan Nieuwenhuizen <janneke@gnu.org>
+#
+#
+# LilyPond is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# LilyPond is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with LilyPond.  If not, see <http://www.gnu.org/licenses/>.
+
+# import midi
+# s = open ("s.midi").read ()
+# midi.parse_track (s)
+# midi.parse (s)
+#
+#
+# returns a MIDI file as the tuple
+#
+#  ((format, division), TRACKLIST)          # division (>0) = TPQN*4
+#                                           # or (<0) TBD
+#
+# each track is an EVENTLIST, where EVENT is
+#
+#   (time, (type, ARG1, [ARG2]))            # time = cumulative delta time
+                                            # MIDI event: 
+                                            #   type = MIDI status+channel >= x80
+                                            # META-event  = xFF:
+                                            #   type = meta-event type <= x7F
+                                            #   ARG1 = length
+                                            #   ARG2 = data
+
+import array
+import struct
+
+class error (Exception): pass
+
+# class warning (Exception): pass
+
+def _add_constants ():
+    channelVoiceMessages = (
+        (0x80, "NOTE_OFF"),
+        (0x90, "NOTE_ON"),
+        (0xA0, "POLYPHONIC_KEY_PRESSURE"),
+        (0xB0, "CONTROLLER_CHANGE"),
+        (0xC0, "PROGRAM_CHANGE"),
+        (0xD0, "CHANNEL_KEY_PRESSURE"),
+        (0xE0, "PITCH_BEND"),
+    )
+    channelModeMessages = (
+        (0x78, "ALL_SOUND_OFF"),
+        (0x79, "RESET_ALL_CONTROLLERS"),
+        (0x7A, "LOCAL_CONTROL"),
+        (0x7B, "ALL_NOTES_OFF"),
+        (0x7C, "OMNI_MODE_OFF"),
+        (0x7D, "OMNI_MODE_ON"),
+        (0x7E, "MONO_MODE_ON"),
+        (0x7F, "POLY_MODE_ON"),
+    )
+    metaEvents = (
+        (0x00, "SEQUENCE_NUMBER"),
+        (0x01, "TEXT_EVENT"),
+        (0x02, "COPYRIGHT_NOTICE"),
+        (0x03, "SEQUENCE_TRACK_NAME"),
+        (0x04, "INSTRUMENT_NAME"),
+        (0x05, "LYRIC"),        #renamed LYRIC_DISPLAY MIDI RP-26
+        (0x06, "MARKER"),
+        (0x07, "CUE_POINT"),
+        (0x08, "PROGRAM_NAME"), #added MIDI RP-19
+        (0X09, "DEVICE_NAME"),  #added MIDI RP-19 
+        (0x20, "MIDI_CHANNEL_PREFIX"),
+        (0x21, "MIDI_PORT"),
+        (0x2F, "END_OF_TRACK"),
+        (0x51, "SET_TEMPO"),
+        (0x54, "SMTPE_OFFSET"),
+        (0x58, "TIME_SIGNATURE"),
+        (0x59, "KEY_SIGNATURE"),
+        (0x60, "XMF_PATCH_TYPE_PREFIX"),    #added MIDI RP-32
+        (0x7F, "SEQUENCER_SPECIFIC_META_EVENT"),
+        (0xFF, "META_EVENT"),
+    )
+    globals().update((desc, msg) for msg, desc in
+                       channelVoiceMessages + channelModeMessages + metaEvents)
+
+_add_constants ()
+
+def _get_variable_length_number (nextbyte, getbyte):
+    sum = 0
+    while nextbyte >= 0x80:
+        sum = (sum + (nextbyte & 0x7F)) << 7
+        nextbyte = getbyte()
+    return sum + nextbyte
+
+def _first_command_is_repeat(status, nextbyte, getbyte):
+    raise error('the first midi command in the track is a repeat')
+
+def _read_two_bytes (status, nextbyte, getbyte):
+    return status, nextbyte
+
+def _read_three_bytes (status, nextbyte, getbyte):
+    return status, nextbyte, getbyte()
+
+def _read_string (nextbyte, getbyte):
+    length = _get_variable_length_number (nextbyte, getbyte)
+    return ''.join(chr(getbyte()) for i in xrange(length))
+
+def _read_f0_byte (status, nextbyte, getbyte):
+    if status == 0xff:
+        return status, nextbyte, _read_string(getbyte(), getbyte)
+    return status, _read_string(nextbyte, getbyte)
+
+_read_midi_event = (
+    _first_command_is_repeat,  #  0
+    None,  # 10
+    None,  # 20
+    None,  # 30
+    None,  # 40
+    None,  # 50
+    None,  # 60 data entry???
+    None,  # 70 all notes off???
+    _read_three_bytes, # 80 note off
+    _read_three_bytes, # 90 note on
+    _read_three_bytes, # a0 poly aftertouch
+    _read_three_bytes, # b0 control
+    _read_two_bytes,  # c0 prog change
+    _read_two_bytes, # d0 ch aftertouch
+    _read_three_bytes, # e0 pitchwheel range
+    _read_f0_byte,   # f0
+)
+
+def _parse_track_body (data, clocks_max):
+    # This seems to be the fastest way of getting bytes in order as integers.
+    dataiter = iter(array.array('B', data))
+    getbyte = dataiter.next
+
+    time = 0
+    status = 0
+    try:
+        for nextbyte in dataiter:
+            time += _get_variable_length_number (nextbyte, getbyte)
+            if clocks_max and time > clocks_max:
+                break
+            nextbyte = getbyte()
+            if nextbyte >= 0x80:
+                status = nextbyte
+                nextbyte = getbyte()
+            yield time, _read_midi_event[status >> 4] (status, nextbyte, getbyte)
+    except StopIteration:
+        # If the track ended just before the start of an event, the for loop
+        # will exit normally. If it ends anywhere else, we end up here.
+        print len(list(dataiter))
+        raise error('a track ended in the middle of a MIDI command')
+
+def _parse_hunk (data, pos, type, magic):
+    if data[pos:pos+4] != magic:
+        raise error ('expected %r, got %r' % (magic, data[pos:pos+4]))
+    try:
+        length, = struct.unpack ('>I', data[pos+4:pos+8])
+    except struct.error:
+        raise error ('the %s header is truncated (may be an incomplete download)' % type)
+    endpos = pos + 8 + length
+    data = data[pos+8:endpos]
+    if len(data) != length:
+        raise error('the %s is truncated (may be an incomplete download)' % type)
+    return data, endpos
+
+def _parse_tracks (midi, pos, num_tracks, clocks_max):
+    if num_tracks > 256:
+        raise error('too many tracks: %d' % num_tracks)
+    for i in xrange(num_tracks):
+        trackdata, pos = _parse_hunk (midi, pos, 'track', 'MTrk')
+        yield list (_parse_track_body (trackdata, clocks_max))
+    # if pos < len(midi):
+    #     warn
+
+def parse_track (track, clocks_max=None):
+    track_body, end = _parse_hunk (track, 0, 'track', 'MTrk')
+    # if end < len(track):
+    #     warn
+    return list (_parse_track_body (track_body, clocks_max))
+
+def parse (midi, clocks_max=None):
+    header, first_track_pos = _parse_hunk(midi, 0, 'file', 'MThd')
+    try:
+        format, num_tracks, division = struct.unpack ('>3H', header[:6])
+    except struct.error:
+        raise error('the file header is too short')
+#  if division < 0:
+#    raise error ('cannot handle non-metrical time')
+    tracks = list (_parse_tracks (midi, first_track_pos, num_tracks, clocks_max))
+    return (format, division*4), tracks
index 86d12d9b217fe8c5f70ef869ff6d2e5a718955fb..3fad8f8912949bf96a9944b6a1019432be850cb3 100644 (file)
@@ -512,7 +512,7 @@ opening bracket will be drawn, for @code{RIGHT} we get the closing bracket."
                                               (interval-start extent)
                                               Y))))
 
-    (if (eq? dir LEFT)
+    (if (eqv? dir LEFT)
         stencil
         (ly:stencil-scale stencil -1 1))))
 
index 07f1538aa275dad7e07737548e2a0feb425f1b52..f048aeabce04d53c10ae7de663cdf8b9e133c987 100644 (file)
@@ -2251,6 +2251,14 @@ Set the dimensions of @var{arg} to @var{x} and@tie{}@var{y}."
       `(delay-stencil-evaluation ,(delay expr))
       x y))))
 
+(define-markup-command (with-outline layout props outline arg)
+  (markup? markup?)
+  #:category other
+  "
+Print @var{arg} with the outline and dimensions of @var{outline}."
+  (ly:stencil-outline (interpret-markup layout props arg)
+                      (interpret-markup layout props outline)))
+
 (define-markup-command (with-dimensions-from layout props arg1 arg2)
   (markup? markup?)
   #:category other
@@ -2333,10 +2341,7 @@ Add padding @var{amount} around @var{arg} in the X@tie{}direction.
   }
 }
 @end lilypond"
-  (let* ((m (interpret-markup layout props arg))
-         (x (ly:stencil-extent m X))
-         (y (ly:stencil-extent m Y)))
-    (ly:make-stencil (list 'transparent-stencil (ly:stencil-expr m)) x y)))
+  (ly:stencil-outline empty-stencil (interpret-markup layout props arg)))
 
 (define-markup-command (pad-to-box layout props x-ext y-ext arg)
   (number-pair? number-pair? markup?)
index 23c17abb9be42fabe29f8ef9584ced97dd2440d5..a7f762ecfdcc5447be93ef2149ba258d576f99ec 100644 (file)
@@ -68,6 +68,7 @@ are used internally in @file{lily/@/stencil-interpret.cc}."
     scale-stencil
     translate-stencil
     transparent-stencil
+    with-outline
     ))
 
 (for-each ly:register-stencil-expression
index 3738d2cabfaf5ccb8912794881157457c9ff05e2..6dda45292852bdc0937521eda8abb1286d343b91 100644 (file)
@@ -872,7 +872,7 @@ at @var{fret}."
          label-stencil
          (stencil-coordinates
           (* size fret-distance (1+ label-vertical-offset))
-          (if (eq? label-dir LEFT)
+          (if (eqv? label-dir LEFT)
               (- label-outside-diagram)
               (+ (* size string-distance (1- string-count))
                  label-outside-diagram))))))
index 46d085ef8f62212a0b022916ec12019f3a48095e..5184fdb3377fae3444b6d3a6b40a3d7075ab7611 100644 (file)
@@ -1205,7 +1205,7 @@ and draws the stencil based on its coordinates.
   ;; outer let to trigger suicide
   (let ((sten (ly:hairpin::print grob)))
     (if (grob::is-live? grob)
-        (let* ((decresc? (eq? (ly:grob-property grob 'grow-direction) LEFT))
+        (let* ((decresc? (eqv? (ly:grob-property grob 'grow-direction) LEFT))
                (thick (ly:grob-property grob 'thickness 0.1))
                (thick (* thick (layout-line-thickness grob)))
                (xex (ly:stencil-extent sten X))
index 1dd534344e4c910938d009dbd1b2f11d18a3e437..f4902cb94b99b2c31b05f064efca75bb8df13c01 100644 (file)
@@ -94,3 +94,26 @@ receive a count with @code{\\startMeasureCount} and
             (ly:grob-suicide! count-spanner)
             (set! count-spanner '())
             (ly:warning "measure count left unfinished")))))))
+
+(ly:register-translator
+ Measure_counter_engraver 'Measure_counter_engraver
+ '((grobs-created . (MeasureCounter))
+   (events-accepted . (measure-counter-event))
+   (properties-read . (currentCommandColumn
+                       measurePosition
+                       currentBarNumber))
+   (properties-written . ())
+   (description . "\
+This engraver numbers ranges of measures, which is useful in parts as an
+aid for counting repeated measures.  There is no requirement that the
+affected measures be repeated, however.  The user delimits the area to
+receive a count with @code{\\startMeasureCount} and
+@code{\\stopMeasureCount}.")))
+
+(ly:register-translator
+ Span_stem_engraver 'Span_stem_engraver
+ '((grobs-created . (Stem))
+   (events-accepted . ())
+   (properties-read . ())
+   (properties-written . ())
+   (description . "Connect cross-staff stems to the stems above in the system")))
index 433bf634d8c21961814c74961612d8088e6a2ccb..0fa79d4161376d45f61b0bc1232fc3abcbb4eda5 100644 (file)
@@ -238,10 +238,7 @@ the more angular the shape of the parenthesis."
 
 (define-public (make-transparent-box-stencil xext yext)
   "Make a transparent box."
-  (ly:make-stencil
-   (list 'transparent-stencil
-         (ly:stencil-expr (make-filled-box-stencil xext yext)))
-   xext yext))
+  (ly:stencil-outline empty-stencil (make-filled-box-stencil xext yext)))
 
 (define-public (make-filled-box-stencil xext yext)
   "Make a filled box."
@@ -1129,6 +1126,9 @@ grestore
          ((eq? head 'color) (interpret (caddr expr)))
          ((eq? head 'rotate-stencil) (interpret (caddr expr)))
          ((eq? head 'translate-stencil) (interpret (caddr expr)))
+         ;; for signatures, we indeed want the _outline_ rather than
+         ;; the expression interpreted.  Right?
+         ((eq? head 'with-outline) (interpret (cadr expr)))
          ((eq? head 'combine-stencil)
           (for-each interpret  (cdr expr)))
          (else
index 3a29f9aaa1cebe66db1b3c16b770dd7a866b9b58..9c490a5f2caf95bd737fee5046878054f69ab364 100644 (file)
@@ -382,12 +382,21 @@ class Text:
         'INSTRUMENT_NAME',
         'LYRIC',
         'MARKER',
-        'CUE_POINT',)
+        'CUE_POINT',
+        'PROGRAM_NAME',
+        'DEVICE_NAME', )
+
+    @staticmethod
+    def _text_only(chr):
+        if ((' ' <= chr <= '~') or chr in ['\n','\r']):
+            return chr
+        else: 
+            return '~'
 
     def __init__ (self, type, text):
         self.clocks = 0
         self.type = type
-        self.text = text
+        self.text =''.join(map(self._text_only, text))
 
     def dump (self):
         # urg, we should be sure that we're in a lyrics staff