|
|
DescriptionIssue 754: don't transpose generic property-setting music commands
The actual issue was that
\transpose c e { \transposition bes ... }
created a Midi corresponding to an instrument using a transposition of
ges, leaving the Midi unchanged. Making the generic property-setting
commands (\set and \override) impervious to transposition will also
keep \transpose from tampering with user-set values.
This is particularly important since the pitch data type in LilyPond
is also being used for signifying intervals or pitch differences
rather than absolute pitches.
Patch Set 1 #Patch Set 2 : Cherry-pick DOC change from other approach. #
Total comments: 2
MessagesTotal messages: 11
Cherry-pick DOC change from other approach.
Sign in to reply to this message.
Yesterday's patch was better. The 'untransposable property is more closely related to the source of the events (\transposition or \instrumentSwitch) than to the event type (override or propertySet). https://codereview.appspot.com/7303057/diff/2001/scm/define-music-types.scm File scm/define-music-types.scm (right): https://codereview.appspot.com/7303057/diff/2001/scm/define-music-types.scm#n... scm/define-music-types.scm:379: (untransposable . #t) Well, not every Grob property that is a pitch is untransposable. The second pitch in a pitchedTrill, for example, should be transposed along with the first pitch. Do we need to remember to avoid \override on those that are transposable? https://codereview.appspot.com/7303057/diff/2001/scm/define-music-types.scm#n... scm/define-music-types.scm:446: (untransposable . #t) Not every context property that is a pitch is untransposable. The tonic of the Staff, for example.
Sign in to reply to this message.
On 2013/02/08 04:46:27, Keith wrote: > Yesterday's patch was better. I beg to differ. It did not address instrument definitions, or manual settings of instrumentTransposition. > The 'untransposable property is more closely related to the source of the events > (\transposition or \instrumentSwitch) than to the event type (override or > propertySet). To be perfectly clear about this: untransposability is related to individual properties. instrumentTransposition should be untransposable no matter how it is being set. One problem is that "untransposable" is a very coarse tool compared to, say, the callback system for \relative. > https://codereview.appspot.com/7303057/diff/2001/scm/define-music-types.scm > File scm/define-music-types.scm (right): > > https://codereview.appspot.com/7303057/diff/2001/scm/define-music-types.scm#n... > scm/define-music-types.scm:379: (untransposable . #t) > Well, not every Grob property that is a pitch is untransposable. The second > pitch in a pitchedTrill, for example, should be transposed along with the first > pitch. I don't see that there is any interface for pitched Trills that would ride on explicit property setting commands. And don't you think it strange that if you use \override for setting a property, the pitches get transposed, whereas if you use \tweak for setting a property, the pitch does not get transposed? Where is the logic with that? > Do we need to remember to avoid \override on those that are transposable? I don't see anybody using \override here on pitched trills. And yes: it would appear that for things sufficiently sophisticated to require transposition, one would want an own music type. > https://codereview.appspot.com/7303057/diff/2001/scm/define-music-types.scm#n... > scm/define-music-types.scm:446: (untransposable . #t) > Not every context property that is a pitch is untransposable. The tonic of the > Staff, for example. The tonic of the Staff is set via KeyChangeEvent, not via PropertySet. It is not manipulated independently from the scale.
Sign in to reply to this message.
On 2013/02/08 08:40:29, dak wrote: > On 2013/02/08 04:46:27, Keith wrote: > > Yesterday's patch was better. > > I beg to differ. It did not address instrument definitions, or manual settings Concretely: can you show an example of not-just-academical LilyPond source that would be change to the worse with patch applied? Do you consider it sensible that values set via \override are transposed (but only if they are not set via a callback) while values set via \tweak aren't? Can you see any internal use of \set/\override in LilyPond source (or the corresponding usage of PropertySet/OverrideProperty) that would now behave inappropriately under transposition?
Sign in to reply to this message.
On Fri, 08 Feb 2013 01:20:59 -0800, <dak@gnu.org> wrote: > On 2013/02/08 08:40:29, dak wrote: >> On 2013/02/08 04:46:27, Keith wrote: >> > Yesterday's patch was better. > >> I beg to differ. It did not address instrument definitions, or manual > settings Well, we had a nice plane for \instrumentSwitch, and I did not think it wise to assume that the pitch should be protected in \set property = #(ly:make-pitch 0 -4 0) I only said that patch was better; this patch is good enough. > Concretely: can you show an example of not-just-academical LilyPond > source that would be change to the worse with patch applied? > Nope. I still encourage caution, because people use LilyPond for very academic projects. Also, it is academically possible that some programmer will want to add a override-able property that is a pitch that should be transposed; he would need to find and understand this patch. > Do you consider it sensible that values set via \override are transposed > (but only if they are not set via a callback) while values set via > \tweak aren't? > I have given it no thought. > Can you see any internal use of \set/\override in LilyPond source (or > the corresponding usage of PropertySet/OverrideProperty) that would now > behave inappropriately under transposition? > No. > https://codereview.appspot.com/7303057/
Sign in to reply to this message.
On 2013/02/09 05:46:45, Keith wrote:
> On Fri, 08 Feb 2013 01:20:59 -0800, <mailto:dak@gnu.org> wrote:
>
> > On 2013/02/08 08:40:29, dak wrote:
> >> On 2013/02/08 04:46:27, Keith wrote:
> >> > Yesterday's patch was better.
> >
> >> I beg to differ. It did not address instrument definitions, or manual
> > settings
>
> Well, we had a nice plane for \instrumentSwitch,
Did we? The plan more or less was to put 'untransposed on it, and
that would mean that properties travelling through \instrumentSwitch
don't get any of their pitches transformed, while properties given
through \set do. Alternatively, you just treat
instrumentTransposition, and that would still mean that setting
instrumentTransposition via \instrumentSwitch is not prone to
transposition, while setting instrumentTransposition via \set _is_
prone to transposition.
> and I did not think it wise to assume that the pitch should be protected in
> \set property = #(ly:make-pitch 0 -4 0)
You call it "protected". I call it "unmolested". There is no
inherent reason that pitches in \set/\override should be subjected to
transposition.
\transpose works on music expressions and stream events in a rather
rough manner. Take a look at transpose_mutable in lily/music.cc. The
rule is that any music or event property that is a pitch gets
transposed. Every property that is named "tonic" gets a normalized
octave afterwards (ugh). A property that is named "element" gets
recursively transposed (only if it is music, not an event), and
"elements" and "articulations" get transposed elementwise. And if a
property is named "pitch-alist", its keys get transposed.
Now with PropertySet and OverrideProperty, the property name in the
music that we are talking about is invariably "value", so it only gets
the pitch treatment. And if we are talking about tweaks, they appear
in arbitrary music events as a field "tweaks" always containing a
list, so nothing in tweaks gets ever transposed.
You complained about \set tonic ... not being transposable. But
neither is \set keySignature ... And I don't see any code which would
expect otherwise.
> I only said that patch was better; this patch is good enough.
Well, LilyPond only deserves the best. The previous patch was most
definitely more confined, and that is its main virtue. As a treatment
for the reported issue, this seems like the least-impact change. In
fact, its impact was limited enough that \instrumentSwitch already was
not being covered. So you proposed "Instrument definitions carry
context definitions for an instrument, except that
instrumentTransposition is not being transposed unlike what \set would
do."
Ugh.
The original approach with regard to the sign of
instrumentTransposition might be summarized as
Oops, we encountered some bad side effects from set/override
accidentally transposing values that are pitches, like
instrumentTransposition. What are we going to do?
Let us change the definition of the sign of
instrumentTransposition so that it does something really clever
even though it is incoherent and quite useless as opposed to
incoherent and totally useless as previously.
Now that is not cleaning up the mess but rather hanging Christmas
ornaments from it. Some people might have gotten enamored to the
ornaments, but I don't see a reasonable way to save them.
> > Concretely: can you show an example of not-just-academical
> > LilyPond source that would be change to the worse with patch
> > applied?
> Nope. I still encourage caution, because people use LilyPond for
> very academic projects. Also, it is academically possible that some
> programmer will want to add a override-able property that is a pitch
> that should be transposed; he would need to find and understand this
> patch.
You are constantly working from the assumption that it is natural to
assume context-property setting commands setting pitches should be
subject to transposition. And you list "tonic" as an example. Except
that "tonic" needs to get _octave-normalized_ after transposition, and
\set tonic ... will _not_ achieve that. The transposition of
instrumentTransposition is spectacularly weird and almost entirely
useless. And so on. Yes, there is the conceivable case of this
weirdness being _exploitable_ in a clever way for some clever purpose.
It doesn't matter. LilyPond is still being actively maintained. If a
feature is required, it can be implemented properly, with a proper
interface, _without_ resorting to exploits.
> > Do you consider it sensible that values set via \override are
> > transposed (but only if they are not set via a callback) while
> > values set via \tweak aren't?
> I have given it no thought.
You should before labelling one approach better than another.
instrumentTransposition turns out to be just one facet of a larger
issue, and in this case I think we are better off solving the larger
issue even though exploits for the inconsistent behavior already
exist: we have been pointed to mailing list threads demonstrating code
catered for this, like
\transpose bes c' { \transposition c' ...
for writing for an instrument with transposition bes in concert pitch.
But this particular usage will break even with the small "solution" to
the issue. I don't know of exploits other than
instrumentTransposition, and if there are any, we'd better plug them
along with the rest.
> > Can you see any internal use of \set/\override in LilyPond source
> > (or the corresponding usage of PropertySet/OverrideProperty) that
> > would now behave inappropriately under transposition?
> No.
I am putting the patch back on countdown for 2013/02/11 then. I am
fully aware that it is not healthy that as "Patch meister" I am judge
and jury in a process where I also happen to be defendant (or, in the
case of Mike's work, state attorney). And I can't really pretend to
act as an impartial instance when I have very strong opinions. But I
can't recluse myself when nobody else picks up. So you have to make
do, or volunteer.
Sign in to reply to this message.
On 2013/02/09 08:54:03, dak wrote: > It doesn't matter. LilyPond is still being actively maintained. If a > feature is required, it can be implemented properly, with a proper > interface, _without_ resorting to exploits. > I was hoping to be able to provide a backward-compatibility function, as in <https://codereview.appspot.com/7312074/>, just in case someone used \transposition inside of \transpose the way it used to work.
Sign in to reply to this message.
On 2013/02/11 06:18:57, Keith wrote: > On 2013/02/09 08:54:03, dak wrote: > > > It doesn't matter. LilyPond is still being actively maintained. If a > > feature is required, it can be implemented properly, with a proper > > interface, _without_ resorting to exploits. > > > > I was hoping to be able to provide a backward-compatibility function, as in > <https://codereview.appspot.com/7312074/>, just in case someone used > \transposition inside of \transpose the way it used to work. I did not even look at the proposed patch but it touches several binaries. That should not be necessary. Of course, in this variant of the patch, it would be feasible just to put untransposable back to #f, but since the followup work includes reversing the sign of the pitch again, this is a dead end. I think that something using ApplyContext should be workable, though, so that the compatibility function gets along just using LilyPond/Scheme and can be loaded on-demand.
Sign in to reply to this message.
On 2013/02/11 09:25:20, dak wrote: > On 2013/02/11 06:18:57, Keith wrote: > > On 2013/02/09 08:54:03, dak wrote: > > > > > It doesn't matter. LilyPond is still being actively maintained. If a > > > feature is required, it can be implemented properly, with a proper > > > interface, _without_ resorting to exploits. > > > > > > > I was hoping to be able to provide a backward-compatibility function, as in > > <https://codereview.appspot.com/7312074/>, just in case someone used > > \transposition inside of \transpose the way it used to work. > > I did not even look at the proposed patch but it touches several binaries. That > should not be necessary. Of course, in this variant of the patch, it would be > feasible just to put untransposable back to #f, but since the followup work > includes reversing the sign of the pitch again, this is a dead end. I think > that something using ApplyContext should be workable, though, so that the > compatibility function gets along just using LilyPond/Scheme and can be loaded > on-demand. Ok, ApplyContext does not cut it since it does not offer access to the original music. But try, for example, oldTransposition = #(define-music-function (parser location pitch) (ly:pitch?) (make-music 'SequentialMusic 'pitch (ly:pitch-negate pitch) 'elements-callback (lambda (m) (list #{ \transposition $(ly:pitch-negate (ly:music-property m 'pitch)) #})))) and you'll see that \oldTransposition will just make the old behavior available again. You can't assign this particular definition to transposition, for obvious reasons, but saving and using the old value of \transposition should be doable in an obvious manner.
Sign in to reply to this message.
On 2013/02/11 12:39:02, dak wrote:
> On 2013/02/11 09:25:20, dak wrote:
> > On 2013/02/11 06:18:57, Keith wrote:
> > >
> > > I was hoping to be able to provide a backward-compatibility function, as
in
> > I did not even look at the proposed patch but it touches several binaries.
> That
> > should not be necessary. Of course, in this variant of the patch, it would
be
> > feasible just to put untransposable back to #f, but since the followup work
> > includes reversing the sign of the pitch again, this is a dead end. I think
> > that something using ApplyContext should be workable, though, so that the
> > compatibility function gets along just using LilyPond/Scheme and can be
loaded
> > on-demand.
Well, my previous suggestion for backward-compatibility used LilyPond, but you
promptly adjusted your patch to stop my suggestion from working.
> oldTransposition =
> #(define-music-function (parser location pitch) (ly:pitch?)
> (make-music 'SequentialMusic
> 'pitch (ly:pitch-negate pitch)
> 'elements-callback
> (lambda (m)
> (list
> #{ \transposition $(ly:pitch-negate
> (ly:music-property m 'pitch))
> #}))))
Great. The pitches in structures built by make-music (differently to those
created by property-set) are molested by \transpose, but then a sneaky callback
tampers with the music and creates -- wait for it -- a nested property-set! It
just goes to show that people will take advantage of _any_ reproducible
behavior, no matter how inconsistent.
Just kidding. This should be fine for a backward-compatibility function, in
case anyone has a 200-page score that accidentally depended on the old behavior.
Sign in to reply to this message.
On 2013/02/11 20:53:53, Keith wrote:
> On 2013/02/11 12:39:02, dak wrote:
> > On 2013/02/11 09:25:20, dak wrote:
> > > On 2013/02/11 06:18:57, Keith wrote:
> > > >
> > > > I was hoping to be able to provide a backward-compatibility function, as
> in
>
> > > I did not even look at the proposed patch but it touches several binaries.
> > That
> > > should not be necessary. Of course, in this variant of the patch, it
would
> be
> > > feasible just to put untransposable back to #f, but since the followup
work
> > > includes reversing the sign of the pitch again, this is a dead end. I
think
> > > that something using ApplyContext should be workable, though, so that the
> > > compatibility function gets along just using LilyPond/Scheme and can be
> loaded
> > > on-demand.
>
> Well, my previous suggestion for backward-compatibility used LilyPond, but you
> promptly adjusted your patch to stop my suggestion from working.
>
> > oldTransposition =
> > #(define-music-function (parser location pitch) (ly:pitch?)
> > (make-music 'SequentialMusic
> > 'pitch (ly:pitch-negate pitch)
> > 'elements-callback
> > (lambda (m)
> > (list
> > #{ \transposition $(ly:pitch-negate
> > (ly:music-property m 'pitch))
> > #}))))
>
> Great. The pitches in structures built by make-music (differently to those
> created by property-set) are molested by \transpose, but then a sneaky
callback
> tampers with the music and creates -- wait for it -- a nested
property-set!
The copy&paste job does not match what happens here. In this case,
transpose manipulates a pitch field that is by naming and function
_chosen_ to get acted upon. That's not the abomination. The
abomination is using a music type intended for something different and
printing as something different for setting a transposition using a
callback not intended for it.
Arguably, one should rather use TransposedMusic or similar for this
abomination. However, this would involve tampering _both_ with
elements-callback as well as iterator-ctor. And TransposedMusic does
not really have anything to do with \transposition except by relation
of the names.
I'd have preferred, in order of priority, using something like
a) ApplyContext. This would not have access to the event, however.
b) a user-defined event. We don't have those in a reliable manner
yet.
This is a compatibility hack. The first version (and most likely also
the ultimate version) did not use #{ ... #} but rather copy&paste from
the internals of \transposition. However, those are going to change
when I change the sign of instrumentTransposition. So for better
longevity of this comment, I picked #{ ... #}.
> It just goes to show that people will take advantage of _any_
> reproducible behavior, no matter how inconsistent.
It is a compatibility hack purposefully not affecting _any_ of the
LilyPond code base when not used. Once user-defined events are more
than a semi-manual hack, I'd use them. Since they aren't, I chose
this self-contained hack. I'd not recommend it for user-maintained
code: it relies on SequentialMusic going through elements-callback.
But maintaining this hack through changes of SequentialMusic should be
less work than maintaining explicit code paths in the main code. We
have still lily_1_8_relative mottled through our code base, and
ripping out this compatibility cruft from versions of 1.8 or earlier
(seriously?!?) was vetoed because people might have been using it as
a user choice option.
Since it seems almost impossible to stamp such compatibility cruft
out, I prefer not letting it in in the first place.
> Just kidding.
Sure, but the amount of hypocrisy of mine that you are basing the
kidding on might be different from what you thing and/or suggest, so I
prefer to have this in the open.
> This should be fine for a backward-compatibility function, in case
> anyone has a 200-page score that accidentally depended on the old
> behavior.
The situation is worse than that. The mailing list carries examples
where people have purposefully rather than accidentally based their
code on the old behavior. And in light of the available
documentation, I can't blame them for doing experimentation and taking
bad choices, choices that it takes someone with a clue about
maintainability, predictability and system design to do right.
So we are not talking about "accidentally" but rather "imprudently"
or, as that level of prudence is nothing to require of a user,
"unwisely" here.
Curing the fallout with documentation, convert-ly rules and backward
compatibility include file will be much more of a wart and disgrace
than the above code.
Sign in to reply to this message.
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
