]> git.donarmstrong.com Git - lilypond.git/blob - lily/page-turn-engraver.cc
* scm/page.scm (make-page): make it friendlier to call (esp. from C++)
[lilypond.git] / lily / page-turn-engraver.cc
1 /*
2   page-turn-engraver.cc -- implement Page_turn_engraver
3
4   source file of the GNU LilyPond music typesetter
5
6   (c) 2006 Joe Neeman <joeneeman@gmail.com>
7 */
8
9 #include "engraver.hh"
10
11 #include "context.hh"
12 #include "duration.hh"
13 #include "grob.hh"
14 #include "international.hh"
15 #include "moment.hh"
16 #include "warn.hh"
17
18 class Page_turn_engraver : public Engraver
19 {
20   Moment rest_begin_;
21   Moment repeat_begin_;
22   Moment note_end_;
23   Rational repeat_begin_rest_length_;
24
25   Real penalty (Rational rest_len);
26
27 protected:
28   DECLARE_ACKNOWLEDGER (note_head);
29
30 public:
31   TRANSLATOR_DECLARATIONS (Page_turn_engraver);
32   void stop_translation_timestep ();
33 };
34
35 Page_turn_engraver::Page_turn_engraver ()
36 {
37   repeat_begin_ = Moment (-1);
38   repeat_begin_rest_length_ = 0;
39   rest_begin_ = 0;
40   note_end_ = 0;
41 }
42
43 Real
44 Page_turn_engraver::penalty (Rational rest_len)
45 {
46   Rational min_turn = robust_scm2moment (get_property ("minPageTurnLength"), Moment (1)).main_part_;
47
48   return (rest_len < min_turn) ? infinity_f : 0;
49 }
50
51 void
52 Page_turn_engraver::acknowledge_note_head (Grob_info gi)
53 {
54   SCM dur_log_scm = gi.grob ()->get_property ("duration-log");
55   if (!scm_is_number (dur_log_scm))
56     return;
57
58   int dur_log = scm_to_int (dur_log_scm);
59   int dot_count = robust_scm2int (gi.grob ()->get_property ("dot-count"), 0);
60
61   if (rest_begin_ < now_mom ())
62     {
63       Real pen = penalty ((now_mom () - rest_begin_).main_part_);
64       if (!isinf (pen))
65         {
66           SCM val = scm_cons (rest_begin_.smobbed_copy (), scm_from_double (pen));
67           context ()->get_score_context ()->set_property ("allowPageTurn", val);
68         }
69     }
70
71   if (rest_begin_ <= repeat_begin_)
72     repeat_begin_rest_length_ = (now_mom () - repeat_begin_).main_part_;
73   note_end_ = now_mom () + Moment (Duration (dur_log, dot_count).get_length ());
74 }
75
76 void
77 Page_turn_engraver::stop_translation_timestep ()
78 {
79   /* C&P from Repeat_acknowledge_engraver */
80   SCM cs = get_property ("repeatCommands");
81   bool start = false;
82   bool end = false;
83
84   for (; scm_is_pair (cs); cs = scm_cdr (cs))
85     {
86       SCM command = scm_car (cs);
87       if (command == ly_symbol2scm ("start-repeat"))
88         start = true;
89       else if (command == ly_symbol2scm ("end-repeat"))
90         end = true;
91     }
92
93   if (end && repeat_begin_.main_part_ >= Moment (0))
94     {
95       Real pen = penalty ((now_mom () - rest_begin_).main_part_ + repeat_begin_rest_length_);
96       Moment *m = unsmob_moment (get_property ("minimumRepeatLengthForPageTurn"));
97       if (m && *m > (now_mom () - repeat_begin_))
98         pen = infinity_f;
99       if (pen > 0)
100         {
101           SCM val = scm_cons (repeat_begin_.smobbed_copy (), scm_from_double (pen));
102           context ()->get_score_context ()->set_property ("revokePageTurns", val);
103         }
104       repeat_begin_ = Moment (-1);
105     }
106   if (start)
107     {
108       repeat_begin_ = now_mom ();
109       repeat_begin_rest_length_ = 0;
110     }
111   rest_begin_ = note_end_;
112 }
113
114 #include "translator.icc"
115
116 ADD_ACKNOWLEDGER (Page_turn_engraver, note_head);
117 ADD_TRANSLATOR (Page_turn_engraver,
118                 /* doc */ "Decide where page turns are allowed to go",
119                 /* create */ "",
120                 /* accept */ "",
121                 /* read */ "",
122                 /* write */
123                 "allowPageTurn "
124                 "revokePageTurns "
125                 );