~ubuntu-branches/ubuntu/precise/lilypond/precise

« back to all changes in this revision

Viewing changes to lily/beam-engraver.cc

  • Committer: Bazaar Package Importer
  • Author(s): Thomas Bushnell, BSG
  • Date: 2006-12-19 10:18:12 UTC
  • mfrom: (3.1.4 feisty)
  • Revision ID: james.westby@ubuntu.com-20061219101812-7awtjkp0i393wxty
Tags: 2.8.7-3
scripts/midi2ly.py: When setting DATADIR, find Lilypond python files
in the @TOPLEVEL_VERSION@ directory, not 'current'.  Patch thanks to
Chris Lamb (chris@chris-lamb.co.uk).  (Closes: #400550)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*   
2
 
  beam-engraver.cc --  implement Beam_engraver
3
 
  
 
1
/*
 
2
  beam-engraver.cc -- implement Beam_engraver
 
3
 
4
4
  source file of the GNU LilyPond music typesetter
5
 
  
6
 
  (c) 1998--2004 Han-Wen Nienhuys <hanwen@cs.uu.nl>
7
 
  
8
 
 */
9
 
 
10
 
#include "engraver.hh"
11
 
#include "event.hh"
 
5
 
 
6
  (c) 1998--2006 Han-Wen Nienhuys <hanwen@xs4all.nl>
 
7
*/
 
8
 
12
9
#include "beam.hh"
13
 
#include "stem.hh"
14
 
#include "warn.hh"
15
10
#include "beaming.hh"
16
 
#include "score-engraver.hh"
17
 
#include "rest.hh"
 
11
#include "context.hh"
18
12
#include "drul-array.hh"
 
13
#include "duration.hh"
 
14
#include "engraver.hh"
 
15
#include "international.hh"
19
16
#include "item.hh"
 
17
#include "rest.hh"
 
18
#include "score-engraver.hh"
20
19
#include "spanner.hh"
21
 
#include "context.hh"
 
20
#include "stem.hh"
 
21
#include "warn.hh"
 
22
 
 
23
#include "translator.icc"
22
24
 
23
25
class Beam_engraver : public Engraver
24
26
{
25
 
protected:  
26
 
  Music * start_ev_;
27
 
  
 
27
public:
 
28
  DECLARE_ACKNOWLEDGER (stem);
 
29
  DECLARE_ACKNOWLEDGER (rest);
 
30
protected:
 
31
  Music *start_ev_;
 
32
 
28
33
  Spanner *finished_beam_;
29
34
  Spanner *beam_;
30
 
  Music * prev_start_ev_;
31
 
 
32
 
  Music * now_stop_ev_;
33
 
  
34
 
  Beaming_info_list * beam_info_;
35
 
  Beaming_info_list * finished_beam_info_;  
 
35
  Music *prev_start_ev_;
 
36
 
 
37
  Music *now_stop_ev_;
 
38
 
 
39
  Beaming_info_list *beam_info_;
 
40
  Beaming_info_list *finished_beam_info_;
36
41
 
37
42
  /// location  within measure where beam started.
38
43
  Moment beam_start_location_;
47
52
  void set_melisma (bool);
48
53
 
49
54
  Moment last_stem_added_at_;
50
 
  virtual void stop_translation_timestep ();
51
 
  virtual void start_translation_timestep ();
 
55
  void stop_translation_timestep ();
 
56
  void start_translation_timestep ();
52
57
  virtual void finalize ();
53
58
 
54
 
  virtual void acknowledge_grob (Grob_info);
55
 
  virtual bool try_music (Music*);
56
 
  virtual void process_music ();
 
59
  virtual bool try_music (Music *);
 
60
  void process_music ();
57
61
 
58
62
  virtual bool valid_start_point ();
59
63
  virtual bool valid_end_point ();
60
 
  
 
64
 
61
65
public:
62
66
  TRANSLATOR_DECLARATIONS (Beam_engraver);
63
67
};
64
68
 
65
 
 
66
69
/*
67
70
  Hmm. this isn't necessary, since grace beams and normal beams are
68
71
  always nested.
69
 
 */
 
72
*/
70
73
bool
71
74
Beam_engraver::valid_start_point ()
72
75
{
84
87
Beam_engraver::Beam_engraver ()
85
88
{
86
89
  beam_ = 0;
87
 
  finished_beam_ =0;
88
 
  finished_beam_info_=0;
89
 
  beam_info_ =0;
 
90
  finished_beam_ = 0;
 
91
  finished_beam_info_ = 0;
 
92
  beam_info_ = 0;
90
93
  now_stop_ev_ = 0;
91
94
  start_ev_ = 0;
92
 
  prev_start_ev_ =0;
 
95
  prev_start_ev_ = 0;
93
96
}
94
97
 
95
98
bool
104
107
        return false;
105
108
 
106
109
      if (d == START)
107
 
        {
108
 
          start_ev_ = m;
109
 
        }
110
 
      else if (d==STOP)
111
 
        {
112
 
          now_stop_ev_ = m;
113
 
        }
 
110
        start_ev_ = m;
 
111
      else if (d == STOP)
 
112
        now_stop_ev_ = m;
114
113
      return true;
115
114
    }
116
115
  return false;
121
120
{
122
121
  SCM b = get_property ("autoBeaming");
123
122
  if (!to_boolean (b))
124
 
    daddy_context_->set_property ("beamMelismaBusy", ml ? SCM_BOOL_T :SCM_BOOL_F);
 
123
    context ()->set_property ("beamMelismaBusy", ml ? SCM_BOOL_T : SCM_BOOL_F);
125
124
}
126
125
 
127
126
void
128
127
Beam_engraver::process_music ()
129
128
{
130
129
  if (beam_ && !to_boolean (get_property ("allowBeamBreak")))
131
 
    {
132
 
      get_score_engraver ()->forbid_breaks ();
133
 
    }
 
130
    get_score_engraver ()->forbid_breaks ();
134
131
 
135
132
  if (start_ev_)
136
133
    {
142
139
 
143
140
      set_melisma (true);
144
141
      prev_start_ev_ = start_ev_;
145
 
      beam_ = make_spanner ("Beam");
146
 
      SCM smp = get_property ("measurePosition");
147
 
      Moment mp = (unsmob_moment (smp)) ? *unsmob_moment (smp) : Moment (0);
 
142
      beam_ = make_spanner ("Beam", start_ev_->self_scm ());
 
143
      Moment mp (robust_scm2moment (get_property ("measurePosition"), Moment (0)));
148
144
 
149
145
      beam_start_location_ = mp;
150
146
      beam_start_mom_ = now_mom ();
151
 
      
 
147
 
152
148
      beam_info_ = new Beaming_info_list;
153
 
      
 
149
 
154
150
      /* urg, must copy to Auto_beam_engraver too */
155
 
      announce_grob (beam_, start_ev_->self_scm ());
156
151
    }
157
 
 
158
152
}
159
153
 
160
 
 
161
154
void
162
155
Beam_engraver::typeset_beam ()
163
156
{
165
158
    {
166
159
      finished_beam_info_->beamify (beat_length_, subdivide_beams_);
167
160
      Beam::set_beaming (finished_beam_, finished_beam_info_);
168
 
      typeset_grob (finished_beam_);
 
161
 
169
162
      delete finished_beam_info_;
170
 
      finished_beam_info_ =0;
 
163
      finished_beam_info_ = 0;
171
164
      finished_beam_ = 0;
172
165
    }
173
166
}
176
169
Beam_engraver::start_translation_timestep ()
177
170
{
178
171
  start_ev_ = 0;
179
 
  
 
172
 
180
173
  if (beam_)
181
174
    {
182
175
      set_melisma (true);
183
 
      
 
176
 
184
177
      subdivide_beams_ = to_boolean (get_property ("subdivideBeams"));
185
 
      beat_length_ = *unsmob_moment (get_property ("beatLength"));
 
178
      beat_length_ = robust_scm2moment (get_property ("beatLength"), Moment (1, 4));
186
179
    }
187
180
}
188
181
 
190
183
Beam_engraver::stop_translation_timestep ()
191
184
{
192
185
  typeset_beam ();
193
 
  if (now_stop_ev_ )
 
186
  if (now_stop_ev_)
194
187
    {
195
188
      finished_beam_ = beam_;
196
189
      finished_beam_info_ = beam_info_;
220
213
}
221
214
 
222
215
void
223
 
Beam_engraver::acknowledge_grob (Grob_info info)
 
216
Beam_engraver::acknowledge_rest (Grob_info info)
224
217
{
225
218
  if (beam_)
226
219
    {
227
 
      if (Rest::has_interface (info.grob_))
228
 
        {
229
 
          info.grob_->add_offset_callback (Beam::rest_collision_callback_proc, Y_AXIS);
230
 
        }
231
 
      else if (Stem::has_interface (info.grob_))
232
 
        {
233
 
          Moment now = now_mom ();
234
 
 
235
 
          if (!valid_start_point ())
236
 
            return ;
237
 
          
238
 
          Item *stem = dynamic_cast<Item*> (info.grob_);
239
 
          if (Stem::get_beam (stem))
240
 
            return;
241
 
 
242
 
          Music* m = info.music_cause ();
243
 
          if (!m->is_mus_type ("rhythmic-event"))
244
 
            {
245
 
              String s = _ ("stem must have Rhythmic structure");
246
 
              if (info.music_cause ())
247
 
                info.music_cause ()->origin ()->warning (s);
248
 
              else
249
 
                ::warning (s);
250
 
          
251
 
              return;
252
 
            }
253
 
 
254
 
 
255
 
          last_stem_added_at_ = now;
256
 
          int durlog  = unsmob_duration (m->get_property ("duration"))-> duration_log ();
257
 
          if (durlog <= 2)
258
 
            {
259
 
              m->origin ()->warning (_ ("stem doesn't fit in beam"));
260
 
              prev_start_ev_->origin ()->warning (_ ("beam was started here"));
261
 
              /*
262
 
                don't return, since
263
 
 
264
 
                [r4 c8] can just as well be modern notation.
265
 
              */
266
 
            }
267
 
 
268
 
          stem->set_property ("duration-log",
269
 
                                    scm_int2num (durlog));
270
 
          Moment stem_location = now - beam_start_mom_ + beam_start_location_;
271
 
          beam_info_->add_stem (stem_location,
272
 
 (durlog- 2) >? 0);
273
 
          Beam::add_stem (beam_, stem);
274
 
        }
275
 
    }
276
 
}
277
 
 
278
 
 
279
 
 
280
 
 
281
 
 
282
 
ENTER_DESCRIPTION (Beam_engraver,
283
 
/* descr */       "Handles Beam events by engraving Beams.    If omitted, then notes will be "
284
 
"printed with flags instead of beams.",
285
 
/* creats*/       "Beam",
286
 
/* accepts */     "beam-event",
287
 
/* acks  */      "stem-interface rest-interface",
288
 
/* reads */       "beamMelismaBusy beatLength subdivideBeams",
289
 
/* write */       "");
290
 
 
 
220
      chain_offset_callback (info.grob(),
 
221
                             Beam::rest_collision_callback_proc, Y_AXIS);
 
222
    }
 
223
}
 
