2 cluster-engraver.cc -- implement Cluster_engraver
4 (c) 2002 Juergen Reuter <reuter@ipd.uka.de>
10 #include "note-head.hh"
13 class Cluster_engraver : public Engraver
17 TRANSLATOR_DECLARATIONS(Cluster_engraver);
18 virtual void start_translation_timestep ();
19 virtual bool try_music (Music *);
20 virtual void process_music ();
21 virtual void acknowledge_grob (Grob_info);
22 virtual void stop_translation_timestep ();
25 Drul_array<Music*> reqs_drul_;
26 Pitch pitch_min, pitch_max;
31 void reset_min_max (Pitch *pitch_min, Pitch *pitch_max)
34 * (pitch_min > pitch_max) means that pitches are not yet
37 *pitch_min = Pitch (0, 0, +1);
38 *pitch_max = Pitch (0, 0, -1);
41 Cluster_engraver::Cluster_engraver ()
44 columns_scm = SCM_EOL;
45 reqs_drul_[LEFT] = reqs_drul_[RIGHT] = 0;
49 Cluster_engraver::try_music (Music *m)
51 if (m->is_mus_type ("abort-event"))
53 reqs_drul_[START] = 0;
59 columns_scm = SCM_EOL;
62 else if (m->is_mus_type ("cluster-event"))
64 Direction d = to_dir (m->get_mus_property ("span-direction"));
72 Cluster_engraver::process_music ()
78 reqs_drul_[STOP]->origin ()->warning ("can't find start of cluster");
82 Grob *bound = unsmob_grob (get_property ("currentMusicalColumn"));
83 cluster->set_bound (RIGHT, bound);
84 cluster->set_grob_property ("segments", columns_scm);
85 typeset_grob (cluster);
87 columns_scm = SCM_EOL;
91 if (reqs_drul_[START])
95 reqs_drul_[START]->origin ()->warning ("may not nest clusters");
99 SCM basicProperties = get_property ("Cluster");
100 cluster = new Spanner (basicProperties);
101 columns_scm = SCM_EOL;
102 Grob *bound = unsmob_grob (get_property ("currentMusicalColumn"));
103 cluster->set_bound (LEFT, bound);
104 announce_grob (cluster, bound->self_scm ());
106 reqs_drul_[START] = 0;
111 Cluster_engraver::start_translation_timestep ()
113 reset_min_max (&pitch_min, &pitch_max);
117 Cluster_engraver::stop_translation_timestep ()
121 SCM column_scm = get_property ("currentMusicalColumn");
122 if (column_scm == SCM_EOL)
124 programming_error("failed retrieving current column");
128 if (Pitch::compare (pitch_min, pitch_max) <= 0)
130 int staff_position = pitch_min.steps ();
131 SCM c0 = get_property ("centralCPosition");
132 if (gh_number_p (c0))
133 staff_position += gh_scm2int (c0);
134 SCM segment = scm_list_n (column_scm,
135 gh_int2scm (staff_position),
136 pitch_min.smobbed_copy (),
137 pitch_max.smobbed_copy (),
139 segment = scm_list_n (segment, SCM_UNDEFINED);
140 columns_scm = (columns_scm != SCM_EOL) ?
141 gh_append2 (columns_scm, segment) : segment;
145 /* This timestep is caused by a different voice of the same
146 staff and hence should be ignored. */
152 Cluster_engraver::acknowledge_grob (Grob_info info)
154 Item *item = dynamic_cast <Item *>(info.grob_);
157 if (Note_head::has_interface (info.grob_))
159 Music *nr = info.music_cause ();
160 if (nr && nr->is_mus_type ("note-event"))
162 Pitch pitch = *unsmob_pitch (nr->get_mus_property ("pitch"));
163 if (Pitch::compare (pitch_min, pitch_max) > 0) // already init'd?
165 // not yet init'd; use current pitch to init min/max
169 else if (Pitch::compare (pitch, pitch_max) > 0) // new max?
173 else if (Pitch::compare (pitch, pitch_min) < 0) // new min?
182 ENTER_DESCRIPTION(Cluster_engraver,
183 /* descr */ "engraves a cluster",
184 /* creats*/ "Cluster",
185 /* accepts */ "cluster-event",
186 /* acks */ "note-head-interface",