]> git.donarmstrong.com Git - lilypond.git/blob - lily/tuplet-engraver.cc
* lily/include/lily-guile.hh: rename ly_c_X_p -> ly_is_X
[lilypond.git] / lily / tuplet-engraver.cc
1 /*
2   tuplet-engraver.cc -- implement Tuplet_engraver
3
4   source file of the GNU LilyPond music typesetter
5
6   (c) 1998--2005 Han-Wen Nienhuys <hanwen@cs.uu.nl>
7 */
8
9 #include "tuplet-bracket.hh"
10 #include "note-column.hh"
11 #include "beam.hh"
12 #include "engraver.hh"
13 #include "spanner.hh"
14
15 struct Tuplet_description
16 {
17   Music *music_;
18   Rational stop_;
19   Rational span_stop_;
20   Spanner *spanner_;
21   Tuplet_description ()
22   {
23     music_ = 0;
24     spanner_ = 0;
25   }
26 };
27
28 class Tuplet_engraver : public Engraver
29 {
30 public:
31   TRANSLATOR_DECLARATIONS (Tuplet_engraver);
32
33 protected:
34   Array<Tuplet_description> tuplets_;
35
36   virtual void acknowledge_grob (Grob_info);
37   virtual bool try_music (Music *r);
38   virtual void start_translation_timestep ();
39   virtual void process_music ();
40 };
41
42 bool
43 Tuplet_engraver::try_music (Music *music)
44 {
45   if (music->is_mus_type ("time-scaled-music"))
46     {
47       Music *el = unsmob_music (music->get_property ("element"));
48       if (el && !el->is_mus_type ("event-chord"))
49         {
50           Tuplet_description d;
51           d.music_ = music;
52           d.stop_ = now_mom ().main_part_ + music->get_length ().main_part_;
53           d.span_stop_ = d.stop_;
54
55           SCM s = get_property ("tupletSpannerDuration");
56           if (unsmob_moment (s))
57             d.span_stop_ = min (d.span_stop_, (now_mom () + *unsmob_moment (s)).main_part_);
58
59           tuplets_.push (d);
60         }
61       return true;
62     }
63   return false;
64 }
65
66 void
67 Tuplet_engraver::process_music ()
68 {
69   for (int i = 0; i < tuplets_.size (); i++)
70     {
71       if (tuplets_[i].spanner_)
72         continue;
73
74       Spanner *spanner = make_spanner ("TupletBracket",
75                                        tuplets_[i].music_->self_scm ());
76       tuplets_[i].spanner_ = spanner;
77
78       SCM proc = get_property ("tupletNumberFormatFunction");
79       if (ly_is_procedure (proc))
80         {
81           SCM t = scm_apply_0 (proc, scm_list_1 (tuplets_[i].music_->self_scm ()));
82           spanner->set_property ("text", t);
83         }
84     }
85 }
86
87 void
88 Tuplet_engraver::acknowledge_grob (Grob_info i)
89 {
90   if (Note_column::has_interface (i.grob ()))
91     {
92       for (int j = 0; j < tuplets_.size (); j++)
93         if (tuplets_[j].spanner_)
94           Tuplet_bracket::add_column (tuplets_[j].spanner_,
95                                       dynamic_cast<Item *> (i.grob ()));
96     }
97 }
98
99 void
100 Tuplet_engraver::start_translation_timestep ()
101 {
102   Moment now = now_mom ();
103
104   Moment tsd;
105   SCM s = get_property ("tupletSpannerDuration");
106   if (unsmob_moment (s))
107     tsd = unsmob_moment (s)->main_part_;
108
109   for (int i = tuplets_.size (); i--;)
110     {
111       if (now.main_part_ >= tuplets_[i].span_stop_)
112         {
113           if (Spanner *sp = tuplets_[i].spanner_)
114             {
115               if (!sp->get_bound (RIGHT))
116                 sp->set_bound (RIGHT, sp->get_bound (LEFT));
117
118               tuplets_[i].spanner_ = 0;
119             }
120
121           if (tsd.to_bool ())
122             tuplets_[i].span_stop_ += tsd.main_part_;
123         }
124
125       if (now.main_part_ >= tuplets_[i].stop_)
126         {
127           tuplets_.del (i);
128         }
129     }
130 }
131
132 Tuplet_engraver::Tuplet_engraver ()
133 {
134 }
135
136 ADD_TRANSLATOR (Tuplet_engraver,
137                 /* descr */ "Catch Time_scaled_music and generate appropriate bracket  ",
138                 /* creats*/ "TupletBracket",
139                 /* accepts */ "time-scaled-music",
140                 /* acks  */ "note-column-interface",
141                 /* reads */ "tupletNumberFormatFunction tupletSpannerDuration",
142                 /* write */ "");