224
 
 
225
 
 
226
 
 
227
void
 
228
Beam_engraver::acknowledge_stem (Grob_info info)
 
229
{
 
230
  if (!beam_)
 
231
    return;
 
232
  
 
233
  Moment now = now_mom ();
 
234
  if (!valid_start_point ())
 
235
    return;
 
236
 
 
237
  Item *stem = dynamic_cast<Item *> (info.grob ());
 
238
  if (Stem::get_beam (stem))
 
239
    return;
 
240
 
 
241
  
 
242
  
 
243
  Music *m = info.ultimate_music_cause ();
 
244
  if (!m->is_mus_type ("rhythmic-event"))
 
245
    {
 
246
      string s = _ ("stem must have Rhythmic structure");
 
247
      if (info.music_cause ())
 
248
        info.music_cause ()->origin ()->warning (s);
 
249
      else
 
250
        ::warning (s);
 
251
 
 
252
      return;
 
253
    }
 
254
 
 
255
  last_stem_added_at_ = now;
 
256
  int durlog = unsmob_duration (m->get_property ("duration"))->duration_log ();
 
257
  if (durlog <= 2)
 
258
    {
 
259
      m->origin ()->warning (_ ("stem doesn't fit in beam"));
 
260
      prev_start_ev_->origin ()->warning (_ ("beam was started here"));
 
261
      /*
 
262
        don't return, since
 
263
 
 
264
        [r4 c8] can just as well be modern notation.
 
265
      */
 
266
    }
 
267
 
 
268
  stem->set_property ("duration-log",
 
269
                      scm_from_int (durlog));
 
270
  Moment stem_location = now - beam_start_mom_ + beam_start_location_;
 
271
  beam_info_->add_stem (stem_location,
 
272
                        max (durlog- 2, 0));
 
273
  Beam::add_stem (beam_, stem);
 
274
}
 
