]> git.donarmstrong.com Git - lilypond.git/blob - lily/chord-name-engraver.cc
* lily/text-item.cc (interpret_string): new file, select font with
[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 "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 "context.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   virtual void finalize ();
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 void
40 Chord_name_engraver::finalize ()
41 {
42   last_chord_ = SCM_EOL; 
43 }
44
45 Chord_name_engraver::Chord_name_engraver ()
46 {
47   chord_name_ = 0;
48   last_chord_ = SCM_EOL;
49 }
50
51 void
52 Chord_name_engraver::add_note (Music * n)
53 {
54   notes_.push (n);
55 }
56
57 void
58 Chord_name_engraver::process_music ()
59 {
60   if (!notes_.size () )
61     return;
62   
63   SCM bass = SCM_EOL;
64   SCM inversion = SCM_EOL;
65   SCM pitches = SCM_EOL;
66
67   Music* inversion_event = 0;
68   for (int i =0 ; i < notes_.size (); i++)
69     {
70       Music *n = notes_[i];
71       SCM p = n->get_property ("pitch");
72       if (!unsmob_pitch (p))
73         continue;
74       
75       if (n->get_property ("inversion") == SCM_BOOL_T)
76         {
77           inversion_event = n;
78           inversion = p;
79         }
80       else if (n->get_property ("bass") == SCM_BOOL_T)
81         bass = p;
82       else
83         pitches = scm_cons (p, pitches);
84     }
85
86   if (inversion_event)
87     {
88       SCM oct = inversion_event->get_property ("octavation");
89       if (is_number (oct))
90         {
91           Pitch *p = unsmob_pitch (inversion_event->get_property ("pitch"));
92           int octavation =  ly_scm2int (oct);
93           Pitch orig = p->transposed (Pitch (-octavation, 0,0));
94           
95           pitches= scm_cons (orig.smobbed_copy (), pitches);
96         }
97       else
98         programming_error ("Inversion does not have original pitch.");
99     }
100
101   pitches = scm_sort_list (pitches, Pitch::less_p_proc);
102
103   SCM name_proc = get_property ("chordNameFunction");
104   SCM markup = scm_call_4 (name_proc, pitches, bass, inversion,
105                            daddy_context_->self_scm ());
106
107   /*
108     Ugh. 
109    */
110   SCM chord_as_scm = scm_cons (pitches, scm_cons (bass, inversion));
111   
112   chord_name_ = make_item ("ChordName");
113   chord_name_->set_property ("text", markup);
114   announce_grob (chord_name_, notes_[0]->self_scm ());
115   SCM s = get_property ("chordChanges");
116   if (to_boolean (s) && is_pair (last_chord_) 
117       && is_equal (chord_as_scm, last_chord_))
118     chord_name_->set_property ("begin-of-line-visible", SCM_BOOL_T);
119
120   last_chord_ = chord_as_scm;
121 }
122
123 bool
124 Chord_name_engraver::try_music (Music* m)
125 {
126   /*
127     hmm. Should check? 
128    */
129   if (m->is_mus_type ("note-event"))
130     {
131       add_note (m);
132       return true;
133     }
134   return false;
135 }
136
137 void
138 Chord_name_engraver::stop_translation_timestep ()
139 {
140   if (chord_name_)
141     {
142       typeset_grob (chord_name_);
143     }
144   chord_name_ = 0;
145   notes_.clear ();
146 }
147
148 /*
149   The READs description is not strictly accurate:
150   which properties are read depend on the chord naming function active.
151 */
152 ENTER_DESCRIPTION (Chord_name_engraver,
153 /* descr */       "Catch note-events "
154 "and generate the appropriate chordname.",
155 /* creats*/       "ChordName",
156 /* accepts */     "note-event",
157 /* acks  */      "",
158 /* reads */       "chordChanges chordNameExceptions chordNameFunction "
159 "chordNoteNamer chordRootNamer chordNameExceptions majorSevenSymbol",
160 /* write */       "");