]> git.donarmstrong.com Git - lilypond.git/blob - lily/new-chord-name-engraver.cc
* lily/new-chord-name-engraver.cc (process_music): give original
[lilypond.git] / lily / new-chord-name-engraver.cc
1 /*
2   chord-name-engraver.cc -- implement New_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 New_chord_name_engraver : public Engraver 
24 {
25   TRANSLATOR_DECLARATIONS( New_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
41
42 New_chord_name_engraver::New_chord_name_engraver ()
43 {
44   chord_name_ = 0;
45   last_chord_ = SCM_EOL;
46 }
47
48 void
49 New_chord_name_engraver::add_note (Music * n)
50 {
51   notes_.push (n);
52 }
53
54 void
55 New_chord_name_engraver::process_music ()
56 {
57   if (!notes_.size() )
58     return;
59   
60   SCM bass = SCM_EOL;
61   SCM inversion = SCM_EOL;
62   SCM pitches = SCM_EOL;
63
64   Music* inversion_event = 0;
65   for (int i =0 ; i < notes_.size (); i++)
66     {
67       Music *n = notes_[i];
68       SCM p = n->get_mus_property ("pitch");;
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 op = inversion_event->get_mus_property ("original-pitch");
83       if (unsmob_pitch (op))
84         pitches= gh_cons (op, pitches);
85       else
86         programming_error ("Inversion does not have original pitch.");
87     }
88
89   pitches = scm_sort_list (pitches, Pitch::less_p_proc);
90
91   SCM name_proc = get_property ("chordNameFunction");
92   SCM markup = scm_call_4 (name_proc, pitches, bass, inversion,
93                            daddy_trans_->self_scm());
94
95   /*
96     Ugh. 
97    */
98   SCM chord_as_scm = gh_cons (pitches, gh_cons (bass, inversion));
99   
100   chord_name_ = new Item (get_property ("ChordName"));
101   chord_name_->set_grob_property("text", markup);
102   announce_grob(chord_name_, SCM_EOL);
103   SCM s = get_property ("chordChanges");
104   if (to_boolean (s) && gh_pair_p (last_chord_) 
105       && gh_equal_p (chord_as_scm, last_chord_))
106     chord_name_->set_grob_property ("begin-of-line-visible", SCM_BOOL_T);
107
108   last_chord_ = chord_as_scm;
109 }
110
111 bool
112 New_chord_name_engraver::try_music (Music* m)
113 {
114   /*
115     hmm. Should check? 
116    */
117   if (m->is_mus_type ("note-event"))
118     {
119       add_note (m);
120       return true;
121     }
122   return false;
123 }
124
125 void
126 New_chord_name_engraver::stop_translation_timestep ()
127 {
128   if (chord_name_)
129     {
130       typeset_grob (chord_name_);
131     }
132   chord_name_ = 0;
133   notes_.clear ();
134 }
135
136 ENTER_DESCRIPTION(New_chord_name_engraver,
137 /* descr */       "Catch note-events "
138 "and generate the appropriate chordname.",
139 /* creats*/       "ChordName",
140 /* accepts */     "note-event",
141 /* acks  */      "",
142 /* reads */       "chordChanges chordNameExceptions chordNameFunction",
143 /* write */       "");