Re: Help with Scheme engraver please

2016-09-19 Thread Trevor Daniels

Trevor Daniels wrote Saturday, September 17, 2016 9:57 PM

> Thomas Morley wrote Friday, September 09, 2016 11:31 PM
> 
>> 2016-09-08 0:07 GMT+02:00 Trevor Daniels :
>>>
>>>  But I don't understand why you
>>> used a rather complicated procedure to obtain durations.  Could you
>>> not simply extract the durations from note events?
>> 
>> In my opinion the historic lute tablatures were written disregarding
>> any polyphony as far as rhythmy are concerned, yes.
>> But this polyphony was always _meant_ and the player should respect it.
>>
>> For our coding this means an example like
>> 
>> upper = { d'2 d' }
>> middle = { \override Rest.staff-position = #-1.5 r8 f r8 f r8 f r8 f }
>> lower = { a,4\rest d a,4\rest d }
>> 
>> \score {
>>  <<
>>   \new Staff << \clef "G_8" \upper \\ \lower \\ \middle >>
>> 
>>   \new TabStaff
>>   << \clef "G_8" \upper \\ \lower \\ \middle >>
>>  >>
>>  \layout {
>>\context {
>>\TabStaff
>>  stringTunings = \stringTuning 
>>}
>>  }
>> }
>> 
>> should return proper polyphonic in Staff, and in TabStaff only a
>> single 8th indication for the overall rhythm should be printed.
>> This can be achieved with my proposal and would warrant the principle
>> of one source-code for Staff _and_ TabStaff.
>> I didn't found a method to do so with simple durations.
> 
> OK, I see now why you need to extract the interval between a note and the
> subsequent note even when they are split between several voices.  
> This interval then should be displayed as the "duration" of the first of the 
> pair
> (unless it is unchanged from the previous one, of course)
> 
> I agree this can't be done by looking solely at the duration of individual
> notes.
> 
> However, your code doesn't quite work in all situations.  If you replace the
> first f in the middle voice with a rest we should have a duration of 4 
> followed
> by one of 8, but the 8 is missing.
> 
>> You seems to be of different opinion, for some cases you let
>> explicitely print the warning:
>> "Polyphony is not supported in lute tab"
> 
> Well, I meant it wasn't supported in my simple implementation, not
> that it shouldn't be.
> 
> I need now to study your approach to polyphony in greater detail to understand
> the logic.

Having thought about polyphony in tab a little more I realise now there is a 
fundamental difficulty: it is quite possible to have an interval in time 
between two adjacent notes that cannot be represented as a single duration.  In 
staff representation ties would be used to do this, but I don't think ties were 
used in baroque tab, were they?  Even if they were, implementing them at this 
early stage would be a step too far, at least for me.  So I plan to sidestep 
polyphony at present and concentrate on implementing lute tab from a single 
voice.  There's plenty to do yet to achieve that in a form suitable for a LP 
patch.

Trevor
___
lilypond-devel mailing list
lilypond-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/lilypond-devel


Re: Help with Scheme engraver please

2016-09-17 Thread Trevor Daniels

Thomas Morley wrote Friday, September 09, 2016 11:31 PM

Hi Harm

back now from my week away ...


> 2016-09-08 0:07 GMT+02:00 Trevor Daniels :
>>
>>  But I don't understand why you
>> used a rather complicated procedure to obtain durations.  Could you
>> not simply extract the durations from note events?
> 
> In my opinion the historic lute tablatures were written disregarding
> any polyphony as far as rhythmy are concerned, yes.
> But this polyphony was always _meant_ and the player should respect it.
>
> For our coding this means an example like
> 
> upper = { d'2 d' }
> middle = { \override Rest.staff-position = #-1.5 r8 f r8 f r8 f r8 f }
> lower = { a,4\rest d a,4\rest d }
> 
> \score {
>  <<
>   \new Staff << \clef "G_8" \upper \\ \lower \\ \middle >>
> 
>   \new TabStaff
>   << \clef "G_8" \upper \\ \lower \\ \middle >>
>  >>
>  \layout {
>\context {
>\TabStaff
>  stringTunings = \stringTuning 
>}
>  }
> }
> 
> should return proper polyphonic in Staff, and in TabStaff only a
> single 8th indication for the overall rhythm should be printed.
> This can be achieved with my proposal and would warrant the principle
> of one source-code for Staff _and_ TabStaff.
> I didn't found a method to do so with simple durations.

OK, I see now why you need to extract the interval between a note and the
subsequent note even when they are split between several voices.  
This interval then should be displayed as the "duration" of the first of the 
pair
(unless it is unchanged from the previous one, of course)

I agree this can't be done by looking solely at the duration of individual
notes.

However, your code doesn't quite work in all situations.  If you replace the
first f in the middle voice with a rest we should have a duration of 4 followed
by one of 8, but the 8 is missing.
 
> You seems to be of different opinion, for some cases you let
> explicitely print the warning:
> "Polyphony is not supported in lute tab"

Well, I meant it wasn't supported in my simple implementation, not
that it shouldn't be.

> Always printing the duration at the start of every bar even if
> unchanged happens sometimes, but sometimes not, Maybe let it depend on
> a context-property?

Yes, a sensible later step.
 
> For the bass courses.
> I didn't understand this point in your former mails. Now with your
> code its clearer to me.
> But why you do it this way? Isn't my implementation of
> https://sourceforge.net/p/testlilyissues/issues/4768/
> sufficient?

Well, to be honest I'd forgotten about this.  But unfortunately it is 
incompatible
with the nice fret number glyphs from Fronimo as that font doesn't include
a '/'.  However, as we can't adopt the Fronimo fonts anyway I'll revert to using
your implementation in any future work.

I need now to study your approach to polyphony in greater detail to understand
the logic.

Trevor

___
lilypond-devel mailing list
lilypond-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/lilypond-devel


Re: Help with Scheme engraver please

2016-09-09 Thread Thomas Morley
Hi Trevor,

2016-09-08 0:07 GMT+02:00 Trevor Daniels <t.dani...@treda.co.uk>:
>
> - Original Message -
> From: "Thomas Morley" <thomasmorle...@gmail.com>
> To: "Trevor Daniels" <t.dani...@treda.co.uk>
> Cc: "Lily-Devel List" <lilypond-devel@gnu.org>
> Sent: Sunday, September 04, 2016 7:28 AM
> Subject: Re: Help with Scheme engraver please
>
>
>> 2016-09-03 19:29 GMT+02:00 Thomas Morley <thomasmorle...@gmail.com>:
>>
>>> I've put some work on it. See attached duration-as-markup-5b-harm.ly
>>> The general work should be clear from comments and descriptions.
>>> There's some ugly code in it, although it works so far, wide room for
>>> improvements still there.
>>> Nevertheless it works now even in polyphonic.
>>
>> Please replace the coding in `stop-translation-timestep' with:
>>
> [snip]
>>
>> This will cure a bug with last notes starting at some moment, but with
>> different durations.
>
> Thanks  Harm, for this and the preceding mail.  I've found them very
> helpful.  In particular, a simpler way to set stringTuning and how to set
> persistent variables within engravers.  But I don't understand why you
> used a rather complicated procedure to obtain durations.  Could you
> not simply extract the durations from note events?

In my opinion the historic lute tablatures were written disregarding
any polyphony as far as rhythmy are concerned, yes.
But this polyphony was always _meant_ and the player should respect it.

For our coding this means an example like

upper = { d'2 d' }
middle = { \override Rest.staff-position = #-1.5 r8 f r8 f r8 f r8 f }
lower = { a,4\rest d a,4\rest d }

\score {
  <<
   \new Staff << \clef "G_8" \upper \\ \lower \\ \middle >>

   \new TabStaff
   << \clef "G_8" \upper \\ \lower \\ \middle >>
  >>
  \layout {
\context {
\TabStaff
  stringTunings = \stringTuning <a, d f a d' f'>
}
  }
}

should return proper polyphonic in Staff, and in TabStaff only a
single 8th indication for the overall rhythm should be printed.
This can be achieved with my proposal and would warrant the principle
of one source-code for Staff _and_ TabStaff.
I didn't found a method to do so with simple durations.

You seems to be of different opinion, for some cases you let
explicitely print the warning:
"Polyphony is not supported in lute tab"


> Actually I'd got quite a bit further than the simple example I posted,
> and my current state is attached, extracting durations and pitches
> from note-events, and detecting the start of bars by acknowledging
> barline grobs.  This version draws duration grobs whenever the
> duration changes, and at the start of every bar, bass course
> grobs below the tab, adds fingering and laissez vibrer slurs (I think
> that's what they are used for.)

Always printing the duration at the start of every bar even if
unchanged happens sometimes, but sometimes not, Maybe let it depend on
a context-property?

For the bass courses.
I didn't understand this point in your former mails. Now with your
code its clearer to me.
But why you do it this way? Isn't my implementation of
https://sourceforge.net/p/testlilyissues/issues/4768/
sufficient?

Didn't dive into it further, hopefully during the upcoming weekend ...

Cheers,
  Harm

___
lilypond-devel mailing list
lilypond-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/lilypond-devel


Re: Help with Scheme engraver please

2016-09-07 Thread Trevor Daniels

- Original Message - 
From: "Thomas Morley" <thomasmorle...@gmail.com>
To: "Trevor Daniels" <t.dani...@treda.co.uk>
Cc: "Lily-Devel List" <lilypond-devel@gnu.org>
Sent: Sunday, September 04, 2016 7:28 AM
Subject: Re: Help with Scheme engraver please


> 2016-09-03 19:29 GMT+02:00 Thomas Morley <thomasmorle...@gmail.com>:
> 
>> I've put some work on it. See attached duration-as-markup-5b-harm.ly
>> The general work should be clear from comments and descriptions.
>> There's some ugly code in it, although it works so far, wide room for
>> improvements still there.
>> Nevertheless it works now even in polyphonic.
> 
> Please replace the coding in `stop-translation-timestep' with:
> 
[snip]
>
> This will cure a bug with last notes starting at some moment, but with
> different durations.

Thanks  Harm, for this and the preceding mail.  I've found them very
helpful.  In particular, a simpler way to set stringTuning and how to set
persistent variables within engravers.  But I don't understand why you
used a rather complicated procedure to obtain durations.  Could you
not simply extract the durations from note events?

Actually I'd got quite a bit further than the simple example I posted,
and my current state is attached, extracting durations and pitches
from note-events, and detecting the start of bars by acknowledging
barline grobs.  This version draws duration grobs whenever the
duration changes, and at the start of every bar, bass course
grobs below the tab, adds fingering and laissez vibrer slurs (I think
that's what they are used for.)

There's quite a lot still wrong with this example, although it works in
simple cases.  You can see these problems listed in the TODOs.
And the code needs some tidying up too as bits of it are rather
messy (to say the least!).  And it would probably be better to separate
the generation of the two types of grobs into two engravers.

You'll see I use the Fronimo glyphs for the bass course indications,
and mensural flags for the durations.  These are just for demonstration: 
we'd need a set of lute tab glyphs of our own to be defined at some stage.

But this is now pretty close to Phase I which I defined in the note 
dated 22 Nov 2009, in this thread:
http://lilypond-s-support-for-tablatures.3383434.n2.nabble.com/Baroque-lute-tablature-td4008032.html

I probably will be somewhat unresponsive for 10 days or so, as we
are away on a belated summer break next week.

Trevor
\version "2.19.46"

% Example of using Scheme engravers to add markup based on
% note duration and pitch

% Avoids repeated durations on both chords and consecutive notes
% Always prints duration at start of bar
% Adds dots
% Adds string indication in bar 3
% Adds stroke finger indications
% Makes dots height not vary with duration
% Adds glyphs for minims and semibreves
% Fixes error message with avoid-slur
% Adds string finger indications
% Adds glissando to show repeated finger
% (not good - each has to be positioned)
% Removes debugging printouts in Lute_tab_duration_engraver
% Uses note names in stringTuning (thanks Harm)
% Places persistent variables inside engraver (thanks Harm)
% Adds bass courses


%{
TODO
  Error when finger is specified with slur
  Warning when bass course pitch is specified
  Handle notes with different durations at one musical moment better
  Need better way of linking notes with repeated right finger
could this be detected and added automatically?
  Bass course pitches should not be hard-coded
%}

#(define (t->m t)
   "Return the current moment of translator object @var{t}."
   (ly:context-current-moment (ly:translator-context t)))

#(define
  (duration-markup duration)
"Returns flags corresponding to duration as markup,
 avoiding repeated symbol if duration has not changed."
  (define flag-glyph "")
  (define dots-glyph "")
  (let ((duration-log
 (ly:duration-log duration))
(duration-dots
 (ly:duration-dot-count duration)))
; obtain flag glyph
(case duration-log
  ; TODO: replace with more suitable glyphs
  ((0) (set! flag-glyph (markup #:note "1" UP)))
  ((1) (set! flag-glyph (markup #:note "2" UP)))
  ((2) (set! flag-glyph (markup #:musicglyph "rests.M2mensural")))
  ((3) (set! flag-glyph (markup #:musicglyph "flags.mensuralu03")))
  ((4) (set! flag-glyph (markup #:musicglyph "flags.mensuralu04")))
  ((5) (set! flag-glyph (markup #:musicglyph "flags.mensuralu05")))
  ((6) (set! flag-glyph (markup #:musicglyph "flags.mensuralu06")))
  (else
   (begin
(ly:warning "Duration glyph not available for duration-log of ~a" duration-log)
(set! flag-glyph " "
; obtain dots glyp

Re: Help with Scheme engraver please

2016-09-04 Thread Thomas Morley
2016-09-03 19:29 GMT+02:00 Thomas Morley :

> I've put some work on it. See attached duration-as-markup-5b-harm.ly
> The general work should be clear from comments and descriptions.
> There's some ugly code in it, although it works so far, wide room for
> improvements still there.
> Nevertheless it works now even in polyphonic.

Please replace the coding in `stop-translation-timestep' with:

   ((stop-translation-timestep translator)
   ; (format 1 "~16a: (stop-translation-timestep)\n" (t->m translator))
   ;; needs to be here, otherwise the moments are not completely collected
(let* (;; The last note-events may start at the same time-step, but
   ;; may have different durations. Thus we need to select the
   ;; one with the longest duration, to detemine which
   ;; duration-string should be used for make-note-markup in tab
   (last-notes-amount
 (length (car ((@@ (lily) split-at-predicate) equal? m-n
   (longest-last-ev
 (last
  (sort
(take ev last-notes-amount)
(lambda (e1 e2)
  (ly:durationduration-string x '()))
 moments-diffs)
   (list
  (ly:duration->string
(ly:event-property longest-last-ev 'duration))
  (for-each
(lambda (g strg)
  (if (string-null? strg)
  (ly:grob-suicide! g)
  (begin
(ly:grob-set-property! g 'direction UP)
(ly:grob-set-property! g 'text
  (markup #:override '(style . mensural) #:note strg UP)
(reverse grobs)
(replace-adjacent-duplicates moment-diff-strings '()

This will cure a bug with last notes starting at some moment, but with
different durations.

Cheers,
  Harm

___
lilypond-devel mailing list
lilypond-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/lilypond-devel


Re: Help with Scheme engraver please

2016-09-03 Thread Thomas Morley
2016-09-02 23:34 GMT+02:00 Trevor Daniels :
>
> Thomas Morley wrote Friday, September 02, 2016 8:22 PM
>
>
>> 2016-09-02 13:05 GMT+02:00 Trevor Daniels :
>>>
>>> There already is a helpful working example in the code base.  See
>>>
>>> input/regression/scheme-engraver.ly
>>>
>>> This doesn't go as far as creating new grobs, so I've attached a
>>> simple example that does.  This is a bit of a hack, used as part of
>>> a learning process, and a bit messy as it evolved from an earlier
>>> attempt, but it illustrates one way.
>>>
>>> Actually, comments from the experts on this would be very helpful.
>>
>> I stumbled across you're printing a rest-glyph for a quarter-note.
>>
>> Eventually I might have some ideas, but there are a plethora of
>> variants for historic tablaures. Which glyphs do you want to be
>> printed above the TabStaff for the code below. Only flags, flags with
>> stems, stems only for quarters, what to do for notes longer than a
>> quarter?
>>
>> m = { \compressFullBarRests c'\maxima \longa \breve 1 2 4 8 16 32 }
>>
>> <<
>>  \new MensuralVoice \m
>>  \new TabStaff \with { \revert TextScript.stencil }
>>  \new TabVoice
>>\with {
>>  \consists \Lute_tab_duration_engraver
>>} \m
>
> I really know very little about lute tablature, but I believe there are many
> different styles.  Should this ever get close to operational we'd need
> to discuss which styles to support and what glyphs would be needed.
> But I fear that's some way in the future.  The mensural (and rest) glyphs
> I used in this little example are just markers really, while I explore how to
> deal with other aspects - fingering, bass courses, articulations, etc.
>
> Trevor

Hi Trevor,

I've put some work on it. See attached duration-as-markup-5b-harm.ly
The general work should be clear from comments and descriptions.
There's some ugly code in it, although it works so far, wide room for
improvements still there.
Nevertheless it works now even in polyphonic.

For the ornaments you may be interested in Nicolas' engraver.
Attached you'll find my fix to make it compile with newer
devel-versions. Though I didn't do any testings for ornaments in
TabStaff.
You may notice the little bug I detected (close to the red exclamation
mark in pdf), no clue how to fix this.


Cheers,
  Harm
\version "2.19.42"

%% taken from:
%% https://github.com/nsceaux/nenuvar/blob/master/common/side-ornementations.ily
%% and adapted for v2.19.42

%%%
%%% Utilities for defining new grobs, grob properties and music event types
%%% (there should be built-in commands to do that in LilyPond)
%%%
#(define (define-grob-definition grob-name grob-entry)
   "Define a new grob and add it to `all-grob-definitions', after
scm/define-grobs.scm fashion.
After grob definitions are added, use:

\\layout {
  \\context {
\\Global
\\grobdescriptions #all-grob-descriptions
  }
}

to register them."
   (let* ((meta-entry   (assoc-get 'meta grob-entry))
  (class(assoc-get 'class meta-entry))
  (ifaces-entry (assoc-get 'interfaces meta-entry)))
 (set-object-property! grob-name 'translation-type? ly:grob-properties?)
 (set-object-property! grob-name 'is-grob? #t)
 (set! ifaces-entry (append (case class
  ((Item) '(item-interface))
  ((Spanner) '(spanner-interface))
  ((Paper_column) '((item-interface
 paper-column-interface)))
  ((System) '((system-interface
   spanner-interface)))
  (else '(unknown-interface)))
ifaces-entry))
 (set! ifaces-entry (uniq-list (sort ifaces-entry symbolhttp://lilypond.1069038.n5.nabble.com/crash-moving-DotColumn-td190493.html
  (set! (ly:grob-property dot-column 'positioning-done)
(lambda (grob)
  (ly:dot-column::calc-positioning-done grob)
  (ly:grob-translate-axis! grob orn-width X)
  #t)
  ornementation))
   
#(define (head-ornementation-engraver-acknowledge-note-head
  engraver note-grob source-engraver)
   "Note head acknowledge method for the head ornementation engraver.
When the note head event attached to the note head grob has ornementation
events among its articulations, then create a HeadOrnementation grob"
   (let* ((note-event (ly:grob-property note-grob 'cause)))
 (for-each (lambda (articulation)
 (if (memq 'head-ornementation-event
(ly:event-property articulation 'class))
 (begin
   (if (markup? (ly:event-property articulation 'text-left))
   (make-head-ornementation
engraver
 

Re: Help with Scheme engraver please

2016-09-02 Thread Trevor Daniels

Thomas Morley wrote Friday, September 02, 2016 8:22 PM


> 2016-09-02 13:05 GMT+02:00 Trevor Daniels :
>>
>> There already is a helpful working example in the code base.  See
>>
>> input/regression/scheme-engraver.ly
>>
>> This doesn't go as far as creating new grobs, so I've attached a
>> simple example that does.  This is a bit of a hack, used as part of
>> a learning process, and a bit messy as it evolved from an earlier
>> attempt, but it illustrates one way.
>>
>> Actually, comments from the experts on this would be very helpful.
>
> I stumbled across you're printing a rest-glyph for a quarter-note.
> 
> Eventually I might have some ideas, but there are a plethora of
> variants for historic tablaures. Which glyphs do you want to be
> printed above the TabStaff for the code below. Only flags, flags with
> stems, stems only for quarters, what to do for notes longer than a
> quarter?
> 
> m = { \compressFullBarRests c'\maxima \longa \breve 1 2 4 8 16 32 }
> 
> <<
>  \new MensuralVoice \m
>  \new TabStaff \with { \revert TextScript.stencil }
>  \new TabVoice
>\with {
>  \consists \Lute_tab_duration_engraver
>} \m

I really know very little about lute tablature, but I believe there are many
different styles.  Should this ever get close to operational we'd need
to discuss which styles to support and what glyphs would be needed.
But I fear that's some way in the future.  The mensural (and rest) glyphs
I used in this little example are just markers really, while I explore how to
deal with other aspects - fingering, bass courses, articulations, etc.

Trevor
___
lilypond-devel mailing list
lilypond-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/lilypond-devel


Re: Help with Scheme engraver please

2016-09-02 Thread Thomas Morley
2016-09-02 13:05 GMT+02:00 Trevor Daniels :
>
> Simon, you wrote Friday, September 02, 2016 1:34 AM
>> I just caught up with all the mailing lists, being back from holiday,
>> and I’d be interested in a working example for this solution. Would you
>> mind sharing it?
>
> There already is a helpful working example in the code base.  See
>
> input/regression/scheme-engraver.ly
>
> This doesn't go as far as creating new grobs, so I've attached a
> simple example that does.  This is a bit of a hack, used as part of
> a learning process, and a bit messy as it evolved from an earlier
> attempt, but it illustrates one way.
>
> Actually, comments from the experts on this would be very helpful.

Hi Trevor,

I stumbled across you're printing a rest-glyph for a quarter-note.

Eventually I might have some ideas, but there are a plethora of
variants for historic tablaures. Which glyphs do you want to be
printed above the TabStaff for the code below. Only flags, flags with
stems, stems only for quarters, what to do for notes longer than a
quarter?

m = { \compressFullBarRests c'\maxima \longa \breve 1 2 4 8 16 32 }

<<
  \new MensuralVoice \m
  \new TabStaff \with { \revert TextScript.stencil }
  \new TabVoice
\with {
  \consists \Lute_tab_duration_engraver
} \m
>>

Cheers,
  Harm

___
lilypond-devel mailing list
lilypond-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/lilypond-devel


Re: Help with Scheme engraver please

2016-09-02 Thread Trevor Daniels

Simon, you wrote Friday, September 02, 2016 1:34 AM

Hi Simon,

>On 24.08.2016 11:51, Trevor Daniels wrote:
>> David Kastrup wrote Wednesday, August 24, 2016 7:48 AM
>>> "Trevor Daniels"  writes:
 Prompted by the recent discussion on lute tablature, I tried coding a
 Scheme engraver to create the duration grobs but quickly ran into a
 problem.  I need to collect information from both a Listener and an
 Acknowledger so the obvious place to build the grob is in
 stop-translator-timestep,
>>> No, no, no.  stop-translator-timestep really is only for cleanup work.
>>> Stuff is no longer in working order then.  You want process-acknowledged
>>> here I think.
>>>
>>> There will always be a call to process-acknowledged whenever grobs have
>>> been created, and_reading_  stuff from grobs should be delayed until
>>> then since other acknowledgers might_write_  stuff into a grob even
>>> after your personal acknowledger has been called.  So the basic workflow
>>> is to use the various acknowledgers to_record_  the grobs you are
>>> interested in and_write_  stuff into them (or do read/write stuff that
>>> more or less is accumulative and/or really unrelated to other
>>> engravers), and then use the process-acknowledged hook for processing
>>> (including_reading_) the grobs you had recorded.
>>>
>>> You can create new grobs in process-acknowledged.  That will lead to a
>>> new cycle of acknowledger calls followed by process-acknowledged.  Only
>>> when all those cycles are over is stop-translator-timestep called, and
>>> then creating grobs is no longer an option.
>>
>> Thanks David.  That's beautifully clear.
>
> I just caught up with all the mailing lists, being back from holiday, 
> and I’d be interested in a working example for this solution. Would you 
> mind sharing it?

There already is a helpful working example in the code base.  See

input/regression/scheme-engraver.ly

This doesn't go as far as creating new grobs, so I've attached a
simple example that does.  This is a bit of a hack, used as part of
a learning process, and a bit messy as it evolved from an earlier
attempt, but it illustrates one way.

Actually, comments from the experts on this would be very helpful.

Trevor
\version "2.19.40"

% Example of using Scheme engraver to add markup based on note duration

% Avoids repeated durations on both chords and consecutive notes

%{
TODO
  Handle notes with different durations at one musical moment better
  Add dots
  Add bass courses
%}

#(define (t->m t)
   "Return the current moment of translator object @var{t}."
   (ly:context-current-moment (ly:translator-context t)))

% persistent variables for Lute_tab_duration_engraver
#(define previous-duration-log #f)	% to supress repeated durations
#(define ev #f)		% event
#(define en #f)		% engraver

Lute_tab_duration_engraver =
#(make-engraver
   ((initialize translator)
(format 1 "\n\n~16a: (initialize)\n" (t->m translator)))
   ((start-translation-timestep translator)
(set! ev #f)
(set! en #f)
(format 1 "~16a: (start-translation-timestep)\n" (t->m translator)))
   (listeners
 ((note-event engraver event)
  ; Save just the last event at each timestep
  ;TODO save shortest duration event?
  (set! ev event)
  (set! en engraver)
  (format 1 "~16a: detected this note event: ~a\n "
(t->m engraver) event)))
   (acknowledgers
 ((note-head-interface engraver grob source-engraver)
  (format 1 "~16a: saw ~a coming from ~a\n"
  (t->m engraver) grob source-engraver)))
   (end-acknowledgers
 ((beam-interface engraver grob source-engraver)
  (format 1 "~16a: saw end of ~a coming from ~a\n"
  (t->m engraver) grob source-engraver)))
   ((process-music translator)
(format 1 "~16a: (process-music)\n" (t->m translator))
(if ev
  (let ((duration-log
 (ly:duration-log (ly:event-property ev 'duration
(display duration-log)
(if (not (equal? duration-log previous-duration-log))
(let ((grob (ly:engraver-make-grob en 'TextScript ev)))
  (set! previous-duration-log duration-log)
  (ly:grob-set-property! grob 'direction UP)
  (ly:grob-set-property! grob 'text
(case duration-log
  ((2) (markup (#:musicglyph "rests.M2mensural")))
  ((3) (markup (#:musicglyph "flags.mensuralu03")))
  ((4) (markup (#:musicglyph "flags.mensuralu04")))
  ((5) (markup (#:musicglyph "flags.mensuralu05")))
  ((6) (markup (#:musicglyph "flags.mensuralu06")))
  (else (markup " ")
   ((process-acknowledged translator)
(format 1 "~16a: (process-acknowledged)\n" (t->m translator)))
   ((stop-translation-timestep translator)
(format 1 "~16a: (stop-translation-timestep)\n" (t->m translator)))
   ((finalize translator)
(format 1 "~16a: (finalize)\n" (t->m 

Re: Help with Scheme engraver please

2016-09-01 Thread Simon Albrecht

Hi Trevor,

On 24.08.2016 11:51, Trevor Daniels wrote:

David Kastrup wrote Wednesday, August 24, 2016 7:48 AM

"Trevor Daniels"  writes:

Prompted by the recent discussion on lute tablature, I tried coding a
Scheme engraver to create the duration grobs but quickly ran into a
problem.  I need to collect information from both a Listener and an
Acknowledger so the obvious place to build the grob is in
stop-translator-timestep,

No, no, no.  stop-translator-timestep really is only for cleanup work.
Stuff is no longer in working order then.  You want process-acknowledged
here I think.

There will always be a call to process-acknowledged whenever grobs have
been created, and_reading_  stuff from grobs should be delayed until
then since other acknowledgers might_write_  stuff into a grob even
after your personal acknowledger has been called.  So the basic workflow
is to use the various acknowledgers to_record_  the grobs you are
interested in and_write_  stuff into them (or do read/write stuff that
more or less is accumulative and/or really unrelated to other
engravers), and then use the process-acknowledged hook for processing
(including_reading_) the grobs you had recorded.

You can create new grobs in process-acknowledged.  That will lead to a
new cycle of acknowledger calls followed by process-acknowledged.  Only
when all those cycles are over is stop-translator-timestep called, and
then creating grobs is no longer an option.

Thanks David.  That's beautifully clear.


I just caught up with all the mailing lists, being back from holiday, 
and I’d be interested in a working example for this solution. Would you 
mind sharing it?


Best, Simon



___
lilypond-devel mailing list
lilypond-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/lilypond-devel


Re: Help with Scheme engraver please

2016-08-24 Thread David Kastrup
"Trevor Daniels"  writes:

> David Kastrup wrote Wednesday, August 24, 2016 7:48 AM
>
>
>> "Trevor Daniels"  writes:
>> 
>>> Prompted by the recent discussion on lute tablature, I tried coding a
>>> Scheme engraver to create the duration grobs but quickly ran into a
>>> problem.  I need to collect information from both a Listener and an
>>> Acknowledger so the obvious place to build the grob is in
>>> stop-translator-timestep,
>> 
>> No, no, no.  stop-translator-timestep really is only for cleanup work.
>> Stuff is no longer in working order then.  You want process-acknowledged
>> here I think.
>> 
>> There will always be a call to process-acknowledged whenever grobs have
>> been created, and _reading_ stuff from grobs should be delayed until
>> then since other acknowledgers might _write_ stuff into a grob even
>> after your personal acknowledger has been called.  So the basic workflow
>> is to use the various acknowledgers to _record_ the grobs you are
>> interested in and _write_ stuff into them (or do read/write stuff that
>> more or less is accumulative and/or really unrelated to other
>> engravers), and then use the process-acknowledged hook for processing
>> (including _reading_) the grobs you had recorded.
>> 
>> You can create new grobs in process-acknowledged.  That will lead to a
>> new cycle of acknowledger calls followed by process-acknowledged.  Only
>> when all those cycles are over is stop-translator-timestep called, and
>> then creating grobs is no longer an option.
>
> Thanks David.  That's beautifully clear, and much better than the rather
> terse sentence in the CG which misled me:
>
> "If useful things are to be done to the acknowledged grobs, this
> should be deferred until all the acknowledging has finished, i.e.,
> store the acknowledged grobs and process the information in a
> process-acknowledged () or stop-translation-timestep () function."
>
> I took what appeared to be the stop-translation-timestep option.

You can still "process" parts of the grob there (if that means just
reading out properties and possibly setting context properties based on
them) but stop-translation-timestep is a cleanup hook, and other
engravers might have already cleaned up stuff you might have wanted to
use.  And _creating_ grobs in there is clean out since engravers and
other code may no longer be in a state where they could process them.

-- 
David Kastrup

___
lilypond-devel mailing list
lilypond-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/lilypond-devel


Re: Help with Scheme engraver please

2016-08-24 Thread Trevor Daniels

David Kastrup wrote Wednesday, August 24, 2016 7:48 AM


> "Trevor Daniels"  writes:
> 
>> Prompted by the recent discussion on lute tablature, I tried coding a
>> Scheme engraver to create the duration grobs but quickly ran into a
>> problem.  I need to collect information from both a Listener and an
>> Acknowledger so the obvious place to build the grob is in
>> stop-translator-timestep,
> 
> No, no, no.  stop-translator-timestep really is only for cleanup work.
> Stuff is no longer in working order then.  You want process-acknowledged
> here I think.
> 
> There will always be a call to process-acknowledged whenever grobs have
> been created, and _reading_ stuff from grobs should be delayed until
> then since other acknowledgers might _write_ stuff into a grob even
> after your personal acknowledger has been called.  So the basic workflow
> is to use the various acknowledgers to _record_ the grobs you are
> interested in and _write_ stuff into them (or do read/write stuff that
> more or less is accumulative and/or really unrelated to other
> engravers), and then use the process-acknowledged hook for processing
> (including _reading_) the grobs you had recorded.
> 
> You can create new grobs in process-acknowledged.  That will lead to a
> new cycle of acknowledger calls followed by process-acknowledged.  Only
> when all those cycles are over is stop-translator-timestep called, and
> then creating grobs is no longer an option.

Thanks David.  That's beautifully clear, and much better than the rather
terse sentence in the CG which misled me:

"If useful things are to be done to the acknowledged grobs, this should be 
deferred until all the acknowledging has finished, i.e., store the acknowledged 
grobs and process the information in a process-acknowledged () or 
stop-translation-timestep () function."

I took what appeared to be the stop-translation-timestep option.

I'll take a time-out and prepare a patch for the CG based on your mail.

Trevor
___
lilypond-devel mailing list
lilypond-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/lilypond-devel


Re: Help with Scheme engraver please

2016-08-24 Thread David Kastrup
"Trevor Daniels"  writes:

> Prompted by the recent discussion on lute tablature, I tried coding a
> Scheme engraver to create the duration grobs but quickly ran into a
> problem.  I need to collect information from both a Listener and an
> Acknowledger so the obvious place to build the grob is in
> stop-translator-timestep,

No, no, no.  stop-translator-timestep really is only for cleanup work.
Stuff is no longer in working order then.  You want process-acknowledged
here I think.

There will always be a call to process-acknowledged whenever grobs have
been created, and _reading_ stuff from grobs should be delayed until
then since other acknowledgers might _write_ stuff into a grob even
after your personal acknowledger has been called.  So the basic workflow
is to use the various acknowledgers to _record_ the grobs you are
interested in and _write_ stuff into them (or do read/write stuff that
more or less is accumulative and/or really unrelated to other
engravers), and then use the process-acknowledged hook for processing
(including _reading_) the grobs you had recorded.

You can create new grobs in process-acknowledged.  That will lead to a
new cycle of acknowledger calls followed by process-acknowledged.  Only
when all those cycles are over is stop-translator-timestep called, and
then creating grobs is no longer an option.

-- 
David Kastrup

___
lilypond-devel mailing list
lilypond-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/lilypond-devel


Re: Help with Scheme engraver please

2016-08-23 Thread David Nalesnik
Hi Trevor,

On Tue, Aug 23, 2016 at 3:54 PM, Trevor Daniels  wrote:
> Prompted by the recent discussion on lute tablature, I tried coding a Scheme 
> engraver to create the duration grobs but quickly ran into a problem.  I need 
> to collect information from both a Listener and an Acknowledger so the 
> obvious place to build the grob is in stop-translator-timestep, but my 
> attempts all result in a LilyPond crash.  I'm on Windows Vista, so the crash 
> code is not very helpful - 1073741819.
>
> Minimal examples below.  The first creates a grob from the Listener and works 
> fine.  The second tries to create a grob from stop-translator-timestep and 
> fails.
>
> What am I doing wrong?

I can't explain what's wrong, but creating the grob in process-music
works for me.  You ought to check that you have an event with
ly:stream-event?


Hope this helps a little,
David

___
lilypond-devel mailing list
lilypond-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/lilypond-devel


Help with Scheme engraver please

2016-08-23 Thread Trevor Daniels
Prompted by the recent discussion on lute tablature, I tried coding a Scheme 
engraver to create the duration grobs but quickly ran into a problem.  I need 
to collect information from both a Listener and an Acknowledger so the obvious 
place to build the grob is in stop-translator-timestep, but my attempts all 
result in a LilyPond crash.  I'm on Windows Vista, so the crash code is not 
very helpful - 1073741819.

Minimal examples below.  The first creates a grob from the Listener and works 
fine.  The second tries to create a grob from stop-translator-timestep and 
fails.

What am I doing wrong?

This works:

\version "2.19.46"

engraver_demo =
#(make-engraver
   (listeners
 ((note-event engraver event)
  (let ((grob (ly:engraver-make-grob engraver 'TextScript event)))
(ly:grob-set-property! grob 'text "hi")

\layout {
  \context {
\Voice
\consists
\engraver_demo
  }
}

\relative {
  c'8
}

This fails:

\version "2.19.46"

#(define ev #f)

engraver_demo =
#(make-engraver
   (listeners
 ((note-event engraver event)
  (set! ev event)))
   ((stop-translation-timestep engraver)
  (let ((grob (ly:engraver-make-grob engraver 'TextScript ev)))
(ly:grob-set-property! grob 'text "hi"

\layout {
  \context {
\Voice
\consists
\engraver_demo
  }
}

\relative {
  c'8
}

Thanks, Trevor
___
lilypond-devel mailing list
lilypond-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/lilypond-devel