]> git.donarmstrong.com Git - lilypond.git/commitdiff
Don't wrap EventChord around rhythmic events outside of music lists.
authorDavid Kastrup <dak@gnu.org>
Thu, 1 Dec 2011 17:32:15 +0000 (18:32 +0100)
committerDavid Kastrup <dak@gnu.org>
Wed, 25 Jan 2012 15:53:25 +0000 (16:53 +0100)
input/regression/display-lily-tests.ly
lily/music-scheme.cc
lily/parser.yy
ly/music-functions-init.ly
scm/define-music-display-methods.scm
scm/modal-transforms.scm
scm/music-functions.scm
scm/song-util.scm
scm/song.scm

index 998627b716b3664c835a6e6147326418d1e60084..76bfc420c629a0eef4cca54e48818fedcb8934da 100644 (file)
@@ -74,7 +74,7 @@ stderr of this run."
 
 %% tags
 \test ##[ { \tag #'foo { c4 d } } #]
-\test ##[ c-\tag #'foo -\tag #'baz -^ -. #]
+\test ##[ c-\tag #'foo -\tag #'baz -^-. #]
 
 %% Graces
 \test ##[ { \grace c8 d2 } #]                          % GraceMusic
index 93fd55d9a55e057426fc2de5fd00ee4bb87b1253..ffa903b4ebedc5d6ead2b34eb08679747f3ab30e 100644 (file)
@@ -76,7 +76,7 @@ LY_DEFINE (ly_music_p, "ly:music?",
 
 LY_DEFINE (ly_event_p, "ly:event?",
            1, 0, 0, (SCM obj),
-           "Is @var{obj} an event object?")
+           "Is @var{obj} a proper (non-rhythmic) event object?")
 {
   if (Music *m = unsmob_music (obj))
     {
index e59625cc36fedf0d0fc5f98f3dfe05fd7692b04b..e913d88cf1df3ecfe52e41f136643026d9c58687 100644 (file)
@@ -201,7 +201,7 @@ while (0)
   scm_apply_0 (proc, args)
 /* Syntactic Sugar. */
 #define MAKE_SYNTAX(name, location, ...)       \
-  LOWLEVEL_MAKE_SYNTAX (ly_lily_module_constant (name), scm_list_n (parser->self_scm (), make_input (location) , ##__VA_ARGS__, SCM_UNDEFINED));
+  LOWLEVEL_MAKE_SYNTAX (ly_lily_module_constant (name), scm_list_n (parser->self_scm (), make_input (location) , ##__VA_ARGS__, SCM_UNDEFINED))
 #define START_MAKE_SYNTAX(name, ...)                                   \
        scm_list_n (ly_lily_module_constant (name) , ##__VA_ARGS__, SCM_UNDEFINED)
 #define FINISH_MAKE_SYNTAX(start, location, ...)                       \
@@ -468,7 +468,6 @@ If we give names, Bison complains.
 %type <scm> embedded_scm_bare
 %type <scm> embedded_scm_bare_arg
 %type <scm> embedded_scm_closed
-%type <scm> embedded_scm_chord_body
 %type <scm> event_function_event
 %type <scm> figure_list
 %type <scm> figure_spec
@@ -513,7 +512,6 @@ If we give names, Bison complains.
 %type <scm> multiplied_duration
 %type <scm> music_function_event
 %type <scm> music_function_chord_body
-%type <scm> music_function_chord_body_arglist
 %type <scm> new_chord
 %type <scm> new_lyrics
 %type <scm> number_expression
@@ -776,16 +774,7 @@ identifier_init:
                $$ = $1;
        }
        | music  {
-               /* Hack: Create event-chord around standalone events.
-                  Prevents the identifier from being interpreted as a post-event. */
-               Music *mus = unsmob_music ($1);
-               bool is_event = mus &&
-                       (scm_memq (ly_symbol2scm ("event"), mus->get_property ("types"))
-                               != SCM_BOOL_F);
-               if (!is_event)
-                       $$ = $1;
-               else
-                       $$ = MAKE_SYNTAX ("event-chord", @$, scm_list_1 ($1));
+               $$ = $1;
        }
        | post_event_nofinger {
                $$ = $1;
@@ -2046,10 +2035,12 @@ scalar_closed:
 
 
 event_chord:
-       /* TODO: Create a special case that avoids the creation of
-          EventChords around simple_elements that have no post_events?
-        */
-       simple_chord_elements post_events       {
+       simple_element post_events {
+               // Let the rhythmic music iterator sort this mess out.
+               unsmob_music ($1)->set_property ("articulations",
+                                                scm_reverse_x ($2, SCM_EOL));
+       }
+       | simple_chord_elements post_events     {
                SCM elts = ly_append2 ($1, scm_reverse_x ($2, SCM_EOL));
 
                Input i;
@@ -2111,7 +2102,8 @@ chord_body:
 chord_body_elements:
        /* empty */             { $$ = SCM_EOL; }
        | chord_body_elements chord_body_element {
-               $$ = scm_cons ($2, $1);
+               if (!SCM_UNBNDP ($2))
+                       $$ = scm_cons ($2, $1);
        }
        ;
 
@@ -2153,43 +2145,17 @@ chord_body_element:
                $$ = n->unprotect ();
        }
        | music_function_chord_body
-       ;
-
-/* We can't accept a music argument, not even a closed one,
- * immediately before chord_body_elements, otherwise a function \fun
- * with a signature of two music arguments can't be sorted out
- * properly in a construct like
- * <\fun { c } \fun { c } c>
- * The second call could be interpreted either as a chord constituent
- * or a music expression.
- */
-
-music_function_chord_body_arglist:
-       function_arglist_bare
-       | EXPECT_SCM music_function_chord_body_arglist embedded_scm_chord_body
        {
-               $$ = check_scheme_arg (parser, @3,
-                                      $3, $2, $1);
-       }
-       ;
-
-embedded_scm_chord_body:
-       embedded_scm_bare_arg
-       | SCM_FUNCTION music_function_chord_body_arglist {
-               $$ = MAKE_SYNTAX ("music-function", @$,
-                                        $1, $2);
+               if (!unsmob_music ($$)->is_mus_type ("rhythmic-event")) {
+                       parser->parser_error (@$, _ ("not a rhythmic event"));
+                       $$ = SCM_UNDEFINED;
+               }
        }
-       | bare_number
-       | fraction
-       | lyric_element
-       | chord_body_element
        ;
 
 music_function_chord_body:
-       MUSIC_FUNCTION music_function_chord_body_arglist {
-               $$ = MAKE_SYNTAX ("music-function", @$,
-                                        $1, $2);
-       }
+       music_function_call
+       | MUSIC_IDENTIFIER
        ;
 
 // Event functions may only take closed arglists, otherwise it would
@@ -2766,10 +2732,7 @@ simple_element:
        ;
 
 simple_chord_elements:
-       simple_element  {
-               $$ = scm_list_1 ($1);
-       }
-       | new_chord {
+       new_chord {
                 if (!parser->lexer_->is_chord_state ())
                         parser->parser_error (@1, _ ("have to be in Chord mode for chords"));
                 $$ = $1;
@@ -2795,35 +2758,29 @@ lyric_element:
 lyric_element_arg:
        lyric_element
        | lyric_element multiplied_duration post_events {
-               SCM lyric_event = MAKE_SYNTAX ("lyric-event", @$, $1, $2);
-               $$ = MAKE_SYNTAX ("event-chord", @$,
-                                 scm_cons (lyric_event,
-                                           scm_reverse_x ($3, SCM_EOL)));
+               $$ = MAKE_SYNTAX ("lyric-event", @$, $1, $2);
+               unsmob_music ($$)->set_property
+                       ("articulations", scm_reverse_x ($3, SCM_EOL));
        }
        | lyric_element post_event post_events {
-               SCM lyric_event =
-                       MAKE_SYNTAX ("lyric-event", @$, $1,
-                                    parser->default_duration_.smobbed_copy ());
-               $$ = MAKE_SYNTAX ("event-chord", @$,
-                                 scm_cons2 (lyric_event, $2,
-                                            scm_reverse_x ($3, SCM_EOL)));
-                                            
+               $$ = MAKE_SYNTAX ("lyric-event", @$, $1,
+                                 parser->default_duration_.smobbed_copy ());
+               unsmob_music ($$)->set_property
+                       ("articulations", scm_cons ($2, scm_reverse_x ($3, SCM_EOL)));
        }
        | LYRIC_ELEMENT optional_notemode_duration post_events {
-               SCM lyric_event = MAKE_SYNTAX ("lyric-event", @$, $1, $2);
-               $$ = MAKE_SYNTAX ("event-chord", @$,
-                                 scm_cons (lyric_event,
-                                           scm_reverse_x ($3, SCM_EOL)));
+               $$ = MAKE_SYNTAX ("lyric-event", @$, $1, $2);
+               unsmob_music ($$)->set_property
+                       ("articulations", scm_reverse_x ($3, SCM_EOL));
        }
        ;
 
 
 lyric_element_music:
        lyric_element optional_notemode_duration post_events {
-               SCM lyric_event = MAKE_SYNTAX ("lyric-event", @$, $1, $2);
-               $$ = MAKE_SYNTAX ("event-chord", @$,
-                                 scm_cons (lyric_event,
-                                           scm_reverse_x ($3, SCM_EOL)));
+               $$ = MAKE_SYNTAX ("lyric-event", @$, $1, $2);
+               unsmob_music ($$)->set_property
+                       ("articulations", scm_reverse_x ($3, SCM_EOL));
        }
        ;
 
index 933712736233eaee870adf5ced267ad05d93f781..59c452065c3a03cc33fda0e489908c5f15faff69 100644 (file)
@@ -293,13 +293,11 @@ endSpanners =
 #(define-music-function (parser location music) (ly:music?)
    (_i "Terminate the next spanner prematurely after exactly one note
 without the need of a specific end spanner.")
-   (if (eq? (ly:music-property music 'name) 'EventChord)
-       (let* ((elts (ly:music-property music 'elements))
-             (start-span-evs (filter (lambda (ev)
-                                       (and (music-has-type ev 'span-event)
-                                            (equal? (ly:music-property ev 'span-direction)
-                                                    START)))
-                                     elts))
+   (if (memq (ly:music-property music 'name) '(EventChord NoteEvent))
+       (let* ((start-span-evs (filter (lambda (ev)
+                                       (equal? (ly:music-property ev 'span-direction)
+                                               START))
+                                     (extract-typed-music music 'span-event)))
              (stop-span-evs
               (map (lambda (m)
                      (let ((c (music-clone m)))
@@ -314,7 +312,7 @@ without the need of a specific end spanner.")
         total)
 
        (begin
-        (ly:input-message location (_ "argument endSpanners is not an EventChord: ~a" music))
+        (ly:input-message location (_ "argument endSpanners is not an EventChord: ~a") music)
         music)))
 
 
@@ -325,16 +323,13 @@ featherDurations=
    (let ((orig-duration (ly:music-length argument))
         (multiplier (ly:make-moment 1 1)))
 
-     (music-map
+     (for-each
       (lambda (mus)
-       (if (and (eq? (ly:music-property mus 'name) 'EventChord)
-                (< 0 (ly:moment-main-denominator (ly:music-length mus))))
+       (if (< 0 (ly:moment-main-denominator (ly:music-length mus)))
            (begin
              (ly:music-compress mus multiplier)
-             (set! multiplier (ly:moment-mul factor multiplier))))
-       mus)
-      argument)
-
+             (set! multiplier (ly:moment-mul factor multiplier)))))
+      (extract-named-music argument '(EventChord NoteEvent RestEvent SkipEvent)))
      (ly:music-compress
       argument
       (ly:moment-div orig-duration (ly:music-length argument)))
@@ -846,13 +841,9 @@ pitchedTrill =
    (_i "Print a trill with @var{main-note} as the main note of the trill and
 print @var{secondary-note} as a stemless note head in parentheses.")
    (let* ((get-notes (lambda (ev-chord)
-                       (filter
-                        (lambda (m) (eq? 'NoteEvent (ly:music-property m 'name)))
-                        (ly:music-property ev-chord 'elements))))
+                      (extract-named-music ev-chord 'NoteEvent)))
           (sec-note-events (get-notes secondary-note))
-          (trill-events (filter (lambda (m) (music-has-type m 'trill-span-event))
-                                (ly:music-property main-note 'elements))))
-
+          (trill-events (extract-named-music main-note 'TrillSpanEvent)))
      (if (pair? sec-note-events)
          (begin
            (let* ((trill-pitch (ly:music-property (car sec-note-events) 'pitch))
index 4546afb0acc0b8dd77524478332616bb0ff8a616..ac9930e1381ae24b9b36ee57a21382e990f2df43 100644 (file)
@@ -108,7 +108,9 @@ expression."
 (define*-public (duration->lily-string ly-duration #:key (prev-duration (*previous-duration*))
                        (force-duration (*force-duration*))
                        (time-factor-numerator (*time-factor-numerator*))
-                       (time-factor-denominator (*time-factor-denominator*)))
+                       (time-factor-denominator (*time-factor-denominator*))
+                       remember)
+  (if remember (*previous-duration* ly-duration))
   (let ((log2   (ly:duration-log ly-duration))
        (dots    (ly:duration-dot-count ly-duration))
        (num+den (ly:duration-factor ly-duration)))
@@ -252,24 +254,22 @@ expression."
     (and (with-music-match (?start (music
                                    'SequentialMusic
                                    elements ((music
-                                              'EventChord
-                                              elements ((music
-                                                         'SkipEvent
-                                                         duration (ly:make-duration 0 0 0 1))
-                                                        (music
-                                                         'SlurEvent
-                                                         span-direction START))))))
-          #t)
-         (with-music-match (?stop (music
-                                   'SequentialMusic
-                                   elements ((music
-                                              'EventChord
-                                              elements ((music
-                                                         'SkipEvent
-                                                         duration (ly:make-duration 0 0 0 1))
-                                                        (music
-                                                         'SlurEvent
-                                                         span-direction STOP))))))
+                                              'SkipEvent
+                                              duration (ly:make-duration 0 0 0 1)
+                                              articulations
+                                              ((music
+                                                'SlurEvent
+                                                span-direction START))))))
+           #t)
+        (with-music-match (?stop (music
+                                  'SequentialMusic
+                                  elements ((music
+                                             'SkipEvent
+                                             duration (ly:make-duration 0 0 0 1)
+                                             articulations
+                                             ((music
+                                               'SlurEvent
+                                               span-direction STOP))))))
            (format #f "\\appoggiatura ~a" (music->lily-string ?music parser))))))
 
 
@@ -287,13 +287,12 @@ expression."
     (and (with-music-match (?start (music
                                    'SequentialMusic
                                    elements ((music
-                                              'EventChord
-                                              elements ((music
-                                                         'SkipEvent
-                                                         duration (ly:make-duration 0 0 0 1))
-                                                        (music
-                                                         'SlurEvent
-                                                         span-direction START)))
+                                              'SkipEvent
+                                              duration (ly:make-duration 0 0 0 1)
+                                              articulations
+                                              ((music
+                                                'SlurEvent
+                                                span-direction START)))
                                              (music
                                               'ContextSpeccedMusic
                                               element (music
@@ -310,14 +309,14 @@ expression."
                                                       'RevertProperty
                                                       grob-property-path '(stroke-style)
                                                       symbol 'Flag))
+
                                             (music
-                                             'EventChord
-                                             elements ((music
-                                                        'SkipEvent
-                                                        duration (ly:make-duration 0 0 0 1))
-                                                       (music
-                                                        'SlurEvent
-                                                        span-direction STOP))))))
+                                             'SkipEvent
+                                             duration (ly:make-duration 0 0 0 1)
+                                             articulations
+                                             ((music
+                                               'SlurEvent
+                                               span-direction STOP))))))
           (format #f "\\acciaccatura ~a" (music->lily-string ?music parser))))))
 
 (define-extra-display-method GraceMusic (expr parser)
@@ -346,12 +345,16 @@ expression."
                                  (*max-element-number-before-break*))))
        (elements (ly:music-property seq 'elements))
        (chord? (make-music-type-predicate 'EventChord))
+       (note-or-chord? (make-music-type-predicate 'EventChord 'NoteEvent
+                                                  'LyricEvent 'RestEvent
+                                                  'ClusterNoteEvent))
        (cluster? (make-music-type-predicate 'ClusterNoteEvent))
        (note? (make-music-type-predicate 'NoteEvent)))
     (format #f "~a~a{~v%~v_~{~a~^ ~}~v%~v_}"
            (if (any (lambda (e)
-                      (and (chord? e)
-                           (any cluster? (ly:music-property e 'elements))))
+                      (or (cluster? e)
+                          (and (chord? e)
+                               (any cluster? (ly:music-property e 'elements)))))
                     elements)
                "\\makeClusters "
                "")
@@ -366,15 +369,17 @@ expression."
                       "\\figuremode ")
                      ((any (lambda (chord)
                              (any (make-music-type-predicate 'LyricEvent)
-                                  (ly:music-property chord 'elements)))
-                           (filter chord? elements))
+                                  (cons chord
+                                        (ly:music-property chord 'elements))))
+                           (filter note-or-chord? elements))
                       "\\lyricmode ")
                      ((any (lambda (chord)
                              (any (lambda (event)
                                     (and (note? event)
                                          (not (null? (ly:music-property event 'drum-type)))))
-                                  (ly:music-property chord 'elements)))
-                           (filter chord? elements))
+                                  (cons chord
+                                        (ly:music-property chord 'elements))))
+                           (filter note-or-chord? elements))
                       "\\drummode ")
                      (else ;; TODO: other modes?
                       ""))
@@ -425,7 +430,7 @@ Otherwise, return #f."
   (let* ((elements (ly:music-property chord 'elements))
         (simple-elements (filter (make-music-type-predicate
                                   'NoteEvent 'ClusterNoteEvent 'RestEvent
-                                  'MultiMeasureRestEvent 'SkipEvent 'LyricEvent)
+                                  'SkipEvent 'LyricEvent)
                                  elements)))
     (if ((make-music-type-predicate 'StaffSpanEvent 'BreathingEvent) (car elements))
        ;; first, a special case: StaffSpanEvent (\startStaff, \stopStaff)
@@ -433,46 +438,39 @@ Otherwise, return #f."
        (music->lily-string (car elements) parser)
        (if (and (not (null? simple-elements))
                 (null? (cdr simple-elements))
-                ;; special case: if this simple_element has any post_events in
-                ;; its 'articulations list, it should be interpreted instead
-                ;; as a note_chord_element to prevent spurious output, e.g.,
-                ;; \displayLilyMusic < c-1\4 >8 -> c-1\48
-                (null? (filter post-event?
-                               (ly:music-property (car simple-elements) 'articulations)))
+                ;; a non-empty articulation list is only possible with
+                ;; chord entry.
+                (null? (ly:music-property (car simple-elements) 'articulations))
                 ;; same for simple_element with \tweak
                 (null? (ly:music-property (car simple-elements) 'tweaks)))
            ;; simple_element : note | figure | rest | mmrest | lyric_element | skip
            (let* ((simple-element (car simple-elements))
-                  (duration (ly:music-property simple-element 'duration))
-                  (lily-string (format #f "~a~a~a~{~a~^ ~}"
-                                       (music->lily-string simple-element parser)
-                                       (duration->lily-string duration)
-                                       (if (and ((make-music-type-predicate 'RestEvent) simple-element)
-                                                (ly:pitch? (ly:music-property simple-element 'pitch)))
-                                           "\\rest"
-                                           "")
-                                       (map-in-order (lambda (music)
-                                                       (music->lily-string music parser))
-                                                     (filter post-event? elements)))))
-             (*previous-duration* duration)
-             lily-string)
+                  (duration (duration->lily-string
+                             (ly:music-property simple-element 'duration)
+                             #:remember #t)))
+             (format #f "~a~a~{~a~^ ~}"
+                     (music->lily-string simple-element parser)
+                     duration
+                     (map-in-order (lambda (music)
+                                     (music->lily-string music parser))
+                                   (filter post-event? elements))))
            (let ((chord-elements (filter (make-music-type-predicate
                                           'NoteEvent 'ClusterNoteEvent 'BassFigureEvent)
                                          elements))
                  (post-events (filter post-event? elements)))
              (if (not (null? chord-elements))
                  ;; note_chord_element : '<' (notepitch | drumpitch)* '>" duration post_events
-                 (let ((lily-string (format #f "< ~{~a ~}>~a~{~a~^ ~}"
-                                            (map-in-order (lambda (music)
-                                                            (music->lily-string music parser))
-                                                          chord-elements)
-                                            (duration->lily-string (ly:music-property (car chord-elements)
-                                                                                      'duration))
-                                            (map-in-order (lambda (music)
-                                                            (music->lily-string music parser))
-                                                          post-events))))
-                   (*previous-duration* (ly:music-property (car chord-elements) 'duration))
-                   lily-string)
+                 (let* ((duration (duration->lily-string
+                                   (ly:music-property (car chord-elements) 'duration)
+                                   #:remember #t)))
+                   (format #f "< ~{~a ~}>~a~{~a~^ ~}"
+                           (map-in-order (lambda (music)
+                                           (music->lily-string music parser))
+                                         chord-elements)
+                           duration
+                           (map-in-order (lambda (music)
+                                           (music->lily-string music parser))
+                                         post-events)))
                  ;; command_element
                  (format #f "~{~a~^ ~}" (map-in-order (lambda (music)
                                                       (music->lily-string music parser))
@@ -499,7 +497,7 @@ Otherwise, return #f."
 ;;;
 
 (define (simple-note->lily-string event parser)
-  (format #f "~a~a~a~a~{~a~}" ; pitchname octave !? octave-check articulations
+  (format #f "~a~a~a~a~a~a~{~a~}" ; pitchname octave !? octave-check duration optional_rest articulations
          (note-name->lily-string (ly:music-property event 'pitch) parser)
          (octave->lily-string (ly:music-property event 'pitch))
          (let ((forced (ly:music-property event 'force-accidental))
@@ -519,6 +517,10 @@ Otherwise, return #f."
                                        (make-string (1- (* -1 octave-check)) #\,))
                                       (else "")))
                ""))
+         (duration->lily-string (ly:music-property event 'duration)
+                                #:remember #t)
+         (if ((make-music-type-predicate 'RestEvent) event)
+             "\\rest" "")
          (map-in-order (lambda (event)
                          (music->lily-string event parser))
                        (ly:music-property event 'articulations))))
@@ -527,7 +529,9 @@ Otherwise, return #f."
   (cond ((not (null? (ly:music-property note 'pitch))) ;; note
         (simple-note->lily-string note parser))
        ((not (null? (ly:music-property note 'drum-type))) ;; drum
-        (format #f "~a" (ly:music-property note 'drum-type)))
+        (format #f "~a~a" (ly:music-property note 'drum-type)
+                (duration->lily-string (ly:music-property note 'duration)
+                                       #:remember #t)))
        (else ;; unknown?
         "")))
 
@@ -537,13 +541,16 @@ Otherwise, return #f."
 (define-display-method RestEvent (rest parser)
   (if (not (null? (ly:music-property rest 'pitch)))
       (simple-note->lily-string rest parser)
-      "r"))
+      (string-append "r" (duration->lily-string (ly:music-property rest 'duration)
+                                               #:remember #t))))
 
 (define-display-method MultiMeasureRestEvent (rest parser)
-  "R")
+  (string-append "R" (duration->lily-string (ly:music-property rest 'duration)
+                                           #:remember #t)))
 
 (define-display-method SkipEvent (rest parser)
-  "s")
+  (string-append "s" (duration->lily-string (ly:music-property rest 'duration)
+                                           #:remember #t)))
 
 (define-display-method RepeatedChord (chord parser)
   (music->lily-string (ly:music-property chord 'element) parser))
@@ -615,18 +622,21 @@ Otherwise, return #f."
            (if (null? bracket-stop) "" "]"))))
 
 (define-display-method LyricEvent (lyric parser)
-  (let ((text (ly:music-property lyric 'text)))
-    (if (or (string? text)
-           (eqv? (first text) simple-markup))
-       ;; a string or a simple markup
-       (let ((string (if (string? text)
-                         text
-                         (second text))))
-         (if (string-match "(\"| |[0-9])" string)
-             ;; TODO check exactly in which cases double quotes should be used
-             (format #f "~s" string)
-             string))
-       (markup->lily-string text))))
+  (format "~a~{~a~^ ~}"
+         (let ((text (ly:music-property lyric 'text)))
+           (if (or (string? text)
+                   (eqv? (first text) simple-markup))
+               ;; a string or a simple markup
+               (let ((string (if (string? text)
+                                 text
+                                 (second text))))
+                 (if (string-match "(\"| |[0-9])" string)
+                     ;; TODO check exactly in which cases double quotes should be used
+                     (format #f "~s" string)
+                     string))
+               (markup->lily-string text)))
+         (map-in-order (lambda (m) (music->lily-string m parser))
+                       (ly:music-property lyric 'articulations))))
 
 (define-display-method BreathingEvent (event parser)
   "\\breathe")
index 737d7e2a9f37dc8c9bf8a957678e902fe13b3656..9617329d77843a4e13777046cc86908be1edd44a 100644 (file)
@@ -126,7 +126,7 @@ LilyPond scheme pitches, e.g. @code{(ly:make-pitch 0 2 0)}
       (change-pitches element converter)))))
 
 
-(define (extract-pitch-sequence music)
+(define (make-scale music)
   "Recurse through @var{music}, extracting pitches.
 Returns a list of pitch objects, e.g
 @code{'((ly:make-pitch 0 2 0) (ly:make-pitch 0 4 0) ... )}
@@ -140,20 +140,15 @@ Typically used to construct a scale for input to transposer-factory
 
     (cond
      ((ly:pitch? pitch)
-      pitch)
+      (list pitch))
 
      ((pair? elements)
-      (map
-       (lambda (x) (extract-pitch-sequence x))
+      (append-map
+       (lambda (x) (make-scale x))
        elements))
 
      ((ly:music? element)
-      (extract-pitch-sequence element)))))
-
-(define (make-scale music)
-  "Convenience wrapper for extract-pitch-sequence."
-  (map car (extract-pitch-sequence music)))
-
+      (make-scale element)))))
 
 (define (make-extended-scale music)
   "Extend scale given by @var{music} by 5 octaves up and down."
index 1b1d07c490fefefbcaeaadfff19f7eec604283fd..6114e144d6bc8e6b5d8400fd7b5b2d3bd04ed132 100644 (file)
@@ -276,12 +276,12 @@ through MUSIC."
     (set! (ly:music-property r 'repeat-count) (max times 1))
     (set! (ly:music-property r 'elements) talts)
     (if (and (equal? name "tremolo")
-            (or (pair? (ly:music-property main 'elements))
-                (ly:music? (ly:music-property main 'element))))
+            (pair? (extract-named-music main 'NoteEvent)))
        ;; This works for single-note and multi-note tremolos!
        (let* ((children (if (music-is-of-type? main 'sequential-music)
                             ;; \repeat tremolo n { ... }
-                            (length (extract-named-music main 'EventChord))
+                            (length (extract-named-music main '(EventChord
+                                                                NoteEvent)))
                             ;; \repeat tremolo n c4
                             1))
               ;; # of dots is equal to the 1 in bitwise representation (minus 1)!
@@ -311,7 +311,7 @@ if durations in @var{music} vary, allowing slash beats and double-percent
 beats to be distinguished."
   (let* ((durs (map (lambda (elt)
                      (duration-of-note elt))
-                   (extract-named-music music 'EventChord)))
+                   (extract-named-music music '(EventChord NoteEvent))))
         (first-dur (car durs)))
 
     (if (every (lambda (d) (equal? d first-dur)) durs)
@@ -1517,7 +1517,8 @@ Entries that conform with the current key signature are not invalidated."
 (define-public (duration-of-note event-chord)
   (let ((evs (filter (lambda (x)
                       (music-has-type x 'rhythmic-event))
-                    (ly:music-property event-chord 'elements))))
+                    (cons event-chord
+                          (ly:music-property event-chord 'elements)))))
 
     (and (pair? evs)
         (ly:music-property (car evs) 'duration))))
@@ -1526,21 +1527,33 @@ Entries that conform with the current key signature are not invalidated."
 
 (define-public (extract-named-music music music-name)
   "Return a flat list of all music named @var{music-name} from @var{music}."
-   (let ((extracted-list
-          (if (ly:music? music)
-              (if (eq? (ly:music-property music 'name) music-name)
-                  (list music)
-                  (let ((elt (ly:music-property music 'element))
-                        (elts (ly:music-property music 'elements)))
-                    (if (ly:music? elt)
-                        (extract-named-music elt music-name)
-                        (if (null? elts)
-                            '()
-                            (map (lambda(x)
-                                    (extract-named-music x music-name ))
-                             elts)))))
-              '())))
-     (flatten-list extracted-list)))
+  (if (not (list? music-name))
+      (set! music-name (list music-name)))
+  (if (ly:music? music)
+      (if (memq (ly:music-property music 'name) music-name)
+         (list music)
+         (let ((arts (ly:music-property music 'articulations)))
+           (append-map!
+            (lambda (x) (extract-named-music x music-name))
+            (if (pair? arts)
+                arts
+                (cons (ly:music-property music 'element)
+                      (ly:music-property music 'elements))))))
+      '()))
+
+(define-public (extract-typed-music music type)
+  "Return a flat list of all music with @var{type} from @var{music}."
+  (if (ly:music? music)
+      (if (music-is-of-type? music type)
+         (list music)
+         (let ((arts (ly:music-property music 'articulations)))
+           (append-map!
+            (lambda (x) (extract-typed-music x type))
+            (if (pair? arts)
+                arts
+                (cons (ly:music-property music 'element)
+                      (ly:music-property music 'elements))))))
+      '()))
 
 (define-public (event-chord-notes event-chord)
   "Return a list of all notes from @var{event-chord}."
index 9a65d44c8eea934ca42b0248fc4031aea257110d..568b967ba6d16ef891b691c87774c81d2e6268a7 100644 (file)
@@ -159,7 +159,9 @@ If it unsets the property, return @code{#f}."
 (define-public (music-elements music)
   "Return list of all @var{music}'s top-level children."
   (let ((elt (ly:music-property music 'element))
-        (elts (ly:music-property music 'elements)))
+        (elts (append
+              (ly:music-property music 'articulations)
+              (ly:music-property music 'elements))))
     (if (not (null? elt))
         (cons elt elts)
         elts)))
@@ -182,12 +184,17 @@ If it unsets the property, return @code{#f}."
 (define-public (process-music music function)
   "Process all nodes of @var{music} (including @var{music}) in the DFS order.
 Apply @var{function} on each of the nodes.  If @var{function} applied on a
-node returns @code{#t}, don't process the node's subtree."
+node returns @code{#t}, don't process the node's subtree.
+
+If a non-boolean is returned, it is considered the material to recurse."
   (define (process-music queue)
     (if (not (null? queue))
         (let* ((elt (car queue))
                (stop (function elt)))
-          (process-music (if stop
-                             (cdr queue)
-                             (append (music-elements elt) (cdr queue)))))))
+          (process-music (if (boolean? stop)
+                            (if stop
+                                (cdr queue)
+                                (append (music-elements elt) (cdr queue)))
+                            ((if (cheap-list? stop) append cons)
+                             stop (cdr queue)))))))
   (process-music (list music)))
index ffa53816c22293af75ab27f862bd4c137313fc5b..71eb03d72f4b5aa17ed5f5902c98798fdac5f2fb 100644 (file)
      (lambda (music)
        (cond
         ;; true lyrics
-        ((music-name? music 'EventChord)
+        ((music-name? music '(EventChord LyricEvent))
          (let ((lyric-event (find-child-named music 'LyricEvent)))
            (push! (make-lyrics
                         #:text (ly:music-property lyric-event 'text)
                                                          (append (score-notes-note/rest-list last-result)
                                                                  (list rest-spec)))
                    (add! (make-score-notes #:note/rest-list (list rest-spec)) result-list))))))
-         #f)
+        (filter
+         (lambda (m)
+           (not (music-name? m '(RestEvent
+                                 NoteEvent
+                                 LyricEvent
+                                 MultiMeasureRestEvent))))
+         (ly:music-property music 'elements)))
+       ((music-name? music '(RestEvent
+                             NoteEvent
+                             LyricEvent
+                             MultiMeasureRestEvent))
+        (make-music 'EventChord
+                    'elements
+                    (cons music
+                          (ly:music-property music 'articulations))))
         ;; autobeaming change
         ((music-property? music 'autoBeaming)
          (set! autobeaming (property-value music))
          (let ((change (if (property-value music) 1 -1)))
            (set! in-slur (+ in-slur change))
            (if last-note-spec
-               (set-note-joined! last-note-spec (+ (note-joined last-note-spec) change)))))
+               (set-note-joined! last-note-spec (+ (note-joined last-note-spec) change))))
+        #t)
         ;; tempo change
         ((music-property? music 'tempoWholesPerMinute)
-         (set! *tempo-compression* (ly:moment-div *default-tempo* (property-value music))))
+         (set! *tempo-compression* (ly:moment-div *default-tempo* (property-value music)))
+        #t)
         ;; breathe
         ((music-name? music 'BreathingEvent)
          (if last-note-spec
                                                #:origin (ly:music-property music 'origin))))
                (set-note-duration! last-note-spec (* note-duration (*breathe-shortage*)))
                (add! (make-score-notes #:note/rest-list (list rest-spec)) result-list))
-             (warning music "\\\\breathe without previous note known")))
+             (warning music "\\\\breathe without previous note known"))
+        #t)
         ;; anything else
         (else
          #f))))