summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Solomon <mike@apollinemike.com>2011-04-28 09:10:27 -0400
committerCarl Sorensen <c_sorensen@byu.edu>2011-05-25 11:54:34 -0600
commitd623a43831b22eb89f75b9b8517a7f38d02cb7d4 (patch)
tree68644e75d5cc5da7d91da3b499337b26b629550e
parentf6aa099ed44aa739bce92d5a5af7543a62ff06ec (diff)
Allows for individual glissandi between members of NoteColumns.
The property glissandoMap is used to tell the glissando-engraver what note-column members to connect via glissandi.
-rw-r--r--input/regression/glissando-chord.ly23
-rw-r--r--lily/glissando-engraver.cc98
-rw-r--r--scm/define-context-properties.scm5
-rw-r--r--scm/define-grob-interfaces.scm2
-rw-r--r--scm/define-grob-properties.scm2
5 files changed, 105 insertions, 25 deletions
diff --git a/input/regression/glissando-chord.ly b/input/regression/glissando-chord.ly
new file mode 100644
index 0000000000..e140c38d8e
--- /dev/null
+++ b/input/regression/glissando-chord.ly
@@ -0,0 +1,23 @@
+\version "2.15.0"
+
+\header {
+ texidoc = "LilyPond typesets glissandi between chords."
+}
+
+\relative c' {
+ c1 \glissando g'
+ c,1 \glissando s1 g'
+ <c, e>1 \glissando <g' b>
+ <c, e>1 \glissando s1 <g' b>
+ \set glissandoMap = #'((0 . 1) (1 . 0))
+ <c, g'>1 \glissando s1 <d a'>
+ \set glissandoMap = #'((0 . 0) (0 . 1) (0 . 2))
+ c1 \glissando s1 <d f a>
+ \set glissandoMap = #'((2 . 0) (1 . 0) (0 . 0))
+ <d f a>1 \glissando s1 c
+ \unset glissandoMap
+ \once \override Voice . Glissando #'style =
+ #(lambda (grob)
+ (if (eq? 1 (ly:grob-property grob 'glissando-index)) 'zigzag 'default))
+ <d f a>1 \glissando s1 <f a c>
+}
diff --git a/lily/glissando-engraver.cc b/lily/glissando-engraver.cc
index 99eb6bc515..08f420c128 100644
--- a/lily/glissando-engraver.cc
+++ b/lily/glissando-engraver.cc
@@ -20,6 +20,7 @@
#include "engraver.hh"
#include "international.hh"
+#include "pointer-group-interface.hh"
#include "rhythmic-head.hh"
#include "spanner.hh"
#include "stream-event.hh"
@@ -35,21 +36,29 @@ public:
protected:
DECLARE_TRANSLATOR_LISTENER (glissando);
- DECLARE_ACKNOWLEDGER (rhythmic_head);
+ DECLARE_ACKNOWLEDGER (note_column);
virtual void finalize ();
void stop_translation_timestep ();
void process_music ();
+
private:
- Spanner *line_;
- Spanner *last_line_;
+ vector<Spanner *> lines_;
+ bool start_glissandi;
+ bool stop_glissandi;
+
Stream_event *event_;
+ SCM map;
+ vector<vsize> note_column_1;
+ vector<vsize> note_column_2;
};
Glissando_engraver::Glissando_engraver ()
{
- last_line_ = line_ = 0;
event_ = 0;
+ map = SCM_EOL;
+ start_glissandi = false;
+ stop_glissandi = false;
}
IMPLEMENT_TRANSLATOR_LISTENER (Glissando_engraver, glissando);
@@ -63,44 +72,85 @@ void
Glissando_engraver::process_music ()
{
if (event_)
- line_ = make_spanner ("Glissando", event_->self_scm ());
+ start_glissandi = true;
}
void
-Glissando_engraver::acknowledge_rhythmic_head (Grob_info info)
+Glissando_engraver::acknowledge_note_column (Grob_info info)
{
Grob *g = info.grob ();
- if (line_)
- line_->set_bound (LEFT, g);
+ if (start_glissandi)
+ {
+ extract_grob_set (g, "note-heads", note_heads);
+ map = get_property ("glissandoMap");
+ if (map == SCM_EOL)
+ for (vsize i = 0; i < note_heads.size (); i++)
+ {
+ note_column_1.push_back (i);
+ note_column_2.push_back (i);
+ }
+ else
+ for (SCM m = map; scm_is_pair (m); m = scm_cdr (m))
+ {
+ SCM candidate = scm_car (m);
+ if (!scm_is_pair (candidate))
+ continue;
+ int n1 = robust_scm2int (scm_car (candidate), -1);
+ int n2 = robust_scm2int (scm_cdr (candidate), -1);
+ if (n1 < 0 || n2 < 0 || n1 >= note_heads.size ())
+ continue;
+ note_column_1.push_back (vsize (n1));
+ note_column_2.push_back (vsize (n2));
+ }
+ for (vsize i=0; i < note_column_1.size (); i++)
+ {
+ lines_.push_back (make_spanner ("Glissando", event_->self_scm ()));
+ lines_.back ()->set_bound (LEFT, note_heads[note_column_1[i]]);
+ }
+ }
- if (last_line_)
+ if (stop_glissandi)
{
- last_line_->set_bound (RIGHT, g);
- announce_end_grob (last_line_, g->self_scm ());
+ extract_grob_set (g, "note-heads", note_heads);
+ int glissando_index = 0;
+ for (vsize i=0; i < note_column_1.size (); i++)
+ {
+ if (note_column_2[i] >= note_heads.size ())
+ lines_[i]->suicide ();
+ else
+ {
+ lines_[i]->set_bound (RIGHT, note_heads[note_column_2[i]]);
+ lines_[i]->set_property ("glissando-index", scm_from_int (glissando_index));
+ glissando_index++;
+ announce_end_grob (lines_[i], note_heads[note_column_2[i]]->self_scm ());
+ }
+ }
+ lines_.clear ();
+ note_column_1.clear ();
+ note_column_2.clear ();
+ stop_glissandi = false;
}
}
void
Glissando_engraver::stop_translation_timestep ()
{
- if (last_line_ && last_line_->get_bound (RIGHT))
- {
- last_line_ = 0;
- }
- if (line_)
+
+ if (start_glissandi)
{
- if (last_line_)
+ if (stop_glissandi)
programming_error ("overwriting glissando");
- last_line_ = line_;
+ stop_glissandi = true;
}
- line_ = 0;
+
+ start_glissandi = false;
event_ = 0;
}
void
Glissando_engraver::finalize ()
{
- if (line_)
+ if (!lines_.empty ())
{
string msg = _ ("unterminated glissando");
@@ -109,12 +159,12 @@ Glissando_engraver::finalize ()
else
warning (msg);
- line_->suicide ();
- line_ = 0;
+ for (vsize i=0; i < lines_.size (); i++)
+ lines_[i]->suicide ();
}
}
-ADD_ACKNOWLEDGER (Glissando_engraver, rhythmic_head);
+ADD_ACKNOWLEDGER (Glissando_engraver, note_column);
ADD_TRANSLATOR (Glissando_engraver,
/* doc */
"Engrave glissandi.",
@@ -123,7 +173,7 @@ ADD_TRANSLATOR (Glissando_engraver,
"Glissando ",
/* read */
- "",
+ "glissandoMap ",
/* write */
""
diff --git a/scm/define-context-properties.scm b/scm/define-context-properties.scm
index a813f1421f..e9484ba194 100644
--- a/scm/define-context-properties.scm
+++ b/scm/define-context-properties.scm
@@ -257,6 +257,11 @@ containing, in the correct order, the labels to be used for lettered
frets in tablature.")
+ (glissandoMap ,list? "A map in the form of '((source1 . target1)
+(source2 . target2) (sourcen . targetn)) showing the glissandi to
+be drawn for note columns. The value '() will default to '((0 . 0)
+(1 . 1) (n . n)), where n is the minimal number of note-heads in
+the two note columns between which the glissandi occur.")
(gridInterval ,ly:moment? "Interval for which to generate
@code{GridPoint}s.")
diff --git a/scm/define-grob-interfaces.scm b/scm/define-grob-interfaces.scm
index edc02a7fb3..a7090de032 100644
--- a/scm/define-grob-interfaces.scm
+++ b/scm/define-grob-interfaces.scm
@@ -100,7 +100,7 @@ note)."
(ly:add-interface
'glissando-interface
"A glissando."
- '())
+ '(glissando-index))
(ly:add-interface
'grace-spacing-interface
diff --git a/scm/define-grob-properties.scm b/scm/define-grob-properties.scm
index 3381cb9e27..7fd0b13819 100644
--- a/scm/define-grob-properties.scm
+++ b/scm/define-grob-properties.scm
@@ -1003,6 +1003,8 @@ in addition to notes and stems.")
(figures ,ly:grob-array? "Figured bass objects for continuation line.")
+ (glissando-index ,integer? "The index of a glissando in its note
+column.")
(grace-spacing ,ly:grob? "A run of grace notes.")
(heads ,ly:grob-array? "An array of note heads.")