275
 
 
276
ADD_ACKNOWLEDGER (Beam_engraver, stem);
 
277
ADD_ACKNOWLEDGER (Beam_engraver, rest);
 
278
 
 
279
ADD_TRANSLATOR (Beam_engraver,
 
280
                /* doc */ "Handles Beam events by engraving Beams.    If omitted, then notes will be "
 
281
                "printed with flags instead of beams.",
 
282
                /* create */ "Beam",
 
283
                /* accept */ "beam-event",
 
284
                /* read */ "beamMelismaBusy beatLength subdivideBeams",
 
285
                /* write */ "");
291
286
 
292
287
class Grace_beam_engraver : public Beam_engraver
293
288
{
294
289
public:
295
 
  TRANSLATOR_DECLARATIONS (Grace_beam_engraver);  
 
290
  TRANSLATOR_DECLARATIONS (Grace_beam_engraver);
296
291
 
297
292
protected:
298
293
  virtual bool valid_start_point ();
311
306
  return n.grace_part_ != Rational (0);
312
307
}
313
308
 
314
 
 
315
309
bool
316
310
Grace_beam_engraver::valid_end_point ()
317
311
{
318
312
  return beam_ && valid_start_point ();
319
313
}
320
314
 
321
 
 
322
 
 
323
 
ENTER_DESCRIPTION (Grace_beam_engraver,
324
 
/* descr */       "Handles Beam events by engraving Beams.  If omitted, then notes will "
325
 
"be printed with flags instead of beams. Only engraves beams when we "
326
 
" are at grace points in time. "
327
 
,
328
 
/* creats*/       "Beam",
329
 
/* accepts */     "beam-event",
330
 
/* acks  */      "stem-interface rest-interface",
331
 
/* reads */       "beamMelismaBusy beatLength allowBeamBreak subdivideBeams",
332
 
/* write */       "");
 
315
ADD_ACKNOWLEDGER (Grace_beam_engraver, stem);
 
316
ADD_ACKNOWLEDGER (Grace_beam_engraver, rest);
 
317
ADD_TRANSLATOR (Grace_beam_engraver,
 
318
                /* doc */ "Handles Beam events by engraving Beams.  If omitted, then notes will "
 
319
                "be printed with flags instead of beams. Only engraves beams when we "
 
320
                " are at grace points in time. ",
 
321
                /* create */ "Beam",
 
322
                /* accept */ "beam-event",
 
323
                /* read */ "beamMelismaBusy beatLength allowBeamBreak subdivideBeams",
 
324
                /* write */ "");
333
325