]> git.donarmstrong.com Git - lilypond.git/commitdiff
Merge remote branch 'origin' into release/unstable
authorGraham Percival <graham@percival-music.ca>
Mon, 4 Jul 2011 11:23:23 +0000 (12:23 +0100)
committerGraham Percival <graham@percival-music.ca>
Mon, 4 Jul 2011 11:23:23 +0000 (12:23 +0100)
Documentation/contributor/administration.itexi
Documentation/contributor/feta-font.itexi
Documentation/notation/pitches.itely
input/regression/glissando-broken-multiple.ly
lily/line-spanner.cc
scm/define-grobs.scm
scm/music-functions.scm
scm/output-lib.scm
scripts/lilymidi.py

index 9ee46b955ea407526edbe098371a400981ceed01..da8f48276caf3ac59043957dff16cbf60ec176b4 100644 (file)
@@ -505,6 +505,24 @@ amount of current material in either form, are important.
 
 (prep: 5 hours.  discuss: 15 hours)
 
+@item @strong{always make an issue number for patches}:
+there is a proposal that we should always have a google code issue
+number for every patch.  This proposal is closely tied to our
+choice of patch review tool; if we switch to a different tool (as
+suggested in a different proposal), this proposal may become moot.
+
+(prep: 1 hour.  discuss: 5 hours)
+
+@item @strong{initalizer lists}:
+shoudl we use initalizer lists for C++?  AFAIK they make no
+difference for built-in types, but there's some weird case where
+it's more efficient for objects, or something.
+
+Probably not worth making this a weekly thing on its own, but we
+can probably wrap it up with some other code-related questions.
+
+(prep: 15 minutes.  discuss: 3 hours)
+
 @end itemize
 
 @node Policy decisions (finished)
