James Lowe <james@james-lilybunto.(none)>
James Lowe <james@james-lily.(none)>
James Lowe <james.lowe@datacore.com>
+James Lowe <jlowe@james-ubuntu.(none)>
Jan Nieuwenhuizen <jan>
Jan Nieuwenhuizen <janneke>
Jan Nieuwenhuizen <janneke@gnu.org>
Joseph Wakeling <joseph.wakeling@webdrake.net>
Jürgen Reuter <reuter>
Jürgen Reuter <reuter@ipd.uka.de>
+Keith OHara <k-ohara5a5a@oco.net>
Kevin Dalley <kevin@kelphead.org>
Kieren MacMillan <kieren_macmillan@sympatico.ca>
Kurt Kroon <kroon@winfirst.com>
@end ignore
+@item
+By using @code{\cueDuringWithClef}, cue notes can now also have their own
+clef, which is correctly reset at the end of the cue notes. At the begin
+of each line, the standard clef is still displayed, but the cue clef is
+shown after the time/key signature in smaller size.
+@lilypond
+vI = \relative c'' { \clef "treble" \repeat unfold 40 g4 }
+\addQuote vIQuote { \vI }
+
+Solo = \relative c {
+ \clef "bass"
+ \cueDuringWithClef #"vIQuote" #DOWN #"treble" { R1 } |
+ c4 \cueDuringWithClef #"vIQuote" #DOWN #"treble" {
+ r4 r2 |
+ r4
+ } c4 c2 |
+ \cueDuringWithClef #"vIQuote" #DOWN "soprano" { R1*2 \break R1 } |
+ c1
+}
+
+\score {
+ <<
+ \new Staff \new Voice \Solo
+ >>
+}
+@end lilypond
+
+
@item
Note names can be selected with a new
@code{@bs{}language "italiano"} command, which
@node Lilydev
@section Lilydev
-text.
+This section discusses how to install and use the Ubuntu LilyPond
+Development Remix.
@menu
* Installing lilydev::
@advanced{Some users might want these files, but if you don't
recognize what they are, then you don't want them:
+@*
@uref{http://files.lilynet.net/ubuntu-lilydev-remix-1.0.iso.md5}
+@*
@uref{http://files.lilynet.net/ubuntu-lilydev-remix-1.0.iso.torrent}
}
their intended contributions:
@itemize
-@item @rcontrib{Documentation work}
-@item @rcontrib{Translating the documentation}
-@item @rcontrib{Website work}
-@item @rcontrib{Regression tests}
-@item @rcontrib{Programming work}
+@item @ref{Documentation work}
+@item @ref{Translating the documentation}
+@item @ref{Website work}
+@item @ref{Regression tests}
+@item @ref{Programming work}
+@end itemize
+
+These chapters are mainly intended for people not using LilyDev,
+but they contain extra information about the
+@qq{behind-the-scenes} activities. We recommend that you read
+these at your leisure, a few weeks after beginning work with
+LilyDev.
+
+@itemize
+@item @ref{Working with source code}
+@item @ref{Compiling}
@end itemize
is made automatically upon compiling the regression test suite
twice.
-Before making changes, a baseline should be established by running:
+@enumerate
+
+@item
+Before making changes, a baseline should be established by
+running:
@example
make test-baseline
@end example
-After making the changes, the code should be checked by running:
+@item
+Make your changes, or apply the patch(es) to consider.
+
+@item
+Check for unintentional changes to the regtests:
@example
make check
@end example
-After @samp{make@tie{}check} is complete, a regression test comparison
-will be available at @file{out/test-results/index.html}.
+After this has finished, a regression test comparison will be
+available at:
+
+@example
+out/test-results/index.html
+@end example
+
For each regression test that differs between the baseline and the
-changed code, a regression test entry will displayed. Ideally, the
-only changes would be the changes that you were working on. If
-regressions are introduced, they must be fixed before committing the
-code.
+changed code, a regression test entry will displayed. Ideally,
+the only changes would be the changes that you were working on.
+If regressions are introduced, they must be fixed before
+committing the code.
@warning{
The special regression test @file{test-output-distance.ly} will always
show up as a regression. This test changes each time it is run, and
serves to verify that the regression tests have, in fact, run.}
-Once @samp{make@tie{}test-baseline} and @samp{make@tie{}check} have been
-run, the files that differ between @samp{test-baseline} and @samp{check}
-can be repeatedly examined by doing:
+@item
+If you are happy with the results, then stop now.
+
+If you want to continue programming, then make any additional code
+changes, and continue.
+
+@item
+To re-check files that differed between the initial
+@samp{make@tie{}test-baseline} and your post-changes
+@samp{make@tie{}check}, run:
@example
make test-redo
This updates the regression list at @file{out/test-results/index.html}.
It does @emph{not} redo @file{test-output-distance.ly}.
+@item
When all regressions have been resolved, the output list will be empty.
+@item
Once all regressions have been resolved, a final check should be completed
by running:
This cleans the results of the previous @samp{make@tie{}check}, then does the
automatic regression comparison again.
+@end enumerate
+
@node Memory and coverage tests
@section Memory and coverage tests
@uref{http://codereview.appspot.com/}
@end example
-@subsubheading Initial setup
+@subsubheading @command{git-cl} install
-@enumerate
+LilyDev users should skip over these @q{install} instructions.
-@item
-You must have a gmail account.
+@enumerate
@item
Install @command{git-cl} by entering:
scripts in one of your PATH directories (such as
@file{$HOME/bin}).
+@end enumerate
+
+@subsubheading @command{git-cl} configuration
+
+LilyDev users should perform these @q{configuration} instructions.
+
+@enumerate
+@item
+You must have a gmail account; please create one if you do not
+have one already.
@item
-Move into the top source directory and then configure
-@command{git cl}. If you do not understand any question, just
-answer with a newline (CR).
+Move into the top source directory and then configure @command{git
+cl} with the following commands. If you do not understand any
+question, just answer with a newline (CR).
@example
cd $HOME/lilypond-git/
@unnumberedsubsubsec Quadrillage temporel
@translationof Grid lines
-@cindex cadrillage temporel
-@cindex temporel, cadrillage
+@cindex quadrillage temporel
+@cindex temporel, quadrillage
@funindex Grid_point_engraver
@funindex Grid_line_span_engraver
%% Translation of GIT committish: 9ccf7f0f5e52e074f3b7852416ad5b78718395c8
texidocfr = "
-Modifier certaines des propriétés du cadrillage temporel aura pour effet
+Modifier certaines des propriétés du quadrillage temporel aura pour effet
d'en changer l'apparence.
"
- doctitlefr = "Apparence du cadrillage temporel"
+ doctitlefr = "Apparence du quadrillage temporel"
@cindex clefs, visibility of octavation
The small octavation symbol on octavated clefs is produced by the
-@code{OctavateEight} layout object. Its visibility is controlled
-independently from that of the @code{Clef} object, so it is
-necessary to apply any required @code{break-visibility} overrides
-to both the @code{Clef} and the @code{OctavateEight} layout objects
-to fully suppress such clef symbols at the start of each line.
+@code{OctavateEight} layout object. Its visibility is automatically
+inherited from the @code{Clef} object, so it is not necessary to apply
+any required @code{break-visibility} overrides to the @code{OctavateEight}
+layout objects to suppress octavation symbols for invisible clefs.
For explicit clef changes, the @code{explicitClefVisibility}
property controls both the clef symbol and any octavation symbol
example of beam tweaking, see @rlearning{Fixing overlapping
notation}.
+@cindex cross-staff collisions
+@cindex collisions, cross-staff voices
+
+Overlapping notation can result when voices cross staves:
+
+@lilypond[verbatim,quote]
+\new PianoStaff <<
+ \new Staff = "up" {
+ \voiceOne
+ % Make space for fingering in the cross-staff voice
+ \once\override DynamicLineSpanner #'staff-padding = #3.4
+ e''2\p\< d''\> s1*0\!
+ }
+ \new Staff = "down" <<
+ {
+ \clef bass
+ s4. e,8\rest g,2\rest
+ } \\ {
+ c8\( g c'
+ \change Staff = "up"
+ e' g' b'-3 a' g'\)
+ }
+ >>
+>>
+@end lilypond
+
+The stem and slur overlap the intervening line of dynamics
+because automatic collision resolution is suspended for beams, slurs
+and other spanners that connect notes on different staves,
+as well as for stems and articulations if their placement is
+affected by a cross-staff spanner.
+The resulting collisions must be resolved manually, where necessary,
+using the methods in @rlearning{Fixing overlapping notation}.
@seealso
Learning Manual:
--- /dev/null
+\version "2.13.45"
+
+\header {
+
+ texidoc = "Octavation signs may be added to clefs. By default,
+their break-visibility is derived from the associated clef, but it may
+be overridden explicitly. The initial treble_8 clef should not have an
+8, while the treble_8 clef after the tenor clef should.
+These settings also need to apply to clefs on new lines."
+
+}
+\layout { ragged-right = ##t }
+
+
+\relative c' {
+ \override Staff.OctavateEight #'break-visibility = #all-invisible
+
+ \clef "treble_8"
+ c2 c |
+ c c | \break
+ c \clef "tenor" c |
+ \revert Staff.OctavateEight #'break-visibility
+ \clef "treble_8"
+ c2 c |
+ c c | \break
+ c c
+}
+
--- /dev/null
+\version "2.13.45"
+
+\header {
+ texidoc = "Clefs for cue notes at the start of a score should print the
+standard clef plus a small cue clef after the time/key signature."
+}
+
+vI = \relative c'' { \clef "treble" \repeat unfold 40 g4 }
+\addQuote vIQuote { \vI }
+
+Solo = \relative c'' {
+ \clef "bass"
+ \cueDuringWithClef #"vIQuote" #DOWN #"treble" { r2 } d,,4 d4 |
+}
+
+\score {
+ <<
+ \new Staff \new Voice \Solo
+ >>
+}
--- /dev/null
+\version "2.13.45"
+
+\header {
+ texidoc = "Clefs for cue notes and line breaks. If the cue notes start in a
+new line, the cue clef should not be printed at the end of the previous line.
+Similarly, an end clef for cue notes ending at a line break should only be
+printed at the end of the line.
+
+Cue notes going over a line break should print the standard clef on the new
+line plus an additional cue clef after the time/key signature."
+}
+
+vI = \relative c'' { \clef "treble" \repeat unfold 40 g4 }
+\addQuote vIQuote { \vI }
+
+Solo = \relative c {
+ \clef "bass"
+ c1 | \break
+ \cueDuringWithClef #"vIQuote" #UP #"tenor" { R1 } | \break
+ c1 |
+ \cueDuringWithClef #"vIQuote" #UP #"tenor" { R1 | \break
+ R1 } |
+ c1
+}
+
+\score {
+ <<
+ \new Staff \new Voice \Solo
+ >>
+}
--- /dev/null
+\version "2.13.45"
+
+\header {
+ texidoc = "Octavation for clefs for cue notes."
+}
+
+vI = \relative c'' { \clef "treble" \repeat unfold 40 g4 }
+\addQuote vIQuote { \vI }
+
+Solo = \relative c' {
+ \clef "treble_8" c1 |
+ \cueDuringWithClef #"vIQuote" #UP #"bass^8" { R1 } |
+ c1 | \break
+ c c
+ \clef "bass^8" c1 |
+ \cueDuringWithClef #"vIQuote" #UP #"treble_8" { R1 R1 } |
+ c
+ \cueDuringWithClef #"vIQuote" #UP #"treble_8" { R1 \break R } |
+ c
+}
+
+\score {
+ <<
+ \new Staff \new Voice \Solo
+ >>
+}
--- /dev/null
+\version "2.13.45"
+
+\header {
+ texidoc = "Clefs for cue notes: Print a cue clef at the begin of the cue
+notes and a cancelling clef after the cue notes."
+}
+
+vI = \relative c'' { \clef "treble" \repeat unfold 16 g4 }
+\addQuote vIQuote { \vI }
+
+Solo = \relative c {
+ \clef "bass"
+ c4 \cueDuringWithClef #"vIQuote" #DOWN #"treble" {
+ r4 r2 |
+ r4
+ } c4 c2 |
+ \cueDuringWithClef #"vIQuote" #DOWN "soprano" { R1*2 } |
+ c1
+}
+
+\score {
+ <<
+ \new Staff \new Voice \Solo
+ >>
+}
public:
TRANSLATOR_DECLARATIONS (Clef_engraver);
- Direction octave_dir_;
-
protected:
void stop_translation_timestep ();
void process_music ();
Clef_engraver::Clef_engraver ()
{
clef_ = 0;
- octave_dir_ = CENTER;
octavate_ = 0;
/*
void
Clef_engraver::acknowledge_bar_line (Grob_info info)
{
- Item *item = dynamic_cast<Item *> (info.grob ());
+ Item *item = info.item ();
if (item && scm_is_string (get_property ("clefGlyph")))
create_clef ();
}
vis = get_property ("explicitClefVisibility");
if (vis)
- {
- clef_->set_property ("break-visibility", vis);
- if (octavate_)
- octavate_->set_property ("break-visibility", vis);
- }
+ clef_->set_property ("break-visibility", vis);
clef_ = 0;
--- /dev/null
+/*
+ This file is part of LilyPond, the GNU music typesetter.
+
+ Copyright (C) 1997--2010 Han-Wen Nienhuys <hanwen@xs4all.nl>
+ Mats Bengtsson <matsb@s3.kth.se>
+ Copyright (C) 2010 Reinhold Kainhofer <reinhold@kainhofer.com>
+
+ 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/>.
+*/
+
+#include <cctype>
+using namespace std;
+
+#include "item.hh"
+#include "context.hh"
+#include "bar-line.hh"
+#include "staff-symbol-referencer.hh"
+#include "engraver.hh"
+#include "direction.hh"
+#include "side-position-interface.hh"
+#include "warn.hh"
+#include "international.hh"
+
+#include "translator.icc"
+
+class Cue_clef_engraver : public Engraver
+{
+public:
+ TRANSLATOR_DECLARATIONS (Cue_clef_engraver);
+
+protected:
+ void stop_translation_timestep ();
+ void process_music ();
+ DECLARE_ACKNOWLEDGER (bar_line);
+
+ virtual void derived_mark () const;
+private:
+ Item *clef_;
+ Item *octavate_;
+
+ SCM prev_glyph_;
+ SCM prev_cpos_;
+ SCM prev_octavation_;
+ void create_clef ();
+ void create_end_clef ();
+ void set_glyph ();
+ void inspect_clef_properties ();
+ void create_octavate_eight (SCM oct);
+};
+
+void
+Cue_clef_engraver::derived_mark () const
+{
+ scm_gc_mark (prev_octavation_);
+ scm_gc_mark (prev_cpos_);
+ scm_gc_mark (prev_glyph_);
+}
+
+Cue_clef_engraver::Cue_clef_engraver ()
+{
+ clef_ = 0;
+ octavate_ = 0;
+
+ prev_octavation_ = prev_cpos_ = prev_glyph_ = SCM_EOL;
+}
+
+void
+Cue_clef_engraver::set_glyph ()
+{
+ SCM glyph_sym = ly_symbol2scm ("glyph");
+ SCM basic = ly_symbol2scm ("CueClef");
+ execute_pushpop_property (context (), basic, glyph_sym, SCM_UNDEFINED);
+ execute_pushpop_property (context (), basic, glyph_sym, get_property ("cueClefGlyph"));
+
+ basic = ly_symbol2scm ("CueEndClef");
+ execute_pushpop_property (context (), basic, glyph_sym, SCM_UNDEFINED);
+ execute_pushpop_property (context (), basic, glyph_sym, get_property ("clefGlyph"));
+}
+
+/**
+ Generate a clef at the start of a measure. (when you see a Bar,
+ ie. a breakpoint)
+*/
+void
+Cue_clef_engraver::acknowledge_bar_line (Grob_info info)
+{
+ Item *item = info.item ();
+ if (item && scm_is_string (get_property ("cueClefGlyph")))
+ create_clef ();
+}
+
+void
+Cue_clef_engraver::create_octavate_eight (SCM oct)
+{
+ if (scm_is_number (oct) && scm_to_int (oct))
+ {
+ Item *g = make_item ("OctavateEight", SCM_EOL);
+
+ int abs_oct = scm_to_int (oct);
+ int dir = sign (abs_oct);
+ abs_oct = abs (abs_oct) + 1;
+
+ SCM txt = scm_number_to_string (scm_from_int (abs_oct),
+ scm_from_int (10));
+
+ g->set_property ("text",
+ scm_list_n (ly_lily_module_constant ("vcenter-markup"),
+ txt, SCM_UNDEFINED));
+ Side_position_interface::add_support (g, clef_);
+
+ g->set_parent (clef_, Y_AXIS);
+ g->set_parent (clef_, X_AXIS);
+ g->set_property ("direction", scm_from_int (dir));
+ octavate_ = g;
+ }
+}
+
+void
+Cue_clef_engraver::create_clef ()
+{
+ if (!clef_)
+ {
+ Item *c = make_item ("CueClef", SCM_EOL);
+
+ clef_ = c;
+ SCM cpos = get_property ("cueClefPosition");
+ if (scm_is_number (cpos))
+ clef_->set_property ("staff-position", cpos);
+
+ create_octavate_eight (get_property ("cueClefOctavation"));
+ }
+}
+
+void
+Cue_clef_engraver::create_end_clef ()
+{
+ if (!clef_)
+ {
+ clef_ = make_item ("CueEndClef", SCM_EOL);
+ SCM cpos = get_property ("clefPosition");
+ if (scm_is_number (cpos))
+ clef_->set_property ("staff-position", cpos);
+
+ create_octavate_eight (get_property ("clefOctavation"));
+ }
+}
+
+void
+Cue_clef_engraver::process_music ()
+{
+ inspect_clef_properties ();
+}
+
+void
+Cue_clef_engraver::inspect_clef_properties ()
+{
+ SCM glyph = get_property ("cueClefGlyph");
+ SCM clefpos = get_property ("cueClefPosition");
+ SCM octavation = get_property ("cueClefOctavation");
+
+ if (scm_equal_p (glyph, prev_glyph_) == SCM_BOOL_F
+ || scm_equal_p (clefpos, prev_cpos_) == SCM_BOOL_F
+ || scm_equal_p (octavation, prev_octavation_) == SCM_BOOL_F)
+ {
+ set_glyph ();
+ if (scm_is_string (glyph))
+ {
+ create_clef ();
+ if (clef_)
+ clef_->set_property ("non-default", SCM_BOOL_T);
+ }
+ else
+ create_end_clef ();
+
+ prev_cpos_ = clefpos;
+ prev_glyph_ = glyph;
+ prev_octavation_ = octavation;
+ }
+
+}
+
+void
+Cue_clef_engraver::stop_translation_timestep ()
+{
+ if (clef_)
+ {
+ SCM vis = 0;
+ if (to_boolean (clef_->get_property ("non-default")))
+ vis = get_property ("explicitCueClefVisibility");
+
+ if (vis)
+ clef_->set_property ("break-visibility", vis);
+
+ clef_ = 0;
+ octavate_ = 0;
+ }
+}
+
+ADD_ACKNOWLEDGER (Cue_clef_engraver, bar_line);
+ADD_TRANSLATOR (Cue_clef_engraver,
+ /* doc */
+ "Determine and set reference point for pitches in cued voices.",
+
+ /* create */
+ "CueClef "
+ "CueEndClef "
+ "OctavateEight ",
+
+ /* read */
+ "cueClefGlyph "
+ "cueClefOctavation "
+ "cueClefPosition "
+ "explicitCueClefVisibility "
+ "middleCCuePosition "
+ "clefOctavation ",
+
+ /* write */
+ ""
+ );
struct Break_position
{
/*
- index in system_spec_index_, if VPOS start of book.
+ index into system_specs_, if this is VPOS, the Break_position represents the
+ start of the book.
*/
vsize system_spec_index_;
- /* if system_spec_index_ is a score, then we start at the score_brk_'th possible
- page-break in the score */
+ /* if system_spec_index_ indexes a score, then we start at the score_brk_'th
+ possible page-break in the score */
vsize score_break_;
- /* if system_spec_index_ is a score, this points to the broken column */
+ /* if system_spec_index_ indexes a score, this points to the broken column */
Grob *col_;
bool score_ender_;
}
else
{
+ /* If systems-per-page and page-count are both specified, we know exactly
+ how many systems should be present. */
+ if (systems_per_page () > 0)
+ {
+ ideal_sys_count = systems_per_page () * page_count;
+
+ if (ideal_sys_count > max_system_count (0, end)
+ || ideal_sys_count < min_system_count (0, end))
+ {
+ warning (_ ("could not satisfy systems-per-page and page-count at the same time, ignoring systems-per-page"));
+ ideal_sys_count = best.system_count ();
+ min_sys_count = page_count;
+ }
+ else
+ {
+ set_current_breakpoints (0, end, ideal_sys_count);
+ min_sys_count = max_sys_count = ideal_sys_count;
+ ideal_line_division = best_division = current_configuration (0);
+ }
+ }
+ else
+ min_sys_count = page_count;
+
/* TODO: the following line will spit out programming errors if the
ideal line spacing doesn't fit on PAGE_COUNT pages */
- /* TODO: the interaction between systems_per_page and page_count needs to
- be considered. */
best = space_systems_on_n_pages (0, page_count, first_page_num);
- min_sys_count = page_count;
}
if (page_count == 1)
/* try a smaller number of systems than the ideal number for line breaking */
Line_division bound = ideal_line_division;
- for (vsize sys_count = ideal_sys_count; --sys_count >= min_sys_count;)
+ for (vsize sys_count = ideal_sys_count + 1; --sys_count >= min_sys_count;)
{
Page_spacing_result best_for_this_sys_count;
set_current_breakpoints (0, end, sys_count, Line_division (), bound);
ret = scm_cons (page, ret);
--page_num;
}
+
+ // By reversing the table, we ensure that duplicated labels (eg. those
+ // straddling a page turn) will appear in the table with their last
+ // occurence first.
+ label_page_table = scm_reverse_x (label_page_table, SCM_EOL);
book_->top_paper ()->set_variable (ly_symbol2scm ("label-page-table"), label_page_table);
return ret;
}
return ret;
}
+// Returns the minimum number of _non-title_ lines.
vsize
Page_breaking::min_system_count (vsize start, vsize end)
{
return ret;
}
+// Returns the maximum number of _non-title_ lines.
vsize
Page_breaking::max_system_count (vsize start, vsize end)
{
return ret;
}
+// The numbers returned by this function represent either
+// the maximum or minimum number of _non-title_ lines
+// per chunk.
Page_breaking::Line_division
Page_breaking::system_count_bounds (vector<Break_position> const &chunks,
bool min)
assert (chunks.size () >= 2);
Line_division ret;
- ret.resize (chunks.size () - 1, 1);
+ ret.resize (chunks.size () - 1, 0);
for (vsize i = 0; i + 1 < chunks.size (); i++)
{
div.push_back (line_breaking_[sys].best_solution (start, end).size ());
}
else
- div.push_back (1);
+ div.push_back (0);
system_count_ += div.back ();
}
}
else
{
- assert (div[i] == 1);
+ assert (div[i] == 0);
uncompressed_line_details_.push_back (system_specs_[sys].prob_
? Line_details (system_specs_[sys].prob_, book_->paper_)
: Line_details ());
int real_min = max ((int) min_sys[my_index], (int) system_count - others_max);
int real_max = min ((int) max_sys[my_index], (int) system_count - others_min);
- if (real_min > real_max || real_min <= 0)
+ if (real_min > real_max || real_min < 0)
{
/* this should never happen within a recursive call. If it happens
at all, it means that we were called with an unsolvable problem
Context *c = unsmob_context (context);
int clef_pos = robust_scm2int (c->get_property ("middleCClefPosition"), 0);
int offset = robust_scm2int (c->get_property ("middleCOffset"), 0);
+ /* middleCCuePosition overrides the clef! */
+ SCM cue_pos = c->get_property ("middleCCuePosition");
+ if (scm_is_number (cue_pos))
+ clef_pos = robust_scm2int (cue_pos, 0);
c->set_property (ly_symbol2scm ("middleCPosition"), scm_from_int (clef_pos + offset));
return SCM_UNDEFINED;
\consists "Figured_bass_engraver"
\consists "Figured_bass_position_engraver"
\consists "Script_row_engraver"
+ \consists "Cue_clef_engraver"
localKeySignature = #'()
createSpacing = ##t
automaticBars = ##t
explicitClefVisibility = #all-visible
+ explicitCueClefVisibility = #end-of-line-invisible
explicitKeySignatureVisibility = #all-visible
implicitTimeSignatureVisibility = #end-of-line-invisible
(_i "Set the current clef to @var{type}.")
(make-clef-set type))
+cueClef =
+#(define-music-function (parser location type) (string?)
+ (_i "Set the current cue clef to @var{type}.")
+ (make-cue-clef-set type))
+cueClefUnset =
+#(define-music-function (parser location) ()
+ (_i "Unset the current cue clef.")
+ (make-cue-clef-unset))
+
cueDuring =
#(define-music-function
(parser location what dir main-music) (string? ly:dir? ly:music?)
'quoted-context-type 'Voice
'quoted-context-id "cue"
'quoted-music-name what
- 'quoted-voice-direction dir
- 'origin location))
+ 'quoted-voice-direction dir))
+
+cueDuringWithClef =
+#(define-music-function
+ (parser location what dir clef main-music) (string? ly:dir? string? ly:music?)
+ (_i "Insert contents of quote @var{what} corresponding to @var{main-music},
+in a CueVoice oriented by @var{dir}.")
+ (make-music 'QuoteMusic
+ 'element main-music
+ 'quoted-context-type 'Voice
+ 'quoted-context-id "cue"
+ 'quoted-music-name what
+ 'quoted-music-clef clef
+ 'quoted-voice-direction dir))
a hairpin crescendo is used.")
(crescendoText ,markup? "The text to print at start of non-hairpin
crescendo, i.e., @samp{cresc.}.")
+ (cueClefGlyph ,string? "Name of the symbol within the music font.")
+ (cueClefOctavation ,integer? "Add this much extra octavation.
+Values of 7 and -7 are common.")
+ (cueClefPosition ,number? "Where should the center of the clef
+symbol go, measured in half staff spaces from the center of the
+staff.")
(currentBarNumber ,integer? "Contains the current barnumber.
This property is incremented at every bar line.")
(explicitClefVisibility ,vector? "@samp{break-visibility}
function for clef changes.")
+ (explicitCueClefVisibility ,vector? "@samp{break-visibility}
+function for cue clef changes.")
(explicitKeySignatureVisibility ,vector? "@samp{break-visibility}
function for explicit key changes. @samp{\\override} of the
@code{break-visibility} property will set the visibility for normal
(middleCClefPosition ,number? "The position of the middle C,
as determined only by the clef. This can be calculated by looking at
@code{clefPosition} and @code{clefGlyph}.")
+ (middleCCuePosition ,number? "The position of the middle C,
+as determined only by the clef of the cue notes. This can be calculated by
+looking at @code{cueClefPosition} and @code{cueClefGlyph}.")
(middleCOffset ,number? "The offset of
middle C from the position given by @code{middleCClefPosition} This
is used for ottava brackets.")
(break-visibility . ,begin-of-line-visible)
(non-musical . #t)
(space-alist . (
+ (cue-end-clef . (extra-space . 0.5))
(clef . (extra-space . 0.5))
+ (cue-clef . (extra-space . 0.5))
(key-signature . (extra-space . 0.0))
(staff-bar . (extra-space . 0.0))
(time-signature . (extra-space . 0.0))
(break-align-orders . ;; end of line
#((
left-edge
+ cue-end-clef
ambitus
breathing-sign
clef
+ cue-clef
staff-bar
key-cancellation
key-signature
;; unbroken
(
left-edge
+ cue-end-clef
ambitus
breathing-sign
clef
+ cue-clef
staff-bar
key-cancellation
key-signature
key-signature
staff-bar
time-signature
+ cue-clef
custos)))
(non-musical . #t)
(positioning-done . ,ly:break-alignment-interface::calc-positioning-done)
(time-signature . (minimum-space . 1.5))
(staff-bar . (minimum-space . 1.5))
(clef . (minimum-space . 2.0))
+ (cue-clef . (minimum-space . 2.0))
+ (cue-end-clef . (minimum-space . 2.0))
(first-note . (fixed-space . 1.0)) ;huh?
(right-edge . (extra-space . 0.1))))
(stencil . ,ly:text-interface::print)
(break-visibility . ,begin-of-line-visible)
(glyph-name . ,ly:clef::calc-glyph-name)
(non-musical . #t)
- (space-alist . ((ambitus . (extra-space . 2.0))
+ (space-alist . ((cue-clef . (extra-space . 2.0))
(staff-bar . (extra-space . 0.7))
(key-cancellation . (minimum-space . 3.5))
(key-signature . (minimum-space . 3.5))
text-interface
text-script-interface))))))
+ (CueClef
+ . (
+ (avoid-slur . inside)
+ (break-align-anchor . ,ly:break-aligned-interface::calc-extent-aligned-anchor)
+ (break-align-symbol . cue-clef)
+ (break-visibility . ,begin-of-line-visible)
+ (font-size . -3)
+ (glyph-name . ,ly:clef::calc-glyph-name)
+ (non-musical . #t)
+ (full-size-change . #t)
+ (space-alist . ((staff-bar . (minimum-space . 2.7))
+ (key-cancellation . (minimum-space . 3.5))
+ (key-signature . (minimum-space . 3.5))
+ (time-signature . (minimum-space . 4.2))
+ (custos . (minimum-space . 0.0))
+ (first-note . (minimum-fixed-space . 3.0))
+ (next-note . (extra-space . 0.5))
+ (right-edge . (extra-space . 0.5))))
+ (stencil . ,ly:clef::print)
+ (extra-spacing-height . (-0.5 . 0.5))
+ (Y-offset . ,ly:staff-symbol-referencer::callback)
+ (meta . ((class . Item)
+ (interfaces . (break-aligned-interface
+ clef-interface
+ font-interface
+ staff-symbol-referencer-interface))))))
+
+ (CueEndClef
+ . (
+ (avoid-slur . inside)
+ (break-align-anchor . ,ly:break-aligned-interface::calc-extent-aligned-anchor)
+ (break-align-symbol . cue-end-clef)
+ (break-visibility . ,begin-of-line-invisible)
+ (font-size . -3)
+ (glyph-name . ,ly:clef::calc-glyph-name)
+ (non-musical . #t)
+ (full-size-change . #t)
+ (space-alist . ((clef . (extra-space . 0.7))
+ (cue-clef . (extra-space . 0.7))
+ (staff-bar . (extra-space . 0.7))
+ (key-cancellation . (minimum-space . 3.5))
+ (key-signature . (minimum-space . 3.5))
+ (time-signature . (minimum-space . 4.2))
+ (first-note . (minimum-fixed-space . 5.0))
+ (next-note . (extra-space . 0.5))
+ (right-edge . (extra-space . 0.5))))
+ (stencil . ,ly:clef::print)
+ (extra-spacing-height . (-0.5 . 0.5))
+ (Y-offset . ,ly:staff-symbol-referencer::callback)
+ (meta . ((class . Item)
+ (interfaces . (break-aligned-interface
+ clef-interface
+ font-interface
+ staff-symbol-referencer-interface))))))
+
(Custos
. (
(break-align-symbol . custos)
(time-signature . (extra-space . 1.25))
(staff-bar . (extra-space . 0.6))
(key-signature . (extra-space . 0.5))
+ (cue-clef . (extra-space . 0.5))
(right-edge . (extra-space . 0.5))
(first-note . (fixed-space . 2.5))))
(stencil . ,ly:key-signature-interface::print)
(space-alist . (
(time-signature . (extra-space . 1.15))
(staff-bar . (extra-space . 1.1))
+ (cue-clef . (extra-space . 0.5))
(right-edge . (extra-space . 0.5))
(first-note . (fixed-space . 2.5))))
(stencil . ,ly:key-signature-interface::print)
(break-visibility . ,center-invisible)
(non-musical . #t)
(space-alist . (
- (custos . (extra-space . 0.0))
(ambitus . (extra-space . 2.0))
- (time-signature . (extra-space . 1.0))
- (staff-bar . (extra-space . 0.0))
(breathing-sign . (minimum-space . 0.0))
+ (cue-end-clef . (extra-space . 0.8))
(clef . (extra-space . 0.8))
+ (cue-clef . (extra-space . 0.8))
+ (staff-bar . (extra-space . 0.0))
+ (key-cancellation . (extra-space . 0.0))
+ (key-signature . (extra-space . 0.8))
+ (time-signature . (extra-space . 1.0))
+ (custos . (extra-space . 0.0))
(first-note . (fixed-space . 2.0))
(right-edge . (extra-space . 0.0))
- (key-signature . (extra-space . 0.8))
- (key-cancellation . (extra-space . 0.0))
))
(X-extent . (0 . 0))
(meta . ((class . Item)
(OctavateEight
. (
- (break-visibility . ,begin-of-line-visible)
+ (break-visibility . ,inherit-x-parent-visibility)
(font-shape . italic)
(font-size . -4)
(self-alignment-X . ,CENTER)
(extra-spacing-height . (-1.0 . 1.0))
(non-musical . #t)
(space-alist . (
+ (cue-clef . (extra-space . 1.5))
(first-note . (fixed-space . 2.0))
(right-edge . (extra-space . 0.5))
(staff-bar . (minimum-space . 2.0))))
direct quotes to, e.g., @code{Voice}.")
(quoted-events ,vector? "A vector of with @code{moment} and
@code{event-list} entries.")
+ (quoted-music-clef ,string? "The clef of the voice to quote.")
(quoted-music-name ,string? "The name of the voice to quote.")
(quoted-transposition ,ly:pitch? "The pitch used for the quote,
overriding @code{\\transposition}.")
(if (vector? (ly:music-property quote-music 'quoted-events))
(let* ((dir (ly:music-property quote-music 'quoted-voice-direction))
+ (clef (ly:music-property quote-music 'quoted-music-clef))
(main-voice (if (eq? 1 dir) 1 0))
(cue-voice (if (eq? 1 dir) 0 1))
(main-music (ly:music-property quote-music 'element))
;; to have opposite stems.
(begin
(set! return-value
-
;; cannot context-spec Quote-music, since context
;; for the quotes is determined in the iterator.
(make-sequential-music
(list
+ (if (null? clef)
+ (make-music 'Music)
+ (make-cue-clef-set clef))
(context-spec-music (make-voice-props-set cue-voice) 'CueVoice "cue")
quote-music
- (context-spec-music (make-voice-props-revert) 'CueVoice "cue"))))
+ (context-spec-music (make-voice-props-revert) 'CueVoice "cue")
+ (if (null? clef)
+ (make-music 'Music)
+ (make-cue-clef-unset)))))
(set! main-music
(make-sequential-music
(list
(define-public center-visible #(#f #t #f))
(define-public end-of-line-visible #(#t #f #f))
(define-public all-invisible #(#f #f #f))
+(define-public (inherit-x-parent-visibility grob)
+ (let ((parent (ly:grob-parent grob X)))
+ (ly:grob-property parent 'break-visibility all-invisible)))
+
(define-public spanbar-begin-of-line-invisible #(#t #f #f))
(sort (map car supported-clefs) string<?)))
(make-music 'Music)))))
+(define-public (make-cue-clef-set clef-name)
+ "Generate the clef setting commands for a cue clef with name CLEF-NAME."
+ (define (make-prop-set props)
+ (let ((m (make-music 'PropertySet)))
+ (map (lambda (x) (set! (ly:music-property m (car x)) (cdr x))) props)
+ m))
+ (let ((e '())
+ (c0 0)
+ (oct 0)
+ (match (string-match "^(.*)([_^])([1-9][0-9]*)$" clef-name)))
+ (if match
+ (begin
+ (set! clef-name (match:substring match 1))
+ (set! oct
+ (* (if (equal? (match:substring match 2) "^") -1 1)
+ (- (string->number (match:substring match 3)) 1)))))
+ (set! e (assoc-get clef-name supported-clefs))
+ (if e
+ (let* ((musics (map make-prop-set
+ `(((symbol . cueClefGlyph) (value . ,(car e)))
+ ((symbol . middleCCuePosition)
+ (value . ,(+ oct
+ (cadr e)
+ (assoc-get (car e) c0-pitch-alist))))
+ ((symbol . cueClefPosition) (value . ,(cadr e)))
+ ((symbol . cueClefOctavation) (value . ,(- oct))))))
+ (recalc-mid-C (make-music 'ApplyContext))
+ (seq (make-music 'SequentialMusic
+ 'elements (append musics (list recalc-mid-C))))
+ (csp (make-music 'ContextSpeccedMusic)))
+ (set! (ly:music-property recalc-mid-C 'procedure) ly:set-middle-C!)
+ (context-spec-music seq 'Staff))
+ (begin
+ (ly:warning (_ "unknown clef type `~a'") clef-name)
+ (ly:warning (_ "supported clefs: ~a")
+ (string-join
+ (sort (map car supported-clefs) string<?)))
+ (make-music 'Music)))))
+
+
+(define-public (make-cue-clef-unset)
+ "Reset the clef settings for a cue clef."
+ (define (make-prop-unset props)
+ (let ((m (make-music 'PropertyUnset)))
+ (set! (ly:music-property m (car props)) (cdr props))
+ m))
+ (let* ((musics (map make-prop-unset
+ `((symbol . cueClefGlyph)
+ (symbol . middleCCuePosition)
+ (symbol . cueClefPosition)
+ (symbol . cueClefOctavation))))
+ (recalc-mid-C (make-music 'ApplyContext))
+ (seq (make-music 'SequentialMusic
+ 'elements (append musics (list recalc-mid-C))))
+ (csp (make-music 'ContextSpeccedMusic)))
+ (set! (ly:music-property recalc-mid-C 'procedure) ly:set-middle-C!)
+ (context-spec-music seq 'Staff)))
+
+
;; a function to add new clefs at runtime
(define-public (add-new-clef clef-name clef-glyph clef-position octavation c0-position)
"Append the entries for a clef symbol to supported clefs and c0-pitch-alist"
;; use defaults, but combine all beats into a unit if possible
;;
;; set all beams to end on beats, but 1 8 to beam entire measure
- ;; in order to avoid beaming every beat for entier measure, we set
+ ;; in order to avoid beaming every beam type for the entire measure, we set
;; triplets back to every beat.
((3 . 4) .
- ((beamExceptions . ((end . (((1 . 8) . (6))
- ((1 . 12) . (3 3 3))))))))
+ ((beamExceptions . ((end . (((1 . 8) . (6)) ;1/8 note whole measure
+ ((1 . 12) . (3 3 3)))))))) ;Anything shorter by beat
;; in 3 8 time:
;; beam entire measure together
;; ly/engraver-init.ly where the default time signature is set
;; are set
((4 . 4) .
- ((beamExceptions . ((end . (((1 . 8) . (4 4))
- ((1 . 12) . (3 3 3 3))))))))
+ ((beamExceptions . ((end . (((1 . 8) . (4 4)) ; 1/8 notes half measure
+ ((1 . 12) . (3 3 3 3)))))))) ;Anything shorter by beat
;; in 4/8 time:
;; combine beats 1 and 2, so beam in 2