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