+2006-10-18 Bertalan Fodor <lilypondtool@organum.hu>
+
+ * scripts/lilypond-book.py: DocBook support.
+
+2006-10-18 Han-Wen Nienhuys <hanwen@lilypond.org>
+
+ * lily/piano-pedal-engraver.cc (struct Pedal_info): remove
+ Y-alignment code.
+ (stop_translation_timestep): set bound to currentMusicalColumn if
+ not set yet. Fixes #102
+
+ * lily/piano-pedal-bracket.cc: formatting.
+
+ * input/test/engraver-one-by-one.ly (MyStaff): reformat.
+
+ * lily/piano-pedal-align-engraver.cc: new class
+ Piano_pedal_align_engraver. Handle side-positioning Y-alignment
+ for piano pedals.
+
2006-10-18 Heikki Junes <hjunes@gmail.com>
* po/fi.po: Update Finnish translation (before the next release).
2006-10-17 Han-Wen Nienhuys <hanwen@lilypond.org>
+ * scm/paper.scm: only use left-margin if defined.
+
* scm/define-grob-interfaces.scm (stroke-finger-interface): typo.
* ly/engraver-init.ly (AncientRemoveEmptyStaffContext): idem.
\version "2.7.39"
\header {
-
-texidoc = "The notation problem, creating a certain symbol,
+
+ texidoc = "The notation problem, creating a certain symbol,
is handled by plugins. Each plugin is called Engraver. In this example,
engravers are switched on one by one, in the following order:
"
- }
+}
\layout { ragged-right = ##t }
\include "engraver-example.ily"
%
MyStaff =\context {
- \type "Engraver_group"
- \name Staff
+ \type "Engraver_group"
+ \name Staff
- \description "Handles clefs, bar lines, keys, accidentals. It can contain
+ \description "Handles clefs, bar lines, keys, accidentals. It can contain
@code{Voice} contexts."
-
- \consists "Output_property_engraver"
-
- \consists "Font_size_engraver"
+
+ \consists "Output_property_engraver"
+
+ \consists "Font_size_engraver"
+
+ \consists "Volta_engraver"
+ \consists "Separating_line_group_engraver"
+ \consists "Dot_column_engraver"
- \consists "Volta_engraver"
- \consists "Separating_line_group_engraver"
- \consists "Dot_column_engraver"
+ \consists "Ottava_spanner_engraver"
+ \consists "Rest_collision_engraver"
+ \consists "Piano_pedal_engraver"
+ \consists "Piano_pedal_align_engraver"
+ \consists "Instrument_name_engraver"
+ \consists "Grob_pq_engraver"
+ \consists "Forbid_line_break_engraver"
+ \consists "Axis_group_engraver"
- \consists "Ottava_spanner_engraver"
- \consists "Rest_collision_engraver"
- \consists "Piano_pedal_engraver"
- \consists "Instrument_name_engraver"
- \consists "Grob_pq_engraver"
- \consists "Forbid_line_break_engraver"
- \consists "Axis_group_engraver"
-\consists "Pitch_squash_engraver"
+ \consists "Pitch_squash_engraver"
- \override VerticalAxisGroup #'minimum-Y-extent = #'(-6 . 6)
- extraVerticalExtent = ##f
- verticalExtent = ##f
- localKeySignature = #'()
+ \override VerticalAxisGroup #'minimum-Y-extent = #'(-6 . 6)
+ extraVerticalExtent = ##f
+ verticalExtent = ##f
+ localKeySignature = #'()
- % explicitly set instrument, so we don't get
- % weird effects when doing instrument names for
- % piano staves
+ % explicitly set instrument, so we don't get
+ % weird effects when doing instrument names for
+ % piano staves
- instrumentName = #'()
- shortInstrumentName = #'()
-
- \accepts "Voice"
+ instrumentName = #'()
+ shortInstrumentName = #'()
+
+ \accepts "Voice"
}
MyVoice = \context {
- \type "Engraver_group"
- \name Voice
+ \type "Engraver_group"
+ \name Voice
-\description "
+ \description "
Corresponds to a voice on a staff. This context handles the
conversion of dynamic signs, stems, beams, super- and subscripts,
slurs, ties, and rests.
You have to instantiate this explicitly if you want to have
multiple voices on the same staff."
- localKeySignature = #'()
- \consists "Font_size_engraver"
-
- % must come before all
- \consists "Output_property_engraver"
- \consists "Arpeggio_engraver"
- \consists "Multi_measure_rest_engraver"
- \consists "Text_spanner_engraver"
- \consists "Grob_pq_engraver"
- \consists "Note_head_line_engraver"
- \consists "Glissando_engraver"
- \consists "Ligature_bracket_engraver"
- \consists "Breathing_sign_engraver"
- % \consists "Rest_engraver"
- \consists "Grace_beam_engraver"
- \consists "New_fingering_engraver"
- \consists "Chord_tremolo_engraver"
- \consists "Percent_repeat_engraver"
- \consists "Slash_repeat_engraver"
- \consists "Melisma_translator"
+ localKeySignature = #'()
+ \consists "Font_size_engraver"
+
+ % must come before all
+ \consists "Output_property_engraver"
+ \consists "Arpeggio_engraver"
+ \consists "Multi_measure_rest_engraver"
+ \consists "Text_spanner_engraver"
+ \consists "Grob_pq_engraver"
+ \consists "Note_head_line_engraver"
+ \consists "Glissando_engraver"
+ \consists "Ligature_bracket_engraver"
+ \consists "Breathing_sign_engraver"
+ % \consists "Rest_engraver"
+ \consists "Grace_beam_engraver"
+ \consists "New_fingering_engraver"
+ \consists "Chord_tremolo_engraver"
+ \consists "Percent_repeat_engraver"
+ \consists "Slash_repeat_engraver"
+ \consists "Melisma_translator"
%{
- Must come before text_engraver, but after note_column engraver.
+ Must come before text_engraver, but after note_column engraver.
%}
- \consists "Text_engraver"
- \consists "Dynamic_engraver"
- \consists "Fingering_engraver"
+ \consists "Text_engraver"
+ \consists "Dynamic_engraver"
+ \consists "Fingering_engraver"
- \consists "Script_column_engraver"
- \consists "Rhythmic_column_engraver"
- \consists "Cluster_spanner_engraver"
- \consists "Tie_engraver"
- \consists "Tie_engraver"
- \consists "Tuplet_engraver"
- \consists "Note_heads_engraver"
- \consists "Rest_engraver"
+ \consists "Script_column_engraver"
+ \consists "Rhythmic_column_engraver"
+ \consists "Cluster_spanner_engraver"
+ \consists "Tie_engraver"
+ \consists "Tie_engraver"
+ \consists "Tuplet_engraver"
+ \consists "Note_heads_engraver"
+ \consists "Rest_engraver"
- \consists "Skip_event_swallow_translator"
+ \consists "Skip_event_swallow_translator"
}
\score {
\topVoice
\layout {
- \context { \MyStaff }
- \context { \MyVoice }
- }
+ \context { \MyStaff }
+ \context { \MyVoice }
+ }
}
MyStaff = \context {
\MyStaff
- \consists "Clef_engraver"
+ \consists "Clef_engraver"
\remove "Pitch_squash_engraver"
}
\score {
\topVoice
\layout {
- \context { \MyStaff }
- \context { \MyVoice }
- }
+ \context { \MyStaff }
+ \context { \MyVoice }
+ }
}
MyVoice = \context {
- \MyVoice
- \consists "Stem_engraver"
- }
+ \MyVoice
+ \consists "Stem_engraver"
+}
\score {
\topVoice
\layout {
- \context { \MyStaff }
- \context { \MyVoice }
- }
+ \context { \MyStaff }
+ \context { \MyVoice }
+ }
}
MyVoice = \context {
- \MyVoice
- \consists "Beam_engraver"
+ \MyVoice
+ \consists "Beam_engraver"
}
\score {
\topVoice
\layout {
- \context { \MyStaff }
- \context { \MyVoice }
- }
+ \context { \MyStaff }
+ \context { \MyVoice }
+ }
}
MyVoice= \context {
- \MyVoice
- \consists "Phrasing_slur_engraver"
- \consists "Slur_engraver"
- \consists "Script_engraver"
+ \MyVoice
+ \consists "Phrasing_slur_engraver"
+ \consists "Slur_engraver"
+ \consists "Script_engraver"
}
\score {
\topVoice
\layout {
- \context { \MyStaff }
- \context { \MyVoice }
- }
+ \context { \MyStaff }
+ \context { \MyVoice }
+ }
}
MyStaff = \context {
- \MyStaff
- \consists "Bar_engraver"
- \consists "Time_signature_engraver"
-
+ \MyStaff
+ \consists "Bar_engraver"
+ \consists "Time_signature_engraver"
}
\score {
\topVoice
\layout {
- \context { \MyStaff }
- \context { \MyVoice }
- }
+ \context { \MyStaff }
+ \context { \MyVoice }
+ }
}
MyStaff = \context {
- \MyStaff
- \consists "Accidental_engraver"
- \consists "Key_engraver"
+ \MyStaff
+ \consists "Accidental_engraver"
+ \consists "Key_engraver"
}
\score {
\topVoice
\layout {
- \context { \MyStaff }
- \context { \MyVoice }
- }
+ \context { \MyStaff }
+ \context { \MyVoice }
+ }
}
--- /dev/null
+/*
+ piano-pedal-align-engraver.cc -- implement Piano_pedal_align_engraver
+
+ source file of the GNU LilyPond music typesetter
+
+ (c) 2006 Han-Wen Nienhuys <hanwen@lilypond.org>
+
+*/
+
+
+#include "engraver.hh"
+
+#include "spanner.hh"
+#include "item.hh"
+#include "side-position-interface.hh"
+#include "stream-event.hh"
+#include "warn.hh"
+#include "axis-group-interface.hh"
+
+
+/*
+ TODO:
+
+
+ * Detach from pedal specifics,
+
+ * Also use this engraver for dynamics.
+
+*/
+
+
+struct Pedal_align_info
+{
+ Spanner *line_spanner_;
+ Grob *carrying_item_;
+ Spanner *carrying_spanner_;
+ Spanner *finished_carrying_spanner_;
+
+ Pedal_align_info ()
+ {
+ clear ();
+
+ }
+ void clear ()
+ {
+ line_spanner_ = 0;
+ carrying_spanner_ = 0;
+ carrying_item_ = 0;
+ finished_carrying_spanner_ = 0;
+ }
+ bool is_finished ()
+ {
+ bool do_continue = carrying_item_;
+
+ do_continue |= (carrying_spanner_ && !finished_carrying_spanner_);
+ do_continue |= (carrying_spanner_ && finished_carrying_spanner_ != carrying_spanner_);
+
+ return !do_continue;
+ }
+};
+
+class Piano_pedal_align_engraver : public Engraver
+{
+public:
+ TRANSLATOR_DECLARATIONS (Piano_pedal_align_engraver);
+
+protected:
+ virtual void finalize ();
+
+ DECLARE_ACKNOWLEDGER (piano_pedal_script);
+ DECLARE_ACKNOWLEDGER (piano_pedal_bracket);
+ DECLARE_ACKNOWLEDGER (note_column);
+
+ DECLARE_END_ACKNOWLEDGER (piano_pedal_bracket);
+
+ void stop_translation_timestep ();
+ void start_translation_timestep ();
+
+private:
+ enum Pedal_type {
+ SOSTENUTO,
+ SUSTAIN,
+ UNA_CORDA,
+ NUM_PEDAL_TYPES
+ };
+ Pedal_align_info pedal_info_[NUM_PEDAL_TYPES];
+ vector<Grob *> supports_;
+
+ Pedal_type get_grob_pedal_type (Grob_info g);
+ Spanner *make_line_spanner (Pedal_type t, SCM);
+};
+
+Piano_pedal_align_engraver::Piano_pedal_align_engraver ()
+{
+}
+
+void
+Piano_pedal_align_engraver::start_translation_timestep ()
+{
+ supports_.clear ();
+}
+
+void
+Piano_pedal_align_engraver::stop_translation_timestep ()
+{
+ for (int i = 0; i < NUM_PEDAL_TYPES; i ++)
+ {
+ if (pedal_info_[i].line_spanner_)
+ {
+
+ if (pedal_info_[i].carrying_item_)
+ {
+ if (!pedal_info_[i].line_spanner_->get_bound (LEFT))
+ pedal_info_[i].line_spanner_->set_bound (LEFT,
+ pedal_info_[i].carrying_item_);
+
+ pedal_info_[i].line_spanner_->set_bound (RIGHT,
+ pedal_info_[i].carrying_item_);
+ }
+ else if (pedal_info_[i].carrying_spanner_
+ || pedal_info_[i].finished_carrying_spanner_
+ )
+ {
+ if (!pedal_info_[i].line_spanner_->get_bound (LEFT)
+ && pedal_info_[i].carrying_spanner_->get_bound (LEFT))
+ pedal_info_[i].line_spanner_->set_bound (LEFT,
+ pedal_info_[i].carrying_spanner_->get_bound (LEFT));
+
+
+ if (pedal_info_[i].finished_carrying_spanner_)
+ pedal_info_[i].line_spanner_->set_bound (RIGHT,
+ pedal_info_[i].finished_carrying_spanner_->get_bound (RIGHT));
+ }
+
+ for (vsize j = 0; j < supports_.size (); j++)
+ {
+ Side_position_interface::add_support (pedal_info_[i].line_spanner_, supports_[j]);
+ }
+
+ if (pedal_info_[i].is_finished ())
+ {
+ announce_end_grob (pedal_info_[i].line_spanner_, SCM_EOL);
+ pedal_info_[i].clear ();
+ }
+ }
+
+ pedal_info_[i].carrying_item_ = 0;
+ }
+}
+
+Piano_pedal_align_engraver::Pedal_type
+Piano_pedal_align_engraver::get_grob_pedal_type (Grob_info g)
+{
+ if (g.event_cause ()->in_event_class ("sostenuto-event"))
+ return SOSTENUTO;
+ if (g.event_cause ()->in_event_class ("sustain-event"))
+ return SUSTAIN;
+ if (g.event_cause ()->in_event_class ("una-corda-event"))
+ return UNA_CORDA;
+
+ programming_error ("Unknown piano pedal type. Defaulting to sustain");
+ return SUSTAIN;
+}
+
+
+Spanner *
+Piano_pedal_align_engraver::make_line_spanner (Pedal_type t, SCM cause)
+{
+ Spanner *sp = pedal_info_[t].line_spanner_;
+ if (!sp)
+ {
+ switch (t)
+ {
+ case (SOSTENUTO):
+ sp = make_spanner ("SostenutoPedalLineSpanner", cause);
+ break;
+ case (SUSTAIN):
+ sp = make_spanner ("SustainPedalLineSpanner", cause);
+ break;
+ case (UNA_CORDA):
+ sp = make_spanner ("UnaCordaPedalLineSpanner", cause);
+ break;
+ default:
+ programming_error ("No pedal type fonud!") ;
+ return sp;
+ }
+
+ pedal_info_[t].line_spanner_ = sp;
+ }
+
+ return sp;
+}
+
+void
+Piano_pedal_align_engraver::acknowledge_note_column (Grob_info gi)
+{
+ supports_.push_back (gi.grob ());
+}
+
+void
+Piano_pedal_align_engraver::acknowledge_piano_pedal_bracket (Grob_info gi)
+{
+ Pedal_type type = get_grob_pedal_type (gi);
+ Grob *sp = make_line_spanner (type, gi.grob ()->self_scm ());
+
+ Axis_group_interface::add_element (sp, gi.grob ());
+ pedal_info_[type].carrying_spanner_ = gi.spanner ();
+}
+
+void
+Piano_pedal_align_engraver::acknowledge_end_piano_pedal_bracket (Grob_info gi)
+{
+ Pedal_type type = get_grob_pedal_type (gi);
+ pedal_info_[type].finished_carrying_spanner_ = gi.spanner ();
+}
+
+void
+Piano_pedal_align_engraver::acknowledge_piano_pedal_script (Grob_info gi)
+{
+ Pedal_type type = get_grob_pedal_type (gi);
+
+ Grob *sp = make_line_spanner (type, gi.grob ()->self_scm ());
+ Axis_group_interface::add_element (sp, gi.grob ());
+ pedal_info_[type].carrying_item_ = gi.grob ();
+}
+
+
+void
+Piano_pedal_align_engraver::finalize ()
+{
+ for (int i = 0; i < NUM_PEDAL_TYPES; i ++)
+ {
+ if (pedal_info_[i].line_spanner_)
+ {
+ SCM cc = get_property ("currentCommandColumn");
+ Item *c = unsmob_item (cc);
+ pedal_info_[i].line_spanner_->set_bound (RIGHT, c);
+
+ pedal_info_[i].clear ();
+ }
+ }
+}
+
+#include "translator.icc"
+
+ADD_ACKNOWLEDGER (Piano_pedal_align_engraver, note_column);
+ADD_ACKNOWLEDGER (Piano_pedal_align_engraver, piano_pedal_bracket);
+ADD_ACKNOWLEDGER (Piano_pedal_align_engraver, piano_pedal_script);
+
+ADD_END_ACKNOWLEDGER (Piano_pedal_align_engraver, piano_pedal_bracket);
+
+
+ADD_TRANSLATOR (Piano_pedal_align_engraver,
+
+ /* doc */
+ "Align piano pedal symbols and brackets.",
+
+ /* create */
+ "SostenutoPedalLineSpanner "
+ "SustainPedalLineSpanner "
+ "UnaCordaPedalLineSpanner ",
+
+ /* read */
+ "currentCommandColumn ",
+
+ /* write */ "");
return m.smobbed_copy ();
}
-ADD_INTERFACE (Piano_pedal_bracket, "piano-pedal-bracket-interface",
- "The bracket of the piano pedal. It can be tuned through the regular "
+ADD_INTERFACE (Piano_pedal_bracket,
+ "piano-pedal-bracket-interface",
+
+ "The bracket of the piano pedal. "
+ "It can be tuned through the regular "
"bracket properties.",
- "bound-padding edge-height shorten-pair bracket-flare pedal-text");
+
+ /* props */
+ "bound-padding "
+ "edge-height "
+ "shorten-pair "
+ "bracket-flare "
+ "pedal-text");
#include "translator.icc"
/*
- Urgh. This engraver is too complex. rewrite. --hwn
+ TODO:
+
+ * Junk hardcoded sustain/sostenuto/una_corda distinction;
+ Softcode using (list (sustain-event SustainPedal PianoPedalBracket) ... )
+
+ * Try to use same engraver for dynamics.
+
*/
/* Ugh: This declaration is duplicated in piano-pedal-performer */
-typedef enum Pedal_type {SOSTENUTO, SUSTAIN, UNA_CORDA, NUM_PEDAL_TYPES};
+typedef enum Pedal_type {
+ SOSTENUTO,
+ SUSTAIN,
+ UNA_CORDA,
+ NUM_PEDAL_TYPES
+};
/*
Static precalculated data (symbols and strings) for the different
SCM style_sym_;
SCM strings_sym_;
- const char *pedal_line_spanner_c_str_;
const char *pedal_c_str_;
Pedal_type_info ()
event_class_sym_ = SCM_EOL;
style_sym_ = SCM_EOL;
strings_sym_ = SCM_EOL;
- pedal_line_spanner_c_str_ = 0;
pedal_c_str_ = 0;
}
void protect ()
Item *item_;
Spanner *bracket_; // A single portion of a pedal bracket
Spanner *finished_bracket_;
-
- /*
- This grob contains all the pedals of the same type on the same staff
- */
- Spanner *line_spanner_;
- Spanner *finished_line_spanner_;
};
static Pedal_type_info pedal_types_[NUM_PEDAL_TYPES];
{
public:
TRANSLATOR_DECLARATIONS (Piano_pedal_engraver);
- ~Piano_pedal_engraver ();
+
protected:
virtual void initialize ();
virtual void finalize ();
DECLARE_TRANSLATOR_LISTENER (sustain);
DECLARE_TRANSLATOR_LISTENER (una_corda);
DECLARE_TRANSLATOR_LISTENER (sostenuto);
- void stop_translation_timestep ();
DECLARE_ACKNOWLEDGER (note_column);
+ void stop_translation_timestep ();
void process_music ();
private:
Pedal_info info_list_[NUM_PEDAL_TYPES + 1];
- /*
- Record a stack of the current pedal spanners, so if more than one pedal
- occurs simultaneously then extra space can be added between them.
- */
-
- vector<Spanner*> previous_;
- void del_linespanner (Spanner *);
-
void create_text_grobs (Pedal_info *p, bool);
void create_bracket_grobs (Pedal_info *p, bool);
void typeset_all (Pedal_info *p);
};
+
static void
init_pedal_types ()
{
info.style_sym_ = scm_str2symbol (("pedal" + base_name + "Style").c_str ());
info.strings_sym_ = scm_str2symbol (("pedal" + base_name + "Strings").c_str ());
- info.pedal_line_spanner_c_str_ = strdup ((base_name + "PedalLineSpanner").c_str ());
info.base_name_ = name;
info.pedal_c_str_ = strdup ((base_name + "Pedal").c_str ());
pedal_types_[i] = info;
}
}
+
ADD_SCM_INIT_FUNC (Piano_pedal_engraver_init_pedal_types_, init_pedal_types);
Piano_pedal_engraver::Piano_pedal_engraver ()
info->item_ = 0;
info->bracket_ = 0;
info->finished_bracket_ = 0;
- info->line_spanner_ = 0;
- info->finished_line_spanner_ = 0;
info->current_bracket_ev_ = 0;
info->event_drul_[START] = 0;
info->event_drul_[STOP] = 0;
info_list_[NUM_PEDAL_TYPES].type_ = 0;
}
-Piano_pedal_engraver::~Piano_pedal_engraver ()
-{
-}
/*
Urg: Code dup
{
for (Pedal_info *p = info_list_; p->type_; p++)
{
- if (p->line_spanner_)
- {
- Side_position_interface::add_support (p->line_spanner_, info.grob ());
- add_bound_item (p->line_spanner_, info.grob ());
- }
if (p->bracket_)
add_bound_item (p->bracket_, info.grob ());
if (p->finished_bracket_)
{
if (p->event_drul_[STOP] || p->event_drul_[START])
{
- if (!p->line_spanner_)
- {
- const char *name = p->type_->pedal_line_spanner_c_str_;
- Stream_event *rq = (p->event_drul_[START] ? p->event_drul_[START] : p->event_drul_[STOP]);
- p->line_spanner_ = make_spanner (name, rq->self_scm ());
- }
-
/* Choose the appropriate grobs to add to the line spanner
These can be text items or text-spanners
*/
{
p->start_ev_ = p->event_drul_[START];
s = scm_car (strings);
- if (!mixed)
- {
- /*
- Code dup?! see below.
- */
- if (previous_.size ())
- // add extra space below the previous already-occuring pedal
- Side_position_interface::add_support (p->line_spanner_,
- previous_.back ());
- previous_.push_back (p->line_spanner_);
- }
- }
+ }
if (scm_is_string (s))
{
: p->event_drul_[STOP])->self_scm ());
p->item_->set_property ("text", s);
- Axis_group_interface::add_element (p->line_spanner_, p->item_);
}
if (!mixed)
if (!p->event_drul_[START])
{
SCM flare = p->bracket_->get_property ("bracket-flare");
- p->bracket_->set_property ("bracket-flare", scm_cons (scm_car (flare),
- scm_from_double (0)));
+ if (scm_is_pair (flare))
+ p->bracket_->set_property ("bracket-flare", scm_cons (scm_car (flare),
+ scm_from_double (0)));
}
p->finished_bracket_ = p->bracket_;
p->bracket_ = 0;
+
+ announce_end_grob (p->finished_bracket_, p->event_drul_[STOP]->self_scm ());
+
p->current_bracket_ev_ = 0;
}
if (p->item_)
p->bracket_->set_object ("pedal-text", p->item_->self_scm ());
}
-
- /*
- We do not use currentMusicalColumn for the left span-point.
- If the column as accidentals (eg on a different stave), the
- currentMusicalColumn is too wide, making the bracket too big.
-
- TODO:
-
- Hmm. What do we do when there are no notes when the spanner starts?
-
- TODO:
-
- what about the right span point?
-
- */
- Axis_group_interface::add_element (p->line_spanner_, p->bracket_);
-
- if (!p->event_drul_[STOP])
- {
-
- /*
- code dup. --hwn.
-
- // position new pedal spanner below the current one
- */
- if (previous_.size ())
- Side_position_interface::add_support (p->line_spanner_, previous_.back ());
-
- previous_.push_back (p->line_spanner_);
- }
}
p->event_drul_[START] = 0;
{
for (Pedal_info *p = info_list_; p->type_; p++)
{
- /*
- suicide?
- */
- if (p->line_spanner_
- && !p->line_spanner_->is_live ())
- p->line_spanner_ = 0;
-
if (p->bracket_
&& !p->bracket_->is_live ())
p->bracket_ = 0;
{
SCM cc = get_property ("currentCommandColumn");
Item *c = unsmob_item (cc);
- if (p->line_spanner_)
- p->line_spanner_->set_bound (RIGHT, c);
p->bracket_->set_bound (RIGHT, c);
p->finished_bracket_ = p->bracket_;
p->bracket_ = 0;
- p->finished_line_spanner_ = p->line_spanner_;
- p->line_spanner_ = 0;
typeset_all (p);
}
- if (p->line_spanner_)
- {
- p->finished_line_spanner_ = p->line_spanner_;
- typeset_all (p);
- }
}
}
-void
-Piano_pedal_engraver::del_linespanner (Spanner *g)
-{
- vsize idx = find (previous_, g) - previous_.begin ();
- if (idx != VPOS && idx < previous_.size ())
- previous_.erase (previous_.begin () + idx);
-}
-
void
Piano_pedal_engraver::stop_translation_timestep ()
{
for (Pedal_info *p = info_list_; p->type_; p++)
{
- if (!p->bracket_)
+
+ typeset_all (p);
+ if (p->bracket_ && !p->bracket_->get_bound (LEFT))
{
- p->finished_line_spanner_ = p->line_spanner_;
- p->line_spanner_ = 0;
- del_linespanner (p->finished_line_spanner_);
- }
+ Grob *cmc = unsmob_grob (get_property ("currentMusicalColumn"));
- typeset_all (p);
+ if (!p->bracket_->get_bound (LEFT))
+ p->bracket_->set_bound (LEFT, cmc);
+ }
}
for (Pedal_info *p = info_list_; p->type_; p++)
/*
Handle suicide.
*/
- if (p->finished_line_spanner_
- && !p->finished_line_spanner_->is_live ())
- p->finished_line_spanner_ = 0;
if (p->finished_bracket_
&& !p->finished_bracket_->is_live ())
p->finished_bracket_ = 0;
p->finished_bracket_ = 0;
}
-
- if (p->finished_line_spanner_)
- {
- Grob *l = p->finished_line_spanner_->get_bound (LEFT);
- Grob *r = p->finished_line_spanner_->get_bound (RIGHT);
- if (!r && l)
- p->finished_line_spanner_->set_bound (RIGHT, l);
- else if (!l && r)
- p->finished_line_spanner_->set_bound (LEFT, r);
- else if (!r && !l)
- {
- Grob *cc = unsmob_grob (get_property ("currentMusicalColumn"));
- Item *ci = dynamic_cast<Item *> (cc);
- p->finished_line_spanner_->set_bound (RIGHT, ci);
- p->finished_line_spanner_->set_bound (LEFT, ci);
- }
-
- p->finished_line_spanner_ = 0;
- }
}
ADD_ACKNOWLEDGER (Piano_pedal_engraver, note_column);
"Engrave piano pedal symbols and brackets.",
/* create */
+ "PianoPedalBracket "
"SostenutoPedal "
- "SostenutoPedalLineSpanner "
"SustainPedal "
- "SustainPedalLineSpanner "
- "UnaCordaPedal "
- "UnaCordaPedalLineSpanner ",
+ "UnaCordaPedal ",
/* read */
"currentCommandColumn "
"pedalSustainStyle "
"pedalUnaCordaStrings "
"pedalUnaCordaStyle",
+
/* write */ "");
\consists "Rest_collision_engraver"
\consists "Accidental_engraver"
\consists "Piano_pedal_engraver"
+ \consists "Piano_pedal_align_engraver"
\consists "Instrument_name_engraver"
\consists "String_number_engraver"
\consists "Axis_group_engraver"
head-separation = 4 \mm
foot-separation = 4 \mm
- left-margin = 10 \mm
- right-margin = 10 \mm
-
first-page-number = #1
print-first-page-number =##f
}
(meta . ((class . Item)
(interfaces . (text-interface
self-alignment-interface
+ piano-pedal-script-interface
font-interface))))))
(SostenutoPedalLineSpanner
line-spanner-interface
text-interface
self-alignment-interface
+ piano-pedal-script-interface
font-interface))))))
(SustainPedalLineSpanner
(X-offset . ,ly:self-alignment-interface::x-aligned-on-self)
(meta . ((class . Item)
(interfaces . (text-interface
+ piano-pedal-script-interface
self-alignment-interface
font-interface))))))
(let*
((paper-height (ly:output-def-lookup layout 'paper-height))
(paper-width (ly:output-def-lookup layout 'paper-width))
-
- (lmargin (ly:output-def-lookup layout 'left-margin))
+ (lmargin (ly:output-def-lookup layout 'left-margin #f))
(left-margin (if lmargin
lmargin
(/ (- paper-width
(module-define! m 'paper-width w)
(module-define! m 'paper-height h)
(module-define! m 'line-width (- w
- (ly:modules-lookup (list m) 'left-margin)
- (ly:modules-lookup (list m) 'right-margin)))
+ (ly:modules-lookup (list m) 'left-margin (* 10 mm))
+ (ly:modules-lookup (list m) 'right-margin (* 10 mm))))
(module-define! m 'indent (/ w 14))
backend = 'ps'
help_summary = _ (
-'''Process LilyPond snippets in hybrid HTML, LaTeX, or texinfo document.
+'''Process LilyPond snippets in hybrid HTML, LaTeX, texinfo or DocBook document.
Example usage:
help=_ ("pipe snippets through FILTER [convert-ly -n -]"),
default=None)
p.add_option ('-f', '--format',
- help=_('''use output format FORMAT (texi [default], texi-html, latex, html)'''),
+ help=_('''use output format FORMAT (texi [default], texi-html, latex, html, docbook)'''),
action='store')
p.add_option ("-I", '--include', help=_('add DIR to include path'),
#
AFTER = 'after'
BEFORE = 'before'
+DOCBOOK = 'docbook'
EXAMPLEINDENT = 'exampleindent'
FILTER = 'filter'
FRAGMENT = 'fragment'
# (?x) -- Ignore whitespace in patterns.
no_match = 'a\ba'
snippet_res = {
+ ##
+ DOCBOOK: {
+ 'include':
+ no_match,
+
+ 'lilypond':
+ r'''(?smx)
+ (?P<match>
+ <(?P<inline>(inline)?)mediaobject>\s*<textobject.*?>\s*<programlisting\s+language="lilypond".*?(role="(?P<options>.*?)")?>(?P<code>.*?)</programlisting\s*>\s*</textobject\s*>\s*</(inline)?mediaobject>)''',
+
+ 'lilypond_block':
+ r'''(?smx)
+ (?P<match>
+ <(?P<inline>(inline)?)mediaobject>\s*<textobject.*?>\s*<programlisting\s+language="lilypond".*?(role="(?P<options>.*?)")?>(?P<code>.*?)</programlisting\s*>\s*</textobject\s*>\s*</(inline)?mediaobject>)''',
+
+ 'lilypond_file':
+ r'''(?smx)
+ (?P<match>
+ <(?P<inline>(inline)?)mediaobject>\s*<imageobject.*?>\s*<imagedata\s+fileref="(?P<filename>.*?\.ly)"\s*(role="(?P<options>.*?)")?\s*(/>|>\s*</imagedata>)\s*</imageobject>\s*</(inline)?mediaobject>)''',
+
+ 'multiline_comment':
+ r'''(?smx)
+ (?P<match>
+ \s*(?!@c\s+)
+ (?P<code><!--\s.*?!-->)
+ \s)''',
+
+ 'singleline_comment':
+ no_match,
+
+ 'verb':
+ no_match,
+
+ 'verbatim':
+ no_match,
+
+ },
##
HTML: {
'include':
format_res = {
+ DOCBOOK: {
+ 'intertext': r',?\s*intertext=\".*?\"',
+ 'option_sep': '\s*',
+ },
HTML: {
'intertext': r',?\s*intertext=\".*?\"',
'option_sep': '\s*',
}
output = {
+ ##
+ DOCBOOK: {
+ FILTER: r'''<mediaobject><textobject><programlisting language="lilypond" role="%(options)s">%(code)s</programlisting></textobject></mediaobject>''',
+
+ OUTPUT: r'''
+ <imageobject role="latex">
+ <imagedata fileref="%(base)s.pdf" format="PDF"/>
+ </imageobject>
+ <imageobject role="html">
+ <imagedata fileref="%(base)s.png" format="PNG"/></imageobject>''',
+
+ VERBATIM: r'''<programlisting>%(verb)s</programlisting>''',
+
+ PRINTFILENAME: '<textobject><simpara><ulink url="%(base)s.ly"><filename>%(filename)s</filename></ulink></simpara></textobject>'
+ },
##
HTML: {
FILTER: r'''<lilypond %(options)s>
images = tuple (images)
return images
+ def output_docbook (self):
+ str = ''
+ base = self.basename ()
+ for image in self.get_images ():
+ (base, ext) = os.path.splitext (image)
+ str += output[DOCBOOK][OUTPUT] % vars ()
+ str += self.output_print_filename (DOCBOOK)
+ if (self.substring('inline') == 'inline'):
+ str = '<inlinemediaobject>' + str + '</inlinemediaobject>'
+ else:
+ str = '<mediaobject>' + str + '</mediaobject>'
+ if VERBATIM in self.option_dict:
+ verb = verbatim_html (self.substring ('code'))
+ str = output[DOCBOOK][VERBATIM] % vars () + str
+ return str
+
def output_html (self):
str = ''
base = self.basename ()
if global_options.format in (HTML, TEXINFO):
cmd += ' --formats=png '
-
+ if global_options.format in (DOCBOOK):
+ cmd += ' --formats=png,pdf '
# UGH
# the --process=CMD switch is a bad idea
# it is too generic for lilypond-book.
'.texi': TEXINFO,
'.texinfo': TEXINFO,
'.xml': HTML,
+ '.lyxml': DOCBOOK
}
format2ext = {
# TEXINFO: '.texinfo',
TEXINFO: '.texi',
LATEX: '.tex',
+ DOCBOOK: '.xml'
}
class Compile_error:
global_options.format = guess_format (files[0])
formats = 'ps'
- if global_options.format in (TEXINFO, HTML):
+ if global_options.format in (TEXINFO, HTML, DOCBOOK):
formats += ',png'