+2004-02-12 Han-Wen Nienhuys <hanwen@xs4all.nl>
+
+ * lily/chord-name.cc: remove props chord, bass, inversion.
+
+ * Documentation/user/appendices.itely: add Scheme functions,
+ context-properties and layout properties to manual.
+
+ * scm/part-combiner.scm (determine-split-list): include rests in a
+ solo1/2 sequence.
+
+ * lily/new-part-combine-iterator.cc (substitute_both): new
+ function.
+ (class New_pc_iterator): add separate Voice=solo context, fixes
+ autobeams going from chords to solo.
+
2004-02-11 Jan Nieuwenhuizen <janneke@gnu.org>
* Documentation/user/invoking.itexi (Editor support): Fix typo.
# Generic rule using % twice not possible?
# $(outdir)/%/%.html: $(outdir)/%.texi
+$(outdir)/lilypond.texi: $(outdir)/lilypond-internals.texi
+$(outdir)/lilypond.nexi: $(outdir)/lilypond-internals.texi
+
+
$(outdir)/lilypond/lilypond.html: $(outdir)/lilypond.texi
mkdir -p $(dir $@)
$(MAKEINFO) -I$(outdir) --output=$(outdir)/lilypond --html $<
@menu
* Chord name chart::
* MIDI instruments::
-* The Feta font::
+* The Feta font::
+* Scheme functions::
+* Layout property overview::
+* Context property overview::
@end menu
@lilypondfile[noindent]{parmesan16list.ly}
+@include scheme-functions.tely
+
+@include context-properties.tely
+
+@include layout-properties.tely
+
+
@tab
@lilypond[fragment,relative=1]
\notes { g'4 g }
- \lyricsto "" \new LyricsVoice \lyrics { twin -- kle }
+ \lyricsto "" \new Lyrics \lyrics { twin -- kle }
@end lilypond
@item @code{\chords @{ c:dim f:maj7 @}}
These use mixed-caps naming: @code{autoBeamSettings},
@code{ignoreMelismata}. They are assigned as follows:
@example
- \property LyricsVoice.ignoreMelismata = ...
+ \property Lyrics.ignoreMelismata = ...
@end example
@item Layout properties
\score { <<
\context ChordNames \chords { c2 c f2 c }
\notes \relative c' { \time 2/4 c4 c g'4 g a4 a g2 }
- \context LyricsVoice \lyrics { twin4 kle twin kle lit tle star2 } >> }
+ \context Lyrics \lyrics { twin4 kle twin kle lit tle star2 } >> }
@end lilypond
Polyphonic notation and piano music can also be printed. The following
@lilypond[raggedright]
\score {
- \context LyricsVoice \notes {
+ \context Lyrics \notes {
\property Score.RehearsalMark \set #'self-alignment-X = #LEFT
\mark #(ly:export (string-append
"(For LilyPond version " (lilypond-version) ")"))
\context Staff \notes\relative c'' {
gis1 s s gisis s s ges s s geses s s g!
}
-\context LyricsVoice \lyrics {
+\context Lyrics \lyrics {
\property Lyrics . LyricText \set #'self-alignment-X = #-1
"sharp " "db. sharp " "flat " "db. flat " natural
}
\clef tenor c s s
\clef baritone c s s
}
-\context LyricsVoice \lyrics {
+\context Lyrics \lyrics {
\property Lyrics . LyricText \override #'self-alignment-X = #-1
"Soprano " "Mezzosoprano " "Alto " "Tenor " Baritone
}
<g b d f> s s
<g b d f a> s s
}
-\context LyricsVoice \lyrics{
+\context Lyrics \lyrics{
\property Lyrics . LyricText \set #'self-alignment-X = #-1
"major " "minor " "diminished " "augmented "
"seventh-chord " "ninth-chord "
\property Voice.TextScript \set #'padding = #-4
e^"~~ S" f g a b^"~~ S" c
}
- \context LyricsVoice \lyrics {
+ \context Lyrics \lyrics {
Ionian
}
@end lilypond
\property Voice.TextScript \set #'padding = #-4
e^"~~ S" f g a b^"~~ S" c d
}
- \context LyricsVoice \lyrics {
+ \context Lyrics \lyrics {
Dorian
}
@end lilypond
\property Voice.TextScript \set #'padding = #-4
e1^"~~ S" f g a b^"~~ S" c d e
}
- \context LyricsVoice \lyrics {
+ \context Lyrics \lyrics {
Phrygian
}
@end lilypond
\property Voice.TextScript \set #'padding = #-4
b^"~~ S" c d e^"~~ S" f
}
- \context LyricsVoice \lyrics {
+ \context Lyrics \lyrics {
Lydian
}
@end lilypond
g1 a
\property Voice.TextScript \set #'padding = #-4
b^"~~ S" c d e^"~~ S" f g }
- \context LyricsVoice \lyrics {
+ \context Lyrics \lyrics {
Mixolydian
}
@end lilypond
\property Voice.TextScript \set #'padding = #-4
b^"~~ S" c d e^"~~ S" f g a
}
- \context LyricsVoice \lyrics {
+ \context Lyrics \lyrics {
Aeolian
}
@end lilypond
\property Voice.TextScript \set #'padding = #-4
e^"~~ S" f g a b^"~~ S" c
}
- \context LyricsVoice \lyrics {
+ \context Lyrics \lyrics {
Major
}
@end lilypond
\property Voice.TextScript \set #'padding = #-4
b^"~~ S" c d e^"~~ S" f g a
}
- \context LyricsVoice \lyrics {
+ \context Lyrics \lyrics {
"ancient minor"
}
@end lilypond
\property Voice.TextScript \set #'padding = #-4
b^"~~ S" c d e^"~~ S" f!^"~~ A" gis^"~~ S" a
}
- \context LyricsVoice \lyrics {
+ \context Lyrics \lyrics {
"Harmonic minor"
}
@end lilypond
b^"~~ S" c d e fis gis^"~~ S"
a g! f!^"~~ S" e d c^"~~ S" b a
}
- \context LyricsVoice \lyrics {
+ \context Lyrics \lyrics {
"Melodic minor"
}
@end lilypond
\context Staff \notes\relative c'' {
gis1 s s as s s <des g,!> s s <cis g!> s s
}
-\context LyricsVoice \lyrics {
+\context Lyrics \lyrics {
\property Lyrics . LyricText \set #'self-alignment-X = #-1
"g sharp " "a flat " "dim fifth " "augm fourth"
}
\clef "F_8"
f1
}
-\context LyricsVoice \lyrics {
+\context Lyrics \lyrics {
\property Lyrics . LyricText \set #'self-alignment-X = #-1
"baritone "
"bass "
\context Voice \notes\relative c'' {
<g e c >1 < a f d > < b g e >
<c a f > < d b g > < e c a > < f d b > }
-\context LyricsVoice \lyrics { T Sp Dp S D Tp "D{\\kern-5pt}$\\mid$" }
+\context Lyrics \lyrics { T Sp Dp S D Tp "D{\\kern-5pt}$\\mid$" }
@end lilypond
@aitem{G}
\clef "G_8"
g s s
}
-\context LyricsVoice \lyrics {
+\context Lyrics \lyrics {
\property Lyrics . LyricText \set #'self-alignment-X = #-1
"french violin clef "
"violin clef "
\partial 4 c4 | f, g c2
\bar "|."
}
- \context LyricsVoice \lyrics {
+ \context Lyrics \lyrics {
T S D T
}
>>
< g b! >^"major" s
< g bis >^"augm" s
}
-\context LyricsVoice \lyrics {
+\context Lyrics \lyrics {
"unisone " "second " "second " "second "
"third " "third " "third " "third "
}
< g e'! >^"major" s
< g eis' >^"augm" s
}
-\context LyricsVoice \lyrics {
+\context Lyrics \lyrics {
"fourth " "fourth " "fifth " "fifth "
"sixth " "sixth " "sixth " "sixth "
}
< g bes' >^"minor" s
< g b'! >^"major" s
}
-\context LyricsVoice \lyrics {
+\context Lyrics \lyrics {
"seventh " "seventh " "seventh " "octave "
"none " "none " "decime " "decime "
}
c4-.-( d-. e-.-) \bar "||"
c4-. d-. e-. \bar "||"
}
-\context LyricsVoice \lyrics {
+\context Lyrics \lyrics {
% \property Lyrics . LyricText \set #'font-style = #'large
a
b "" ""
\context Staff \notes\relative c' {
c1 d e f g a b c
}
-\context LyricsVoice \lyrics {
+\context Lyrics \lyrics {
<< { I II III IV V VI VII I }
{ T "" "" S D } >>
}
\key es \major
es8 c d bes c as bes16 as g f | es4
}
- \context LyricsVoice \lyrics {
- \property LyricsVoice . VerticalAlign \override #'threshold = #'(6 . 12)
+ \context Lyrics \lyrics {
+ \property Lyrics . VerticalAlign \override #'threshold = #'(6 . 12)
<< { "" "6" "" "4" "" "6" "" "" "6" "4" }
{ "" "" "" "2" "" "" "" "" "" "2" } >>
}
Like notes, lyrics are also a form of music, but they must not be
printed on a staff, which is the default way to print music. To print
-them as lyrics, they must be marked with @code{ \new LyricsVoice}:
+them as lyrics, they must be marked with @code{ \new Lyrics}:
@example
- \new LyricsVoice \lyrics @{ I want to break free @}
+ \new Lyrics \lyrics @{ I want to break free @}
@end example
The melody for this song is as follows:
The lyrics can be set to these notes, combining both with the
@code{\lyricsto} keyword:
@example
- \lyricsto "@var{name}" \new LyricsVoice @dots{}
+ \lyricsto "@var{name}" \new Lyrics @dots{}
@end example
where @var{name} identifies to which melody the lyrics should be
aligned. In this case, there is only one melody, so we can leave it
c8
\times 2/3 { f g g } \times 2/3 { g4( a2) }
}
- \lyricsto "" \new LyricsVoice \lyrics { I want to break free }
+ \lyricsto "" \new Lyrics \lyrics { I want to break free }
>>
\paper{ }
}
\partial 8
c8
\times 2/3 { f g g } \times 2/3 { g4( a2) } }
- \lyricsto "" \new LyricsVoice \lyrics { I want to break free __ }
+ \lyricsto "" \new Lyrics \lyrics { I want to break free __ }
>>
\paper{ }
}
<<
\context ChordNames \chords @{ @emph{chords} @}
\notes @emph{the melody}
- \lyricsto "" \new LyricsVoice \lyrics @{ @emph{the text} @}
+ \lyricsto "" \new Lyrics \lyrics @{ @emph{the text} @}
>>
\paper @{ @}
@}
\partial 8
c8
\times 2/3 { f g g } \times 2/3 { g4( a2) } }
- \new LyricsVoice \lyricsto "" \lyrics { I want to break free __ }
+ \new Lyrics \lyricsto "" \lyrics { I want to break free __ }
>>
\paper{ raggedright = ##t }
}
ADD_INTERFACE (Chord_name, "chord-name-interface",
"generate a chord name",
- "pitches chord style inversion bass begin-of-line-visible");
+ "begin-of-line-visible");
Status state_;
Status playing_state_;
+ /*
+ TODO: this is getting of hand...
+ */
Interpretation_context_handle one_;
Interpretation_context_handle two_;
Interpretation_context_handle null_;
Interpretation_context_handle shared_;
+ Interpretation_context_handle solo_;
+
+ void substitute_both (Translator_group * to1,
+ Translator_group * to2);
void kill_mmrest (Translator_group*);
void chords_together ();
if (second_iter_)
second_iter_->quit();
+ null_.set_translator (0);
one_ .set_translator (0);
two_.set_translator (0);
shared_.set_translator (0);
+ solo_.set_translator (0);
}
-
-
Moment
New_pc_iterator::pending_moment () const
{
{
playing_state_ = TOGETHER;
state_ = TOGETHER;
- first_iter_->substitute_outlet (one_.get_outlet (), shared_.get_outlet ());
- first_iter_->substitute_outlet (null_.get_outlet (), shared_.get_outlet ());
- second_iter_->substitute_outlet (two_.get_outlet (), shared_.get_outlet ());
- second_iter_->substitute_outlet (null_.get_outlet (), shared_.get_outlet ());
+
+ substitute_both (shared_.get_outlet (), shared_.get_outlet());
}
}
else
{
state_ = SOLO1;
- first_iter_->substitute_outlet (null_.get_outlet (), shared_.get_outlet ());
- first_iter_->substitute_outlet (one_.get_outlet (), shared_.get_outlet ());
-
- second_iter_->substitute_outlet (two_.get_outlet (), null_.get_outlet ());
- second_iter_->substitute_outlet (shared_.get_outlet (), null_.get_outlet ());
+ substitute_both (solo_.get_outlet (),
+ null_.get_outlet ());
+
kill_mmrest (two_.get_outlet ());
kill_mmrest (shared_.get_outlet ());
playing_state_ = SOLO1;
}
}
+
+void
+New_pc_iterator::substitute_both (Translator_group * to1,
+ Translator_group * to2)
+{
+ Translator_group *tos[] = {to1,to2};
+ Music_iterator *mis[] = {first_iter_, second_iter_};
+ Interpretation_context_handle *hs[] = {
+ &null_,
+ &one_, &two_,
+ &shared_, &solo_,
+ 0
+ };
+
+ for (int i = 0; i < 2 ; i++)
+ {
+ for (int j = 0; hs[j]; j++)
+ if (hs[j]->get_outlet () != tos[i])
+ mis[i]->substitute_outlet (hs[j]->get_outlet (), tos[i]);
+ }
+
+ for (int j = 0; hs[j]; j++)
+ {
+ Translator_group* t = hs[j]->get_outlet ();
+ if (t != to1 && t != to2)
+ kill_mmrest (t);
+ }
+}
+
+
void
New_pc_iterator::unisono (bool silent)
{
return;
else
{
+ substitute_both (shared_.get_outlet (), null_.get_outlet ());
- first_iter_->substitute_outlet (null_.get_outlet (), shared_.get_outlet ());
- first_iter_->substitute_outlet (one_.get_outlet (), shared_.get_outlet ());
-
- second_iter_->substitute_outlet (two_.get_outlet (), null_.get_outlet ());
- second_iter_->substitute_outlet (shared_.get_outlet (), null_.get_outlet ());
kill_mmrest (two_.get_outlet ());
kill_mmrest (shared_.get_outlet ());
{
state_ = SOLO2;
- second_iter_->substitute_outlet (null_.get_outlet (), shared_.get_outlet ());
- second_iter_->substitute_outlet (two_.get_outlet (), shared_.get_outlet ());
-
- first_iter_->substitute_outlet (one_.get_outlet (), null_.get_outlet ());
- first_iter_->substitute_outlet (shared_.get_outlet (), null_.get_outlet ());
- kill_mmrest (one_.get_outlet ());
- kill_mmrest (shared_.get_outlet ());
+ substitute_both (null_.get_outlet (), solo_.get_outlet ());
if (playing_state_ != SOLO2)
{
else
{
state_ = APART;
-
- first_iter_->substitute_outlet (null_.get_outlet (), one_.get_outlet ());
- first_iter_->substitute_outlet (shared_.get_outlet (), one_.get_outlet ());
-
- second_iter_->substitute_outlet (null_.get_outlet (), two_.get_outlet ());
- second_iter_->substitute_outlet (shared_.get_outlet (), two_.get_outlet ()); }
+ substitute_both (one_.get_outlet (), two_.get_outlet ());
+ }
}
+
void
New_pc_iterator::construct_children ()
{
= get_outlet ()->find_create_translator (ly_symbol2scm ("Voice"),
"shared",props);
- shared_ .set_translator (tr);
+ shared_.set_translator (tr);
+
+ /*
+ If we don't, we get a new staff for every Voice.
+ */
set_translator (tr);
+
+ Translator_group *solo_tr
+ = get_outlet ()->find_create_translator (ly_symbol2scm ("Voice"),
+ "solo",props);
+
+ solo_ .set_translator (solo_tr);
+
Translator_group *null
= get_outlet ()->find_create_translator (ly_symbol2scm ("Devnull"),
"", SCM_EOL);
)
;; put this in an alist?
-(define
+(define-public
all-user-grob-properties
(map
(base-shortest-duration ,ly:moment?
"Spacing is based on the shortest notes in a piece. Normally, pieces are spaced as if notes at least as short as this are present.")
(baseline-skip ,ly:dimension? "Baseline skip to use for multiple lines of text.")
- (bass ,list? " musical-pitch, optional.")
(beam-thickness ,ly:dimension? "thickness, measured in staffspace.")
(beam-width ,ly:dimension? "width of the tremolo sign.")
(beamed-lengths ,list? "list of stem lengths given beam multiplicity .")
(force-hshift ,number? "amount of collision_note_width that
overides automatic collision settings. This is used by
-@ref{note-collision-interface}.")
+@internalsref{note-collision-interface}.")
(fraction ,number-pair? "fraction of a time signature.")
(french-beaming ,boolean? "Use French
(grow-direction ,ly:dir? "crescendo or ,decrescendo?.")
(hair-thickness ,number? "thickness, measured in linethickness.")
- (head-pair ,pair? "Pair of grob pointers, pointing to the two heads of the tie.")
(height ,ly:dimension? "in staffspace.")
(height-limit ,ly:dimension? "Maximum slur height: the longer the
(horizontal-shift ,integer? "integer that identifies ranking of
note-column for horizontal shifting. This is used by
-@ref{note-collision-interface}.")
+@internalsref{note-collision-interface}.")
(ideal-distances ,list? "(OBJ . (DIST . STRENGTH)) pairs.")
(inclinatum ,boolean? "is this neume an ,inclinatum?.")
(interfaces ,list? "list of symbols indicating the interfaces supported by this object. Is initialized from the @code{meta} field.")
- (inversion ,list? " musical-pitch, optional.")
(join-heads ,boolean? "Whether to join the noteheads of an ambitus grob with a vertical line.")
(kern ,ly:dimension? "amount of extra white
space to add. For barline, space after a thick line.")
noteheads in collisions, even if they have different note heads. The
smaller of the two heads will be rendered invisible. This used
polyphonic guitar notation. The value of this setting is used by
-@ref{note-collision-interface} .")
+@internalsref{note-collision-interface} .")
(merge-differently-dotted ,boolean? " Merge
noteheads in collisions, even if they have a different number of
dots. This normal notation for some types of polyphonic music. The
-value of this setting is used by @ref{note-collision-interface} .")
+value of this setting is used by @internalsref{note-collision-interface} .")
(meta ,list? "Contains meta information. It is an alist with the
entries @code{name} and @code{interfaces}.")
(pitch-max ,ly:pitch? "FIXME, JUNKME")
(pitch-min ,ly:pitch? "FIXME, JUNKME")
- (pitches ,list? "list of musical-pitch.")
(quilisma ,boolean? "is this neume a ,quilisma?.")
(positions ,pair?
This is used in spacing. Making this larger will make the score tighter.")
(shortest-duration-space ,ly:dimension? "Start
with this much space for the shortest duration. This is explessed in @code{spacing-increment} as unit. See also
-@ref{spacing-spanner-interface}.")
+@internalsref{spacing-spanner-interface}.")
(shortest-playing-duration ,ly:moment? "duration of the shortest playing in that column.")
(shortest-starter-duration ,ly:moment? "duration of the shortest notes that starts exactly in this column.")
(side-relative-direction ,ly:dir? "if set: get the direction from a different object, and multiply by this.")
(spacing-increment ,number? "Add this much space for a doubled
duration. Typically, the width of a note head. See also
-@ref{spacing-spanner-interface}.")
+@internalsref{spacing-spanner-interface}.")
(spacing-procedure ,procedure? "procedure taking grob as
argument. This is called after before-line-breaking-callback, but
)
-(define all-internal-grob-properties
+(define-public all-internal-grob-properties
(map
(lambda (x)
(apply define-internal-grob-property x))
;; TODO: use interface for this!
(chord-tremolo ,boolean? "if set, this beam is a tremolo. ")
- (chord ,pair? "?")
- (begin-of-line-visible ,boolean? "?")
- (quant-score ,number? "Beam quanting score
--- can be stored for debugging")
+ (begin-of-line-visible ,boolean? "Used for marking ChordNames that should only show changes.")
+ (head-pair ,pair? "Pair of grob pointers, pointing to the two heads of the tie.")
+ (quant-score ,number? "Beam quanting score -- can be stored for
+debugging")
(least-squares-dy ,number?
"ideal beam slope, without damping.")
(ligature-primitive-callback ,procedure? "callback that brews ligature head.")
(append
all-internal-grob-properties
all-user-grob-properties))
+
symbol
)
-(define all-user-translation-properties
+(define-public all-user-translation-properties
(map
(lambda (x)
(apply translator-property-description x))
highest pitch on the instrument. This used by the automatic string
selector for tab notation.")
- (ignoreMelismata ,boolean? "Ignore melismata for this @ref{Lyrics}.")
+ (ignoreMelismata ,boolean? "Ignore melismata for this @internalsref{Lyrics}.")
(instr ,markup? "see @code{instrument}")
(instrument ,markup? "The name to print left of a staff. The
@end example
This will create a start-repeat bar in this staff only.
-Valid values are described in @ref{bar-line-interface}.
+Valid values are described in @internalsref{bar-line-interface}.
")
)))
-(define all-internal-translation-properties
+(define-public all-internal-translation-properties
(map
(lambda (x)
(set-object-property! (car x) 'internal-translation #t)
)
))
-(define all-translation-properties
+(define-public all-translation-properties
(append all-user-translation-properties
all-internal-translation-properties))
(map interface-doc interface-description-alist)
))
-(define (all-backend-properties-doc)
+(define (backend-properties-doc-string lst)
(let*
(
- (ps (sort (map symbol->string all-backend-properties) string<?))
+ (ps (sort (map symbol->string lst) string<?))
(descs (map (lambda (prop)
(document-property (string->symbol prop) 'backend #f))
ps))
(texi (description-list->texi descs))
)
+ texi))
+
+(define (all-backend-properties-doc)
(make <texi-node>
#:name "All backend properties"
#:desc "All grob properties in a big list"
- #:text texi)
- ))
+ #:text (backend-properties-doc-string all-backend-properties)))
+
;(dump-node (grob-doc (cdadr all-grob-descriptions)) (current-output-port) 0 )
(define (backend-doc-node)
(make <texi-node>
#:children
(map engraver-doc all-engravers-list)))
-(define (all-translation-properties-doc)
-
+(define (translation-properties-doc-string lst)
(let*
- (
- (ps (sort (map symbol->string all-translation-properties) string<?))
+ ((ps (sort (map symbol->string lst) string<?))
(sortedsyms (map string->symbol ps))
(propdescs
(map
(lambda (x) (document-property x 'translation #f))
sortedsyms))
- (texi (description-list->texi propdescs))
- )
+ (texi (description-list->texi propdescs)))
+ texi
+ ))
+(define (all-translation-properties-doc)
(make <texi-node>
#:name "Context properties"
- #:desc "All context properties"
- #:text texi)
- ))
+ #:desc "All context properties"
+ #:text (translation-properties-doc-string all-translation-properties))
+ )
;(dump-node (all-contexts-doc) (current-output-port) 0 )
;;;;;;;;;;;;;;;; TODO : make modules of these!
;;;;;;;;;;;;;;;;
+; todo: naming: grob vs. layout property
+
(define load-files '("documentation-lib.scm"
"document-functions.scm"
"document-translation.scm"
@end ifinfo
+@macro internalsref{NAME}
+@ref{\\NAME\\}
+@end macro
+
+@ifhtml
+
+@macro inputfileref{DIR,NAME}
+@uref{../../../../\\DIR\\/out-www/collated-files.html#\\NAME\\,@file{\\DIR\\/\\NAME\\}}@c
+@end macro
+
+@end ifhtml
+
+@ifinfo
+
+@macro inputfileref{DIR,NAME}
+@file{\\DIR\\/\\NAME\\}
+@end macro
+
+@end ifinfo
+
+@iftex
+@macro inputfileref{DIR,NAME}@c
+@file{\\DIR\\/\\NAME\\}@c
+@end macro
+@end iftex
+
+
+
@ignore
@omftitle LilyPond internals
@omfcreator Han-Wen Nienhuys and Jan Nieuwenhuizen
(dump-node top-node out-port 0)
(newline (current-error-port))
+
+
+(dump-node (all-scheme-functions-doc)
+ (open-output-file "scheme-functions.tely")
+ 2)
+
+(dump-node
+ (make <texi-node>
+ #:name "Layout property overview"
+ #:desc "All user serviceable layout properties"
+ #:text (backend-properties-doc-string all-user-grob-properties))
+
+ (open-output-file "layout-properties.tely")
+ 2)
+
+(dump-node
+ (make <texi-node>
+ #:name "Context property overview"
+ #:desc "All user serviceable context properties"
+ #:text (translation-properties-doc-string all-user-translation-properties))
+
+ (open-output-file "context-properties.tely")
+ 2)
+
+
(,boolean? . "boolean")
(,char? . "char")
(,grob-list? . "list of grobs")
+ (,hash-table? . "hash table")
(,input-port? . "input port")
(,integer? . "integer")
(,list? . "list")
(,ly:dimension? . "dimension, in staff space")
(,ly:dir? . "direction")
(,ly:duration? . "duration")
- (,ly:grob? . "grob (GRaphical OBject)")
+ (,ly:grob? . "layout object")
(,ly:input-location? . "input location")
(,ly:input-location? . "input location")
(,ly:moment? . "moment")
(define-class <Split-state> ()
(configuration #:init-value '() #:accessor configuration)
(when-moment #:accessor when #:init-keyword #:when)
+
+ ; voice-states are states starting with the Split-state or later
+ ;
(is #:init-keyword #:voice-states #:accessor voice-states)
(synced #:init-keyword #:synced #:init-value #f #:getter synced?) )
-
-
(define-method (write (x <Split-state> ) f)
(display (when x) f)
(display " = " f)
))
(define (put-range x a b)
- (display (list "put range " x a b "\n"))
+; (display (list "put range " x a b "\n"))
(do
((i a (1+ i)))
((> i b) b)
(set! (configuration (vector-ref result i)) x)
))
+
(define (put x)
-
- (display (list "putting " x "\n"))
- (set! (configuration (vector-ref result ri)) x))
-
+; (display (list "putting " x "\n"))
+
+ (set! (configuration (vector-ref result ri)) x))
+
+ (define (current-voice-state now-state voice-num)
+ (define vs ((if (= 1 voice-num) car cdr)
+ (voice-states now-state) ) )
+ (if (equal? (when now-state) (when vs))
+ vs
+ (previous-voice-state vs)
+ ))
+
(define (try-solo type start-idx current-idx)
"Find a maximum stretch that can be marked as solo. Only set
the mark when there are no spanners active."
(if (< current-idx (vector-length result))
(let*
((now-state (vector-ref result current-idx))
- (solo-state ((if (equal? type 'solo1) car cdr) (voice-states now-state)))
- (silent-state ((if (equal? type 'solo1) cdr car) (voice-states now-state)))
+ (solo-state (current-voice-state now-state (if (equal? type 'solo1) 1 2)))
+
+ (silent-state (current-voice-state now-state (if (equal? type 'solo1) 2 1)))
(silent-notes (if silent-state (note-events silent-state) '()))
(solo-notes (if solo-state (note-events solo-state) '()))
+
(soln (length solo-notes))
(siln (length silent-notes)))
+ (display (list "trying " type " at " (when now-state) solo-state silent-state "\n"))
(cond
((not (equal? (configuration now-state) 'apart))
current-idx)
- ((= soln 0) current-idx)
- ((> siln 0) current-idx)
- ((null? (span-state solo-state))
+ ((> siln 0) start-idx)
+
+ ((and
+ ;
+ ; This includes rests. This isn't a problem: long rests
+ ; will be shared with the silent voice, and be marked
+ ; as unisilence. Therefore, long rests won't
+ ; accidentally be part of a solo.
+ ;
+ (null? (span-state solo-state)))
(put-range type start-idx current-idx)
- current-idx)
+ (try-solo type (1+ current-idx) (1+ current-idx)))
(else
(try-solo type start-idx (1+ current-idx)))
))
- (1- current-idx)))
-
+ start-idx)) ; try-solo
+
+
(define (analyse-moment ri)
- "Analyse 'apart starting at RI. Return next index. "
+ "Analyse 'apart starting at RI. Return next index. "
(let*
((now-state (vector-ref result ri))
- (vs1 (car (voice-states now-state)))
- (vs2 (cdr (voice-states now-state)))
+ (vs1 (current-voice-state now-state 1))
+ (vs2 (current-voice-state now-state 2))
+; (vs1 (car (voice-states now-state)))
+; (vs2 (cdr (voice-states now-state)))
(notes1 (if vs1 (note-events vs1) '()))
(notes2 (if vs2 (note-events vs2) '()))
(n1 (length notes1))
(n2 (length notes2)) )
- (display (list "analysing " (when now-state)
- "\n1= " vs1
- "\n2= " vs2
- "\n"))
+ (display (list "analyzing step " ri " moment " (when now-state) vs1 vs2 "\n"))
+
- (cond
- ((and (= n1 0) (= n2 0))
- (put 'apart-silence)
- (1+ ri) )
-
- ((and (= n2 0)
- (equal? (when vs1) (when now-state))
- (null? (previous-span-state vs1)))
- (try-solo 'solo1 ri ri))
- ((and (= n1 0)
- (equal? (when vs2) (when now-state))
- (null? (previous-span-state vs2)))
- (try-solo 'solo2 ri ri))
- (else
- (1+ ri))
- )))
+ (max ; we should always increase.
+ (cond
+ ((and (= n1 0) (= n2 0))
+ (put 'apart-silence)
+ (1+ ri) )
+
+ ((and (= n2 0)
+ (equal? (when vs1) (when now-state))
+ (null? (previous-span-state vs1)))
+ (try-solo 'solo1 ri ri))
+ ((and (= n1 0)
+ (equal? (when vs2) (when now-state))
+ (null? (previous-span-state vs2)))
+ (try-solo 'solo2 ri ri))
+ (else (1+ ri) ))
+ (1+ ri))
+ )) ; analyse-moment
(if (< ri (vector-length result))
(if (equal? (configuration (vector-ref result ri)) 'apart)
(analyse-solo12 (analyse-moment ri))
- (analyse-solo12 (1+ ri)))) )
+ (analyse-solo12 (1+ ri)))) ) ; analyse-solo12
(analyse-spanner-states voice-state-vec1)
(analyse-time-step 0)
; (display result)
-; (analyse-a2 0)
+ (analyse-a2 0)
; (display result)
(analyse-solo12 0)
(display result)
(lambda (x) (cons (when x) (configuration x)))
(vector->list result)))
- (if pc-debug (display result))
+; (if pc-debug (display result))
result))