]> git.donarmstrong.com Git - lilypond.git/blob - midi2ly/lilypond-voice.cc
patch::: 1.5.18.moh1: [PATCH] 1.4 Lyric alignment
[lilypond.git] / midi2ly / lilypond-voice.cc
1 //
2 // lilypond-voice.cc -- implement Lilypond_voice
3 //
4 // (c) 1997--2001 Jan Nieuwenhuizen <janneke@gnu.org>
5
6 #include "string-convert.hh"
7 #include "midi2ly-global.hh"
8 #include "lilypond-column.hh"
9 #include "lilypond-item.hh"
10 #include "lilypond-staff.hh"
11 #include "lilypond-stream.hh"
12 #include "lilypond-voice.hh"
13 #include "lilypond-score.hh"
14
15 extern Lilypond_score* lilypond_score_l_g;
16
17 Lilypond_voice::Lilypond_voice (Lilypond_staff* lilypond_staff_l)
18 {
19   lilypond_staff_l_ = lilypond_staff_l;
20   threads_.push (new Cons_list<Lilypond_item>);
21   mom_ = 0;
22 }
23   
24 void
25 Lilypond_voice::add_items (Link_array<Lilypond_item>& items)
26 {
27   int thread = 0;
28   for (int i = 0; i < items.size (); i++)
29     {
30       Lilypond_item* item = items[i];
31
32       int to_thread;
33       if (Lilypond_note* n = dynamic_cast<Lilypond_note*> (item))
34         to_thread = thread++;
35       else
36         to_thread = 0;
37       
38       if (to_thread >= threads_.size ())
39         threads_.push (new Cons_list<Lilypond_item>);
40       
41       if (to_thread == 0 && item->at_mom () > mom_)
42         {
43           /* urg: skip should use refer to end-colum, not separate moment */
44           Rational r = item->at_mom () - mom_;
45           Lilypond_column* start = lilypond_score_l_g->find_column_l (mom_);
46           threads_[to_thread]->append (new Cons<Lilypond_item> (new Lilypond_skip (start, r), 0));
47           mom_ = item->at_mom ();
48         }
49
50       threads_[to_thread]->append (new Cons<Lilypond_item> (item, 0));
51       if (to_thread == 0)
52         mom_ += item->duration_mom ();
53     }
54 }
55
56 /**
57    analyse pitches to determine clef.
58  */
59 String
60 Lilypond_voice::get_clef () const
61 {
62   Lilypond_note * n =0;
63
64   for (Cons<Lilypond_item> *cp = threads_[0]->head_; !n && cp; cp = cp->next_)
65     {
66       n = dynamic_cast<Lilypond_note*> (cp->car_);
67     }
68   
69   if (!n)
70     return "";
71
72   int p = n->pitch_i_;
73
74   if (p < 56)
75     return "\\clef \"bass\"\n";
76   else if (p > 67)
77     return "\\clef \"treble\"\n";
78   else
79     return "";
80 }
81
82 static int const FAIRLY_LONG_VOICE_i = 6;
83
84 void
85 Lilypond_voice::output (Lilypond_stream& lilypond_stream_r)
86 {
87   lilypond_stream_r << "{ ";
88   if (threads_[0]->size_i () > FAIRLY_LONG_VOICE_i)
89     lilypond_stream_r << '\n';
90
91
92   lilypond_stream_r << get_clef () << '\n';
93   
94   int current_bar_i = 0;
95   Rational bar_mom = lilypond_staff_l_->lilypond_time_signature_l_->bar_mom ();
96
97   Link_array <Cons<Lilypond_item> > heads;
98   for (int i = 1; i < threads_.size (); i++)
99     heads.push (threads_[i]->head_);
100   for (Cons<Lilypond_item>* i = threads_[0]->head_; i; i = i->next_)
101     {
102       Rational at_mom = i->car_->lilypond_column_l_->at_mom ();
103       int bar_i = (int) (at_mom / bar_mom) + 1;
104       if (bar_i > current_bar_i) 
105         {
106           if (current_bar_i) 
107             {
108               if (at_mom == Rational (bar_i - 1) * bar_mom)
109                 lilypond_stream_r << "|";
110               lilypond_stream_r << "\n% ";
111               lilypond_stream_r << String_convert::i2dec_str (bar_i, 0, ' ');
112               lilypond_stream_r << '\n';
113             }
114           LOGOUT (NORMAL_ver) << "[" << bar_i << "]" << flush; 
115           current_bar_i = bar_i;
116         }
117
118       if (dynamic_cast<Lilypond_note*> (i->car_)
119           && heads.size ()
120           && heads[0]
121           && heads[0]->car_->at_mom () == at_mom)
122         {
123           lilypond_stream_r << '<';
124       
125           lilypond_stream_r << *i->car_;
126
127           for (int h = 0;
128                h < heads.size ()
129                  && heads[h]
130                  && heads[h]->car_->at_mom () == at_mom;
131                h++)
132             {
133               lilypond_stream_r << *heads[h]->car_;
134               heads[h] = heads[h]->next_;
135             }
136           lilypond_stream_r << '>';
137         }
138       else
139         lilypond_stream_r << *i->car_;
140       
141       if (Lilypond_key* k = dynamic_cast<Lilypond_key*> (i->car_))
142         lilypond_staff_l_->lilypond_key_l_ = lilypond_score_l_g->lilypond_key_l_ = k;
143     }
144
145   if (threads_[0]->size_i () > FAIRLY_LONG_VOICE_i)
146     lilypond_stream_r << '\n';
147
148   lilypond_stream_r << "} ";
149 }
150
151