index a8bf78fe75dfb56af19f6f62e08ce12737028f38..eb5dd124cd18395007677e8fe532a34d81445ac7 100644 (file)
@@ -17,7 +17,10 @@ The feta font is a font that was created specifically for use in
 LilyPond.  The sources for the font are found in mf/*.mf.
 
 The feta font is merged from a number of subfonts.  Each subfont
-can contain at most 223 glyphs.
+can contain at most 224 glyphs.  This is because each subfont is
+limited to a one-byte address space (256 glyphs maximum) and we
+avoid the first 32 points in that address space, since they are
+non-printing control characters in ASCII.
 
 In LilyPond, glyphs are accessed by glyph name, rather than by code point.
 Therefore, the naming of glyphs is significant.
@@ -38,13 +41,15 @@ available at CTAN.
 
 mf2pt1 is used to create type 1 fonts from the metafont sources.
 
-FontForge is used to display the resulting glyph shapes.
+FontForge is used to postprocess the output of mf2pt1 and clean up
+details of the font.  It can also be used by a developer to
+display the resulting glyph shapes.
 
 @node Adding a new font section
 @section Adding a new font section
 
 The font is divided into sections, each of which contains less
-than 223 glyphs.  If more than 223 glyphs are included in a section,
+than 224 glyphs.  If more than 224 glyphs are included in a section,
 an error will be generated.
 
 Each of the sections is contained in a separate @code{.mf} file.  The
@@ -62,6 +67,8 @@ An entry in the generic file used to create the font, or a new
 generic file
 @item
 If necessary, new entries in the GNUmakefile
+@item
+An entry in @file{scripts/build/gen-emmentaler-scripts.py}
 @end itemize
 
 See the examples in @code{mf/} for more information.
@@ -104,4 +111,3 @@ is to do:
 rm mf/out/*
 make
 @end example
-
index f3ab13aec6a118e60a6ea4183844ffe9e851ff7a..c90ae01468a75e770c912d84e94fd03f71e847f8 100644 (file)
@@ -1677,10 +1677,10 @@ musicB = {
 
 This rule corresponds to the common practice in the twentieth
 century.  It omits some extra natural signs, which were
-traditionally prefixed to accidentals that reduce or reverse
-the direction of a previous alteration.  The @code{modern} rule
+traditionally prefixed to a sharp following a double sharp,
+or a flat following a double flat.  The @code{modern} rule
 prints the same accidentals as @code{default}, with
-two exceptions that serve to avoid ambiguity: after temporary
+two additions that serve to avoid ambiguity: after temporary
 accidentals, cancellation marks are printed also in the following
 measure (for notes in the same octave) and, in the same measure,
 for notes in other octaves.  Hence the naturals before
index 4ef945b427c1d266be3854aa04aa3c1e98616fcb..906f984be4067291366fb02b712ad91ebf01bfca 100644 (file)
   \break s1
   \break s1
   c,1^\ff\trill
+  % Subsequent glissando prints correctly instead of
+  % using the Y positions from the previous one.
+  a'1\glissando
+  \break s1
+  \break s1
+  \break s1
+  e1^\ff\trill
 }
index 69cbc69ce0544400a34b99ee748d634dc0933253..d50b94834a57c7fd3b6a83291d51acb7a0a23673 100644 (file)
@@ -224,6 +224,9 @@ Line_spanner::print (SCM smob)
 {
   Spanner *me = dynamic_cast<Spanner *> (unsmob_grob (smob));
 
+  // Triggers simple-Y calculations
+  bool simple_y = to_boolean (me->get_property ("simple-Y")) && !to_boolean (me->get_property ("cross-staff"));
+
   Drul_array<SCM> bounds (me->get_property ("left-bound-info"),
                          me->get_property ("right-bound-info"));
 
@@ -269,7 +272,6 @@ Line_spanner::print (SCM smob)
   while (flip (&d) != LEFT);
 
   Grob *my_common_y = common_y[LEFT]->common_refpoint (common_y[RIGHT], Y_AXIS);
-  bool simple_y = to_boolean (me->get_property ("simple-Y")) && !to_boolean (me->get_property ("cross-staff"));
 
   if (!simple_y)
     {
index d2162ce58724d7eed32258b0eed2c63afbddcd0c..9a8d14a1c31a434b0c02a72e194433ee818d1ed7 100644 (file)
     (Glissando
      . (
        (after-line-breaking . ,ly:spanner::kill-zero-spanned-time)
-       (before-line-breaking . ,glissando::before-line-breaking)
        (bound-details . ((right . ((attach-dir .  ,CENTER)
                                    (padding . 1.5)
                                      ))
        (left-bound-info . ,ly:line-spanner::calc-left-bound-info)
        (normalized-endpoints . ,ly:spanner::calc-normalized-endpoints)
        (right-bound-info . ,ly:line-spanner::calc-right-bound-info)
-       (simple-Y . #t)
+       (simple-Y . ,glissando::make-simple-y)
        (stencil . ,ly:line-spanner::print)
        (style . line)
        (X-extent . #f)
index 31b6c8ad3c48d3861b3ffe500b8a1c6d2f627d76..7c52d41846632b8ffda35086e6cdf49b032949ec 100644 (file)
@@ -1093,8 +1093,8 @@ specifies whether accidentals should be canceled in different octaves."
              (begin
                (set! need-accidental #t)
                (if (and (not (= this-alt 0))
-                        (or (< (abs this-alt) (abs prev-alt))
-                            (< (* prev-alt this-alt) 0)))
+                        (and (< (abs this-alt) (abs prev-alt))
+                            (> (* prev-alt this-alt) 0)))
                    (set! need-restore #t))))))
 
     (cons need-restore need-accidental)))
index a9581e5e8e0b47129cd94ecdb5cfaf019b6dc225..01953a941215f60b06c9a30797c5d2c5e8d551f0 100644 (file)
@@ -795,26 +795,35 @@ between the two text elements."
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;; glissando
 
-(define-public (glissando::before-line-breaking grob)
-  "Establishes the Y terminus points of the glissando based on the pre-broken
-positions of its left and right bounds."
-  (let ((bound-details (ly:grob-property grob 'bound-details))
+(define-public (glissando::make-simple-y grob)
+ "Establishes the Y terminus points of the glissando based on the
+pre-broken positions of its left and right bounds."
+ (let* ((siblings (ly:spanner-broken-into (ly:grob-original grob)))
+        (bound-details (ly:grob-property grob 'bound-details))
         (extra-dy (ly:grob-property grob 'extra-dy 0.0)))
 
-    (for-each (lambda (dir-sym)
-                (let* ((details (assoc-get dir-sym bound-details))
-                       (dir (if (eq? dir-sym 'left) LEFT RIGHT))
-                       (bound (ly:spanner-bound grob dir))
-                       (common-y (ly:grob-common-refpoint grob bound Y))
-                       (y (+ (interval-center (ly:grob-extent bound common-y Y))
-                             (/ (* dir extra-dy)
-                                2))))
-                  (if (not (assoc-get 'Y details))
-                      (set! bound-details (assoc-set! bound-details dir-sym
-                                                      (acons 'Y y details))))))
-              '(left right))
-
-    (set! (ly:grob-property grob 'bound-details) bound-details)))
+   (and (pair? siblings)
+        (for-each (lambda (dir-sym)
+                    (let* ((details (assoc-get dir-sym bound-details))
+                           (dir (if (eq? dir-sym 'left) LEFT RIGHT))
+                           (good-grob (if (eq? dir-sym 'left)
+                                          (first siblings)
+                                          (last siblings)))
+                           (bound (ly:spanner-bound good-grob dir))
+                           (common-y (ly:grob-common-refpoint good-grob
+                                                              bound
+                                                              Y))
+                           (y (+ (interval-center (ly:grob-extent bound
+                                                                 common-y
+                                                                 Y))
+                                 (/ (* dir extra-dy)
+                                    2))))
+                      (if (not (assoc-get 'Y details))
+                          (set! bound-details (assoc-set! bound-details dir-sym
+                                                          (acons 'Y y details))))))
+                  '(left right))
+
+        (set! (ly:grob-property grob 'bound-details) bound-details))))
 
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
index 73809a4d4d9f227591ded8fbfb0a63664f9e8226..357988818d13fe45d377e693a0707082e92fb3e0 100644 (file)
@@ -35,6 +35,8 @@ def process_options (args):
                        help="prefix filtered track numbers with PREFIX")
     parser.add_option ('', '--dump', action='store_true', dest='dump',
                        help="just dump parsed contents of the MIDI file")
+    parser.add_option ('', '--pretty', action='store_true', dest='pretty',
+                       help="dump parsed contents of the MIDI file in human-readable form (implies --dump)")
     parser.usage = parser.usage + " FILE"
     options, args = parser.parse_args (args)
     if len (args) != 1:
@@ -62,13 +64,142 @@ def track_info (data):
         track_info.append ((i, track_name (tracks[i])))
     return track_info
 
+
+class formatter:
+   def __init__ (self, txt = ""):
+     self.text = txt
+   def format_vals (self, val1, val2 = ""):
+     return str (val1) + str(val2)
+   def format (self, val1, val2 = ""):
+     return self.text + self.format_vals (val1, val2)
+class none_formatter (formatter):
+   def format_vals (self, val1, val2 = ""):
+     return ''
+class meta_formatter (formatter):
+   def format_vals (self, val1, val2):
+     return str (val2);
+class tempo_formatter (formatter):
+   def format_vals (self, val1, val2):
+     return str (val2) + " msec/quarter"
+
+class time_signature_formatter (formatter):
+   def format_vals (self, val1, val2 = ""):
+     return str (val2)   # TODO
+class key_signature_formatter (formatter):
+   def format_vals (self, val1, val2):
+     return str (val2)   # TODO
+class channel_formatter (formatter):
+   def __init__ (self, txt, ch):
+     formatter.__init__ (self, txt)
+     self.channel = ch
+   def format (self, val1, val2 = ""):
+     return self.text + "Channel " + str (self.channel) + ", " + \
+            self.format_vals (val1, val2)
+class control_mode_formatter (formatter):
+   def __init__ (self, txt, ch):
+     formatter.__init__ (self, txt)
+     self.mode = ch
+   def format (self, val1, val2 = ""):
+     return self.text + str (self.mode) + ", " + \
+            self.format_vals (val1, val2)
+class note_formatter (channel_formatter):
+   def pitch (self, val):
+     pitch_names = ['C', 'Cis', 'D', 'Dis', 'E', 'F', 'Fis', 'G', 'Gis', 'A', 'Ais', 'B'];
+     p = val % 12;
+     oct = val / 12 -1;
+     return pitch_names[p] + str(oct) + "(" + str(val) + ")"
+   def velocity (self, val):
+     #01   #10   #20   #30   #40   #50   #60   #70   #7F
+     pass;
+   def format_vals (self, val1, val2):
+     return self.pitch (val1)
+
+
+meta_dict = {0x00: meta_formatter ("Seq.Nr.:    "),
+             0x01: meta_formatter ("Text:       "),
+             0x02: meta_formatter ("Copyright:  "),
+             0x03: meta_formatter ("Track name: "),
+             0x04: meta_formatter ("Instrument: "),
+             0x05: meta_formatter ("Lyric:      "),
+             0x06: meta_formatter ("Marker:     "),
+             0x07: meta_formatter ("Cue point:  "),
+             0x2F: none_formatter ("End of Track"),
+             0x51: tempo_formatter ("Tempo:      "),
+             0x54: meta_formatter ("SMPTE Offs.:"),
+             0x58: time_signature_formatter ("Time signature: "),
+             0x59: key_signature_formatter ("Key signature: ")
+}
+
+def dump_event (ev, time, padding):
+    ch = ev[0] & 0x0F;
+    func = ev[0] & 0xF0;
+    f = None
+    if (ev[0] == 0xFF):
+        f = meta_dict.get (ev[1], formatter ())
+    if (func == 0x80):
+        f = note_formatter ("Note off: ", ch)
+    elif (func == 0x90):
+        if (ev[2] == 0):
+          desc = "Note off: "
+        else:
+          desc = "Note on: "
+        f = note_formatter (desc, ch)
+    elif (func == 0xA0):
+        f = note_formatter ("Polyphonic aftertouch: ", ch, "Aftertouch pressure: ")
+    elif (func == 0xB0):
+        f = control_mode_formatter ("Control mode change: ", ch)
+    elif (func == 0xC0):
+        f = channel_formatter ("Program Change: ", ch)
+    elif (func == 0xD0):
+        f = channel_formatter ("Channel aftertouch: ", ch)
+    elif (ev[0] in [0xF0, 0xF7]):
+        f = meta_formatter ("System-exclusive event: ")
+
+    if f:
+      if len (ev) > 2:
+        print padding + f.format (ev[1], ev[2])
+      elif len (ev) > 1:
+        print padding + f.format (ev[1])
+      else:
+        print padding + f.format ()
+    else:
+      print padding + "Unrecognized MIDI event: " + str (ev);
+
+def dump_midi (data, midi_file, options):
+    if not options.pretty:
+        print data
+        return
+    # First, dump general info, #tracks, etc.
+    print "Filename:     " + midi_file;
+    i = data[0];
+    m_formats = {0: 'single multi-channel track',
+                 1: "one or more simultaneous tracks",
+                 2: "one or more sequentially independent single-track patterns"}
+    print "MIDI format:  " + str (i[0]) + " (" + m_formats.get (i[0], "") + ")";
+    print "Divisions:    " + str (i[1]) + " per whole note";
+    print "#Tracks:      " + str ( len (data[1]))
+    n = 0;
+    for tr in data[1]:
+      time = 0;
+      n += 1;
+      print
+      print "Track " + str(n) + ":"
+      print "    Time 0:"
+      for ev in tr:
+        if ev[0]>time:
+           time = ev[0]
+           print "    Time " + str(time) + ": "
+        dump_event (ev[1], time, "        ");
+
+
+
 def go ():
     options, args = process_options (sys.argv[1:])
     midi_file = args[0]
     midi_data = read_midi (midi_file)
     info = track_info (midi_data)
-    if options.dump:
-        print midi_data
+    if (options.dump or options.pretty):
+        dump_midi (midi_data, midi_file, options);
     elif options.regexp:
         import re
         regexp = re.compile (options.regexp)