]> git.donarmstrong.com Git - lilypond.git/blob - lily/tab-note-heads-engraver.cc
* lily/tab-note-heads-engraver.cc: listen to string number events
[lilypond.git] / lily / tab-note-heads-engraver.cc
1 /*
2   head-grav.cc -- part of GNU LilyPond
3
4   (c)  1997--2003 Han-Wen Nienhuys <hanwen@cs.uu.nl>
5 */
6 #include <ctype.h>
7 #include <stdio.h>
8
9 #include "rhythmic-head.hh"
10 #include "paper-def.hh"
11 #include "event.hh"
12 #include "dots.hh"
13 #include "dot-column.hh"
14 #include "staff-symbol-referencer.hh"
15 #include "item.hh"
16 #include "score-engraver.hh"
17 #include "warn.hh"
18
19 /**
20    make (guitar-like) tablature note
21 */
22 class Tab_note_heads_engraver : public Engraver
23 {
24   Link_array<Item> notes_;
25   
26   Link_array<Item> dots_;
27   Link_array<Music> note_events_;
28   Link_array<Music> tabstring_events_;
29 public:
30   TRANSLATOR_DECLARATIONS(Tab_note_heads_engraver);
31
32 protected:
33   virtual void start_translation_timestep ();
34   virtual bool try_music (Music *event) ;
35   virtual void process_music ();
36
37   virtual void stop_translation_timestep ();
38 };
39
40
41 Tab_note_heads_engraver::Tab_note_heads_engraver()
42 {
43 }
44
45 bool
46 Tab_note_heads_engraver::try_music (Music *m) 
47 {
48   if (m->is_mus_type ("note-event"))
49     {
50       note_events_.push (m);
51       return true;
52     }
53   else if (m->is_mus_type ("string-number-event"))
54     {
55       tabstring_events_.push (m);
56       return true;
57     }
58   else if (m->is_mus_type ("busy-playing-event"))
59     {
60       return note_events_.size ();
61     }
62   
63   return false;
64 }
65
66
67 void
68 Tab_note_heads_engraver::process_music ()
69 {
70   int j = 0; 
71   for (int i=0; i < note_events_.size (); i++)
72     {
73
74
75       
76       SCM stringTunings = get_property ("stringTunings");
77       int number_of_strings = ((int) gh_length(stringTunings));
78       bool high_string_one = to_boolean(get_property ("highStringOne"));
79
80       Item * note  = new Item (get_property ("TabNoteHead"));
81       
82       Music * event = note_events_[i];
83
84       
85       Music * tabstring_event=0;
86
87       for (SCM s =event->get_mus_property ("articulations");
88            !tabstring_event && gh_pair_p (s); s = gh_cdr (s))
89         {
90           Music * art = unsmob_music (gh_car (s));
91
92           if (art->is_mus_type ("string-number-event"))
93             tabstring_event = art;
94         }
95
96       if (!tabstring_event  && j < tabstring_events_.size ())
97         {
98           tabstring_event = tabstring_events_[j];
99           if (j +1 <  tabstring_events_.size())
100             j++;
101         }
102
103       int tab_string;
104       bool string_found;
105       if (tabstring_event)
106         {
107           tab_string = gh_scm2int(tabstring_event->get_mus_property ("string-number"));
108           string_found = true;
109         }
110       else
111         {
112           tab_string = high_string_one ? 1 : number_of_strings;
113           string_found = false;
114         }
115       
116       Duration dur = *unsmob_duration (event->get_mus_property ("duration"));
117       note->set_grob_property ("duration-log",
118                                gh_int2scm (dur.duration_log ()));
119
120       if (dur.dot_count ())
121         {
122           Item * d = new Item (get_property ("Dots"));
123           Rhythmic_head::set_dots (note, d);
124           
125           if (dur.dot_count ()
126               != gh_scm2int (d->get_grob_property ("dot-count")))
127             d->set_grob_property ("dot-count", gh_int2scm (dur.dot_count ()));
128
129           d->set_parent (note, Y_AXIS);
130           announce_grob (d, SCM_EOL);
131           dots_.push (d);
132         }
133       
134       
135       SCM scm_pitch = event->get_mus_property ("pitch");
136       SCM proc      = get_property ("tablatureFormat");
137       SCM min_fret_scm = get_property ("minimumFret");
138       int min_fret = gh_number_p(min_fret_scm) ? gh_scm2int(min_fret_scm) : 0;
139
140       while(!string_found)
141         {
142           int fret = unsmob_pitch(scm_pitch)->semitone_pitch()
143             - gh_scm2int(gh_list_ref(stringTunings,gh_int2scm(tab_string-1)));
144           if(fret<min_fret)
145             tab_string += high_string_one ? 1 : -1;
146           else
147             string_found = true;
148         }
149
150       SCM text = gh_call3 (proc, gh_int2scm (tab_string), stringTunings, scm_pitch);
151
152       int pos = 2 * tab_string - number_of_strings - 1; // No tab-note between the string !!!
153       if(to_boolean(get_property("stringOneTopmost")))
154         pos = -pos;
155       
156       note->set_grob_property ("text", text);      
157       
158       note->set_grob_property ("staff-position", gh_int2scm (pos));
159       announce_grob (note, event->self_scm());
160       notes_.push (note);
161     }
162 }
163
164 void
165 Tab_note_heads_engraver::stop_translation_timestep ()
166 {
167   for (int i=0; i < notes_.size (); i++)
168     {
169       typeset_grob (notes_[i]);
170     }
171
172   notes_.clear ();
173   for (int i=0; i < dots_.size (); i++)
174     {
175       typeset_grob (dots_[i]);
176     }
177   
178   dots_.clear ();
179   note_events_.clear ();
180   tabstring_events_.clear ();
181 }
182
183 void
184 Tab_note_heads_engraver::start_translation_timestep ()
185 {
186 }
187
188
189 ENTER_DESCRIPTION(Tab_note_heads_engraver,
190 /* descr */       "Generate one or more tablature noteheads from Music of type NoteEvent.",
191 /* creats*/       "TabNoteHead Dots",
192 /* accepts */     "note-event string-number-event busy-playing-event",
193 /* acks  */      "",
194 /* reads */       "centralCPosition stringTunings minimumFret tablatureFormat highStringOne stringOneTopmost",
195 /* write */       "");
196