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