]> git.donarmstrong.com Git - lilypond.git/blob - lily/chord-name-engraver.cc
bdca1d10b13f732ab0951f2b5cc5e8c5851f027f
[lilypond.git] / lily / chord-name-engraver.cc
1 /*
2   chord-name-engraver.cc -- implement Chord_name_engraver
3
4   source file of the GNU LilyPond music typesetter
5
6   (c) 1998--2003 Jan Nieuwenhuizen <janneke@gnu.org>
7 */
8
9 #include "engraver.hh"
10 #include "chord-name.hh"
11 #include "event.hh"
12 #include "paper-def.hh"
13 #include "font-interface.hh"
14 #include "paper-def.hh"
15 #include "dimensions.hh"
16 #include "item.hh"
17 #include "pitch.hh"
18 #include "protected-scm.hh"
19 #include "translator-group.hh"
20 #include "warn.hh"
21
22 class Chord_name_engraver : public Engraver 
23 {
24   TRANSLATOR_DECLARATIONS( Chord_name_engraver);
25 protected:
26   virtual void stop_translation_timestep ();
27   virtual void process_music ();
28   virtual bool try_music (Music *);
29
30 private:
31   void add_note (Music *);
32   
33   Item* chord_name_;
34   Link_array<Music> notes_;
35   
36   Protected_scm last_chord_;
37 };
38
39 Chord_name_engraver::Chord_name_engraver ()
40 {
41   chord_name_ = 0;
42   last_chord_ = SCM_EOL;
43 }
44
45 void
46 Chord_name_engraver::add_note (Music * n)
47 {
48   notes_.push (n);
49 }
50
51 void
52 Chord_name_engraver::process_music ()
53 {
54   if (!notes_.size() )
55     return;
56   
57   SCM bass = SCM_EOL;
58   SCM inversion = SCM_EOL;
59   SCM pitches = SCM_EOL;
60
61   Music* inversion_event = 0;
62   for (int i =0 ; i < notes_.size (); i++)
63     {
64       Music *n = notes_[i];
65       SCM p = n->get_mus_property ("pitch");
66       if (!unsmob_pitch (p))
67         continue;
68       
69       if (n->get_mus_property ("inversion") == SCM_BOOL_T)
70         {
71           inversion_event = n;
72           inversion = p;
73         }
74       else if (n->get_mus_property ("bass") == SCM_BOOL_T)
75         bass = p;
76       else
77         pitches = gh_cons (p, pitches);
78     }
79
80   if (inversion_event)
81     {
82       SCM oct = inversion_event->get_mus_property ("octavation");
83       if (gh_number_p (oct))
84         {
85           Pitch *p = unsmob_pitch (inversion_event->get_mus_property ("pitch"));
86           int octavation =  gh_scm2int (oct);
87           Pitch orig = p->transposed (Pitch (-octavation, 0,0));
88           
89           pitches= gh_cons (orig.smobbed_copy (), pitches);
90         }
91       else
92         programming_error ("Inversion does not have original pitch.");
93     }
94
95   pitches = scm_sort_list (pitches, Pitch::less_p_proc);
96
97   SCM name_proc = get_property ("chordNameFunction");
98   SCM markup = scm_call_4 (name_proc, pitches, bass, inversion,
99                            daddy_trans_->self_scm());
100
101   /*
102     Ugh. 
103    */
104   SCM chord_as_scm = gh_cons (pitches, gh_cons (bass, inversion));
105   
106   chord_name_ = make_item ("ChordName");
107   chord_name_->set_grob_property("text", markup);
108   announce_grob(chord_name_, notes_[0]->self_scm ());
109   SCM s = get_property ("chordChanges");
110   if (to_boolean (s) && gh_pair_p (last_chord_) 
111       && gh_equal_p (chord_as_scm, last_chord_))
112     chord_name_->set_grob_property ("begin-of-line-visible", SCM_BOOL_T);
113
114   last_chord_ = chord_as_scm;
115 }
116
117 bool
118 Chord_name_engraver::try_music (Music* m)
119 {
120   /*
121     hmm. Should check? 
122    */
123   if (m->is_mus_type ("note-event"))
124     {
125       add_note (m);
126       return true;
127     }
128   return false;
129 }
130
131 void
132 Chord_name_engraver::stop_translation_timestep ()
133 {
134   if (chord_name_)
135     {
136       typeset_grob (chord_name_);
137     }
138   chord_name_ = 0;
139   notes_.clear ();
140 }
141
142 /*
143   The READs description is not strictly accurate:
144   which properties are read depend on the chord naming function active.
145 */
146 ENTER_DESCRIPTION(Chord_name_engraver,
147 /* descr */       "Catch note-events "
148 "and generate the appropriate chordname.",
149 /* creats*/       "ChordName",
150 /* accepts */     "note-event",
151 /* acks  */      "",
152 /* reads */       "chordChanges chordNameExceptions chordNameFunction "
153 "chordNoteNamer chordRootNamer chordNameExceptions majorSevenSymbol",
154 /* write */       "");