expressions.
* input/regression/tag-filter.ly (texidoc): new file.
* lily/parser.yy (post_event): add \tag #'symbol / \tag #'(symbol1
symbol2 .. ) etc.
* Documentation/user/refman.itely (Fingering instructions): adjust manual.
2003-08-30 Han-Wen Nienhuys <hanwen@cs.uu.nl>
+ * scm/music-functions.scm (remove-tag): filter \tagged music
+ expressions.
+
+ * input/regression/tag-filter.ly (texidoc): new file.
+
+ * lily/parser.yy (post_event): add \tag #'symbol / \tag #'(symbol1
+ symbol2 .. ) etc.
+
* scripts/convert-ly.py (FatalConversionError.conv): fingering
convert rule.
@chapter New features in 1.9 since 1.8
@itemize
+
+@item
+Each music expression can now be tagged, to make different printed
+versions from the same music expression. In the following example,
+we see two versions of a piece of music, one for the full score, and
+one with cue notes for the instrumental part:
+@example
+< \tag #'part <
+ @{ c4 f2 g @} % in the part, we have cue-notes
+ \\ R1 >
+ \tag #'score R1 % in the score: only a rest
+>
+@end example
+
+The same can be applied to articulations, texts, etc.: they are
+made by prepending
+@example
+ -\tag #@var{your-tag(s)}
+@end example
+to an articulation, for example,
+@example
+ c4-\tag #'with-fingerings -4 -\tag #'with-strings \6
+@end example
+
+This defines a note, which has a fingering and a string-number
+indication.
+
+
+
@item
Markup text (ie. general text formatting) may now be used for lyrics too.
@end lilypond
+@node Different editions from one source
+@subsection Different editions from one source
+
+The @code{\\tag} command marks music expressions with a name. These
+tagged expressions can be filtered out later. With this mechanism it
+is possible to make different versions of the same music source.
+
+In the following example, we see two versions of a piece of music, one
+for the full score, and one with cue notes for the instrumental part:
+
+@example
+ c1
+ \relative c' <
+ \tag #'part <
+ R1 \\
+ {
+ \property Voice.fontSize = #-1
+ c4_"cue" f2 g4 }
+ >
+ \tag #'score R1
+ >
+@end example
+
+The same can be applied to articulations, texts, etc.: they are
+made by prepending
+@example
+ -\tag #@var{your-tag}
+@end example
+to an articulation, for example,
+@example
+ c1-\tag #'part ^4
+@end example
+
+This defines a note with a conditional fingering indication.
+
+By applying the @code{remove-tag} function, tagged expressions can be
+filtered. For example,
+@example
+\simultaneous {
+ @var{the music}
+ \apply #(remove-tag 'score) @var{the music}
+ \apply #(remove-tag 'part) @var{the music}
+}
+@end example
+would yield
+
+@lilypondfile[notexidoc]{tag-filter.ly}
+
+The argument of the @code{\tag} command should be a symbol, or a list
+of symbols, for example,
+@example
+ \tag #'(original-part transposed-part) @dots{}
+@end example
+
+@seealso
+
+@inputfileref{input/regression,tag-filter.ly}
+
+
@node Sound output for transposing instruments
@subsection Sound output for transposing instruments
--- /dev/null
+
+\version "1.9.3"
+\header {
+
+texidoc = "The @code{\\tag} command marks music expressions with a
+name. These tagged expressions can be filtered out later. This
+mechanism can be used to make different versions of the same music. In
+this example, the top stave displays the music expression with all
+tags included. The bottom two staves are filtered: the part has cue
+notes and fingerings, but the score has not."
+
+}
+
+\paper { raggedright= ##t }
+
+common =
+\notes \relative c'' {
+
+ c1
+ \relative c' <
+ \tag #'part <
+ R1 \\
+ {
+ \property Voice.fontSize = #-1
+ c4_"cue" f2 g4 }
+ >
+ \tag #'score R1
+ >
+ c1-\tag #'part ^4
+}
+
+
+\score {
+ \notes \simultaneous {
+ \new Staff {
+ \property Staff.instrument = #"both"
+ \common
+ }
+ \new Staff {
+ \property Staff.instrument = #"part"
+ \apply #(remove-tag 'score) \common
+ }
+ \new Staff {
+ \property Staff.instrument = #"score"
+ \apply #(remove-tag 'part) \common
+ }
+ }
+}
+
+
+
+
+
{"set", SET},
{"simultaneous", SIMULTANEOUS},
{"skip", SKIP},
+ {"tag", TAG},
{"tempo", TEMPO},
{"time", TIME_T},
{"times", TIMES},
#define yyerror THIS->parser_error
+/*
+ Add symbols to the TAGS field of a music object.
+*/
+void
+tag_music (Music*m, SCM tag, Input ip)
+{
+ SCM tags = m->get_mus_property ("tags");
+ if (gh_symbol_p (tag))
+ tags = scm_cons (tag, tags);
+ else if (gh_list_p (tag))
+ tags = gh_append2 (tag, tags);
+ else
+ ip.warning (_("Tag must be symbol or list of symbols."));
+
+ m->set_mus_property ("tags", tags);
+}
%token SIMULTANEOUS
%token SKIP
%token SPANREQUEST
+%token TAG
%token TEMPO
%token TIMES
%token TIME_T
%type <scm> steno_duration optional_notemode_duration multiplied_duration
%type <scm> verbose_duration
-%type <scm> post_events
+%type <scm> post_events
%type <music> gen_text_def direction_less_event direction_reqd_event
%type <scm> steno_pitch pitch absolute_pitch pitch_also_in_chords
%type <scm> explicit_pitch steno_tonic_pitch
%type <scm> Music_list
%type <outputdef> music_output_def_body
%type <music> shorthand_command_req
-%type <music> post_event
+%type <music> post_event tagged_post_event
%type <music> command_req verbose_command_req
%type <music> extender_req
%type <music> hyphen_req
}
| relative_music { $$ = $1; }
| re_rhythmed_music { $$ = $1; }
- | part_combined_music { $$ = $1; }
+ | part_combined_music { $$ = $1; }
+ | TAG embedded_scm Music {
+ tag_music ($3, $2, THIS->here_input ());
+ $$ = $3;
+ }
;
relative_music:
$$ = gh_cons ($2->self_scm(), $$);
scm_gc_unprotect_object ($2->self_scm());
}
+ | post_events tagged_post_event {
+ $2 -> set_spot (THIS->here_input ());
+ $$ = scm_cons ($2->self_scm(), $$);
+ scm_gc_unprotect_object ($2->self_scm());
+ }
;
+tagged_post_event:
+ '-' TAG embedded_scm post_event {
+ tag_music ($4, $3, THIS->here_input ());
+ $$ = $4;
+ }
+ ;
post_event:
direction_less_event {
$$ = $1;
}
| script_dir direction_reqd_event {
- $2->set_mus_property ("direction", gh_int2scm ($1));
+ if ($1)
+ $2->set_mus_property ("direction", gh_int2scm ($1));
$$ = $2;
}
| script_dir direction_less_event {
- $2->set_mus_property ("direction", gh_int2scm ($1));
+ if ($1)
+ $2->set_mus_property ("direction", gh_int2scm ($1));
$$ = $2;
}
| string_number_event
(music-property-description 'denominator integer? "denominator in a time signature")
(music-property-description 'digit integer? "digit for fingering")
(music-property-description 'direction ly:dir? "Print this up or down?")
+(music-property-description 'tags list? "List of symbols that for denoting extra details,
+eg. @code{\\tag #'part ...} could tag a piece of music as only being active in a part.")
+
+
(music-property-description 'text-type symbol? "Particular type of text script (eg. finger, dynamic).")
(music-property-description 'tempo-unit ly:duration? "The unit for the metronome count.")
(music-property-description 'tonic ly:pitch? "Base of the scale")
-
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define-public (music-map function music)
(function music)
))
+(define-public (music-filter pred? music)
+ "Filter out music expressions that do not satisfy PRED."
+
+ (define (inner-music-filter pred? music)
+ "Recursive function."
+ (let* ((es (ly:get-mus-property music 'elements))
+ (e (ly:get-mus-property music 'element))
+ (as (ly:get-mus-property music 'articulations))
+ (filtered-as (filter ly:music? (map (lambda (y) (inner-music-filter pred? y)) as)))
+ (filtered-e (if (ly:music? e)
+ (inner-music-filter pred? e)
+ e))
+ (filtered-es (filter ly:music? (map (lambda (y) (inner-music-filter pred? y)) es)))
+ )
+
+ (ly:set-mus-property! music 'element filtered-e)
+ (ly:set-mus-property! music 'elements filtered-es)
+ (ly:set-mus-property! music 'articulations filtered-as)
+
+ ;; if filtering emptied the expression, we remove it completely.
+ (if (or (pred? music)
+ (and (eq? filtered-es '()) (not (ly:music? e))
+ (or (not (eq? es '()))
+ (ly:music? e))))
+ (set! music '()))
+
+ music))
+
+ (set! music (inner-music-filter pred? music))
+ (if (ly:music? music)
+ music
+ (make-music-by-name 'Music) ;must return music.
+ ))
+
+(define-public (remove-tag tag)
+ (lambda (mus)
+ (music-filter
+ (lambda (m)
+ (let* ((tags (ly:get-mus-property m 'tags))
+ (res (memq tag tags)))
+ res)) mus)))
+
(define-public (display-music music)
"Display music, not done with music-map for clarity of presentation."
(display music)