# chord-name-engraver plus capo - schemeing away ...

21 messages
12
Open this post in threaded view
|

## chord-name-engraver plus capo - schemeing away ...

 Okay. I (think I) know how to call scheme from C++. And I've been told it's a lot easier to manipulate markup in scheme than C++. So I need to write two functions in scheme, and call them from my engraver. Help! :-) The chords are stored as markup as: (#   (     (#       ( (# C)         (#       ( (# )))))     (# )     (#       (#     ((#       ( (#           ((# )))         (# 7)))))))) Digging into that, it seems fairly simple that I want to wrap a couple more "procedure line-markup" or "procedure simple-markup"s around this lot. So. (define (parenthesize-markup markup)   (make-line-markup (list (make-simple-markup "(") markup (make-simple-markup ")")) ??? I can't believe it's that easy! there must be more to it than that! So. First of all, what have I missed :-) Secondly, where do I put this function if I have got it right. Thirdly, how do I create "" or " " as my separator and do I need it ... Fourthly, given that I know the name of the function, is that all I need to pass from C++, or do I need to get a pointer to the function from somewhere? Phew! Get this done, then the code is all working and all I need do is document it and submit it for inclusion! Cheers, Wol --- ---- Join the Frogs!
Open this post in threaded view
|

## Re: chord-name-engraver plus capo - schemeing away ...

 On 27 August 2010 16:59, Wols Lists <[hidden email]> wrote: >  Okay. I (think I) know how to call scheme from C++. And I've been told > it's a lot easier to manipulate markup in scheme than C++. So I need to > write two functions in scheme, and call them from my engraver. Help! :-) I'm still not convinced you need a separate formatter. What's the difference between the main chord markup and the capo markup apart from being transposed? Does the capo markup use the same pitches as the main chord? If the only difference is that the capo is generated based on capoFret (i.e., all other elements are the same), then there's no reason why you can't read capoFret from the chord formatter and do all the formatting internally, completely bypassing the engraver. The other option is to create a separate grob for the capo, then it's easy to position it relative to the existing ChordName. > (define (parenthesize-markup markup) >  (make-line-markup (list (make-simple-markup "(") markup > (make-simple-markup ")")) > > ??? I can't believe it's that easy! there must be more to it than that! Easier: use the \parenthesize markup command (which creates proper curves rather than using glyphs from the font). > Secondly, where do I put this function if I have got it right. If it's something similar to the existing formatter, then you'd put it in scm/translation-functions.scm. > Thirdly, how do I create "" or " " as my separator and do I need it ... \line automatically spaces the markups word-space apart, so you shouldn't need to introduce any extra separators. > Fourthly, given that I know the name of the function, is that all I need > to pass from C++, or do I need to get a pointer to the function from > somewhere? If it's defined in one of the .scm files, you use ly_lily_module_constant () to get the proc, then call it using one of the scm_call_... functions (depending on the number of arguments). Cheers, Neil --- ---- Join the Frogs!
Open this post in threaded view
|

## Re: chord-name-engraver plus capo - schemeing away ...

 On 27/08/10 17:18, Neil Puttock wrote: > On 27 August 2010 16:59, Wols Lists <[hidden email]> wrote: >>  Okay. I (think I) know how to call scheme from C++. And I've been told >> it's a lot easier to manipulate markup in scheme than C++. So I need to >> write two functions in scheme, and call them from my engraver. Help! :-) > I'm still not convinced you need a separate formatter. > > What's the difference between the main chord markup and the capo > markup apart from being transposed? It isn't "just transposed". The final output is both the original chord and the transposed chord. > Does the capo markup use the same pitches as the main chord? Yes. > If the only difference is that the capo is generated based on capoFret > (i.e., all other elements are the same), then there's no reason why > you can't read capoFret from the chord formatter and do all the > formatting internally, completely bypassing the engraver. But it's the engraver calling the formatter, isn't it? I've just twigged what you're saying - no I CAN'T do that, because the formatter has to be called twice, once using capoFret, and once not. How do I tell it whether or not to use it? > The other option is to create a separate grob for the capo, then it's > easy to position it relative to the existing ChordName. > What happens if the user moves the ChordName? And how do I link one grob to another so they move as one? >> (define (parenthesize-markup markup) >>  (make-line-markup (list (make-simple-markup "(") markup >> (make-simple-markup ")")) >> >> ??? I can't believe it's that easy! there must be more to it than that! > Easier: use the \parenthesize markup command (which creates proper > curves rather than using glyphs from the font). > I'll play with that - I'll probably be back. I was looking for that. >> Secondly, where do I put this function if I have got it right. > If it's something similar to the existing formatter, then you'd put it > in scm/translation-functions.scm. > >> Thirdly, how do I create "" or " " as my separator and do I need it ... > \line automatically spaces the markups word-space apart, so you > shouldn't need to introduce any extra separators. > >> Fourthly, given that I know the name of the function, is that all I need >> to pass from C++, or do I need to get a pointer to the function from >> somewhere? > If it's defined in one of the .scm files, you use > ly_lily_module_constant () to get the proc, then call it using one of > the scm_call_... functions (depending on the number of arguments). > Thanks. So get the parenthesis function, get the make-line-markup function, and off we go. There might be a few more calls for help, though. > Cheers, > Neil Cheers, Anthony --- ---- Join the Frogs!
Open this post in threaded view
|

## Re: chord-name-engraver plus capo - schemeing away ...

 On 27/08/10 19:42, Wols Lists wrote: >> If it's defined in one of the .scm files, you use >> > ly_lily_module_constant () to get the proc, then call it using one of >> > the scm_call_... functions (depending on the number of arguments). >> > > Thanks. So get the parenthesis function, get the make-line-markup > function, and off we go. There might be a few more calls for help, though. I said there might be another call for help ... line-markup takes a pair as its second argument. How do I join my two markups into a pair from C++? And what's the parenthesis function actually called? (I've found one, but I've got to re-find it, and it didn't look right when I found it.) Cheers, Wol --- ---- Join the Frogs!
Open this post in threaded view
|

## Re: chord-name-engraver plus capo - schemeing away ...

 Okay - broken code follows: ------   if (!capo)     chord_name_->set_property ("text", markup);   else   {     SCM capovertical = get_property ("capoVertical");     // how do I combine text and markup to get "markup (capo_markup)" !!!     SCM paren_proc = ly_lily_module_constant ("parenthesize");    // what's this function really called?     capo_markup = scm_call_1 (paren_proc, capo_markup);         SCM line_proc = ly_lily_module_constant ("line-markup");     SCM final_markup = scm_call_3 (line_proc, scm_cons (markup, capo_markup), SCM_EOL);    // what is this missing?     chord_name_->set_property ("text", final_markup);   } ------ Forget the capoVertical stuff, that just currently does nothing. There's a function called "parenthesize" in define-markup-commands.scm that looks like it does what I want (line 3154), but ly_lily_module_constant can't find it, and I don't know whether I've got the call to it in the line below correct or not, anyway. And lastly, the call to line-markup blows up with "invalid arguments". I've found another function - markup-join (markup.scm, l514) - should I be using that? But I think it wants a pair, and scm_cons does not seem to be the function that creates a pair. There's probably more to it than that, though. Once I've cracked this, I'll have basic capo functionality working in the engraver, and I can submit it for proper review. (And I'll pretty much have learnt enough C++/Scheme-fu to finish the engraver properly :-) Cheers, Wol --- ---- Join the Frogs!
Open this post in threaded view
|

## Re: chord-name-engraver plus capo - schemeing away ...

 In reply to this post by Neil Puttock On 27 August 2010 17:56, Wols Lists <[hidden email]> wrote: >  On 27/08/10 17:18, Neil Puttock wrote: >> On 27 August 2010 16:59, Wols Lists <[hidden email]> wrote: >>>  Okay. I (think I) know how to call scheme from C++. And I've been told >>> it's a lot easier to manipulate markup in scheme than C++. So I need to >>> write two functions in scheme, and call them from my engraver. Help! :-) >> I'm still not convinced you need a separate formatter. > Because you've missed the entire point of what I'm doing. As far as I > can tell, the formatter is chosen by the user - whether standard, > ignaziek or whatever - and fed a series of notes. It then returns ONE > chord to the engraver, which the engraver then prints. > > So if I did what you suggest, I would have to rewrite EVERY FORMATTER! > (sorry for the shouting :-) There are only two styles (forget Banter, it doesn't work and will be removed eventually).  Both are already somewhat modular in that they rely on several library functions defined in scm/chord-name.scm, so it shouldn't be too difficult to create a handler for capos which can be slotted in to both formatters without excess duplication. > As modified, once capoFret is set, for every ONE chord fed INTO the > engraver, it will spit TWO chords OUT. So I need some way of combining > things. And as I said, you don't want to do this in C++.  There's a good reason why line-markup' is only called outside scheme from the parser: it's painful to juggle several markups this way, and separte markups which should be stacked are usually treated as separate grobs (or stacked internally by whatever function's doing the formatting). > For example, if capoFret is set to 3, and the engraver is fed the chord > of C, it will print "C (A)". So if you had Cmaj7, you'd want (Amaj7) for the capo? > As far as I can see, what I am doing is the obvious (only?) way of doing it. > > Cheers, > Wol > --- ---- Join the Frogs!
Open this post in threaded view
|

## Re: chord-name-engraver plus capo - schemeing away ...

 In reply to this post by Wols Lists On 27 August 2010 20:07, Wols Lists <[hidden email]> wrote: > line-markup takes a pair as its second argument. How do I join my two > markups into a pair from C++? It takes a list, so you'd use scm_list_[1,2,3,4,5] () or scm_list_n (). > And what's the parenthesis function actually called? (I've found one, > but I've got to re-find it, and it didn't look right when I found it.) It's called parenthesize', so its internal name is parenthesize-markup'. Cheers, Neil --- ---- Join the Frogs!
Open this post in threaded view
|

## Re: chord-name-engraver plus capo - schemeing away ...

 In reply to this post by Neil Puttock  On 27/08/10 23:01, Neil Puttock wrote: >> For example, if capoFret is set to 3, and the engraver is fed the chord >> > of C, it will print "C (A)". > So if you had Cmaj7, you'd want (Amaj7) for the capo? > Yes. So the engraver needs to spit out "Cmaj7 (Amaj7)". Cheers, Wol --- ---- Join the Frogs!
Open this post in threaded view
|

## Re: chord-name-engraver plus capo - schemeing away ...

 In reply to this post by Wols Lists On 27 August 2010 21:49, Wols Lists <[hidden email]> wrote: > There's a function called "parenthesize" in define-markup-commands.scm > that looks like it does what I want (line 3154), but > ly_lily_module_constant can't find it, and I don't know whether I've got > the call to it in the line below correct or not, anyway. ly_lily_module_constant ("parenthesize-markup") > And lastly, the call to line-markup blows up with "invalid arguments". > I've found another function - markup-join (markup.scm, l514) - should I > be using that? But I think it wants a pair, and scm_cons does not seem > to be the function that creates a pair. There's probably more to it than > that, though. scm_cons does create a pair, but you need a list for the arguments to \line. Just to prove how nasty doing markup in C++ is, here's the above code corrected:   SCM paren_proc = ly_lily_module_constant ("parenthesize-markup");   SCM line_proc = ly_lily_module_constant ("line-markup");   SCM hspace_proc = ly_lily_module_constant ("hspace-markup");   SCM final_markup = scm_list_n (line_proc,                                  scm_list_3 (markup,                                              scm_list_2 (hspace_proc,                                                          scm_from_int (1)),                                              scm_list_2 (paren_proc, capo_markup)),                                  SCM_UNDEFINED);                                           chord_name_->set_property ("text", final_markup); I feel dirty after messing with that. ;) I haven't used scm_call, since the markup isn't evaluated until the stencil's created: the 'text property just stores the markup pending its conversion to a stencil via Text_interface::interpret_markup. BTW, I forgot that there's no word-space set for ChordName markup, since it would mess up the spacing of the individual elements, so I had to add some space using \hspace instead. Cheers, Neil --- ---- Join the Frogs!
Open this post in threaded view
|

## Re: chord-name-engraver plus capo - schemeing away ...

 In reply to this post by Neil Puttock  On 27/08/10 23:01, Neil Puttock wrote: > And as I said, you don't want to do this in C++.  There's a good > reason why line-markup' is only called outside scheme from the > parser: it's painful to juggle several markups this way, and separte > markups which should be stacked are usually treated as separate grobs > (or stacked internally by whatever function's doing the formatting). That makes it sound like you don't normally want to call Scheme from C++. From what I can see, you just pass two markups as a pair to it. Bear in mind I'm far more at home in C than Scheme at the moment (and I'm not juggling much) it doesn't seem that much of a problem. Looking at chord-name.scm and chord-ignatzek-names.scm, I just don't have a clue where to start. Looking at the C++ code, it seems simple. Or is it that passing the "layout props" bit is a pig? If I shouldn't be doing it in C++, where on earth do I start doing it in Scheme? (Bear in mind, I have on several previous occasions wanted to combine markups, and whether Scheme or lilypond, I've got nowhere trying to find out how to do it. Now I'm trying to find out how to do it in C++ and finding the same. It seems that combining markups is a "don't do it" in *any* language :-( How on earth DO I do it, ANYWHERE? Cheers, Wol --- ---- Join the Frogs!
Open this post in threaded view
|

## Re: chord-name-engraver plus capo - schemeing away ...

 In reply to this post by Neil Puttock  On 27/08/10 23:42, Neil Puttock wrote: > scm_cons does create a pair, but you need a list for the arguments to \line. > > Just to prove how nasty doing markup in C++ is, here's the above code corrected: > >   SCM paren_proc = ly_lily_module_constant ("parenthesize-markup"); >   SCM line_proc = ly_lily_module_constant ("line-markup"); >   SCM hspace_proc = ly_lily_module_constant ("hspace-markup"); >   SCM final_markup = scm_list_n (line_proc, > scm_list_3 (markup, >     scm_list_2 (hspace_proc, > scm_from_int (1)), >     scm_list_2 (paren_proc, capo_markup)), > SCM_UNDEFINED); > >   chord_name_->set_property ("text", final_markup); > > I feel dirty after messing with that. ;) :-) Thanks. I know it might feel awful to you, but as a non-schemer it doesn't seem that bad to me. I'll play with it, then when I write my next engraver I'll try to do it in Scheme and rewrite this for you :-) Cheers, Wol --- ---- Join the Frogs!
Open this post in threaded view
|

## Re: chord-name-engraver plus capo - schemeing away ...

 In reply to this post by Neil Puttock I'm sorry that I haven't been in on this conversation.   I've had a *very* unreliable internet connection for the past week. On 8/27/10 4:01 PM, "Neil Puttock" <[hidden email]> wrote: > On 27 August 2010 17:56, Wols Lists <[hidden email]> wrote: >>  On 27/08/10 17:18, Neil Puttock wrote: >>> On 27 August 2010 16:59, Wols Lists <[hidden email]> wrote: >>>>  Okay. I (think I) know how to call scheme from C++. And I've been told >>>> it's a lot easier to manipulate markup in scheme than C++. So I need to >>>> write two functions in scheme, and call them from my engraver. Help! :-) >>> I'm still not convinced you need a separate formatter. >> Because you've missed the entire point of what I'm doing. As far as I >> can tell, the formatter is chosen by the user - whether standard, >> ignaziek or whatever - and fed a series of notes. It then returns ONE >> chord to the engraver, which the engraver then prints. >> >> So if I did what you suggest, I would have to rewrite EVERY FORMATTER! >> (sorry for the shouting :-) > > There are only two styles (forget Banter, it doesn't work and will be > removed eventually).  Both are already somewhat modular in that they > rely on several library functions defined in scm/chord-name.scm, so it > shouldn't be too difficult to create a handler for capos which can be > slotted in to both formatters without excess duplication. There's a work in process to rewrite the chord name function.  I think that the approach that Anthony is taking is correct. > >> As modified, once capoFret is set, for every ONE chord fed INTO the >> engraver, it will spit TWO chords OUT. So I need some way of combining >> things. > > And as I said, you don't want to do this in C++.  There's a good > reason why `line-markup' is only called outside scheme from the > parser: it's painful to juggle several markups this way, and separte > markups which should be stacked are usually treated as separate grobs > (or stacked internally by whatever function's doing the formatting). I'd recommend that a scheme function be written (part of chord-name.scm) that takes two chord markups and an orientation, and spits out the appropriate chord markup.  Then you can just call the chord name procedure twice and the combiner once. Thanks, Carl --- ---- Join the Frogs!
Open this post in threaded view
|

## Re: chord-name-engraver plus capo - schemeing away ...

 On 28 August 2010 19:02, Carl Sorensen <[hidden email]> wrote: > There's a work in process to rewrite the chord name function.  I think that > the approach that Anthony is taking is correct. Is it ever going to be finished?  It's been in process for about a year unless I'm mistaken; you posted a patch on Rietveld from Thomas earlier this year, but I haven't seen progress since. I still think it's better to do this in scheme (and that doesn't mean as a scheme engraver); even if we ever get to the stage where the chord name infrastructure does get rewritten, it shouldn't prevent other enhancements being made earlier, especially if they're implemented in a modular fashion. Cheers, Neil --- ---- Join the Frogs!
Open this post in threaded view
|

## Re: chord-name-engraver plus capo - schemeing away ...

 In reply to this post by Wols Lists On 27 August 2010 23:59, Wols Lists <[hidden email]> wrote: > If I shouldn't be doing it in C++, where on earth do I start doing it in > Scheme? See the attached patch for a first draft (missing the conversion of capoFret to a transposition pitch). Cheers, Neil 0001-chord-and-capo-in-scheme.patch (3K) Download Attachment
Open this post in threaded view
|

## Re: chord-name-engraver plus capo - schemeing away ...

 In reply to this post by Neil Puttock  On 28/08/10 19:17, Neil Puttock wrote: > On 28 August 2010 19:02, Carl Sorensen <[hidden email]> wrote: > >> There's a work in process to rewrite the chord name function.  I think that >> the approach that Anthony is taking is correct. > Is it ever going to be finished?  It's been in process for about a > year unless I'm mistaken; you posted a patch on Rietveld from Thomas > earlier this year, but I haven't seen progress since. > > I still think it's better to do this in scheme (and that doesn't mean > as a scheme engraver); even if we ever get to the stage where the > chord name infrastructure does get rewritten, it shouldn't prevent > other enhancements being made earlier, especially if they're > implemented in a modular fashion. > > Cheers, > Neil > I'm quite happy to do it Scheme, and thanks for all the stuff you've sent/pointed me at to look at. Only thing is, at the moment it's as clear to me as double-italian (As a german-speaker (my second language), double-dutch isn't too bad ... :-) All being well, I'll start on the capo-indicating-engraver in Scheme tomorrow, so expect a flurry of "how on earth do I do this!" emails :-) Cheers, Wol --- ---- Join the Frogs!
Open this post in threaded view
|

## Re: chord-name-engraver plus capo - schemeing away ...

 In reply to this post by Carl Sorensen  On 28/08/10 19:02, Carl Sorensen wrote: > I'd recommend that a scheme function be written (part of chord-name.scm) > that takes two chord markups and an orientation, and spits out the > appropriate chord markup.  Then you can just call the chord name procedure > twice and the combiner once. Actually, wouldn't this be better in the markup functions? Write a generic function called combine-markup that just takes two markups, a flag to say next to each other or one above the other, and the gap (if any) between them. As I say, I've often wanted to combine markups and got totally frustrated (things like where I've got a rehearsal mark clashing with something else ...) Cheers, Wol --- ---- Join the Frogs!
Open this post in threaded view
|

## Re: chord-name-engraver plus capo - schemeing away ...

 On 8/29/10 2:34 PM, "Wols Lists" <[hidden email]> wrote: >  On 28/08/10 19:02, Carl Sorensen wrote: >> I'd recommend that a scheme function be written (part of chord-name.scm) >> that takes two chord markups and an orientation, and spits out the >> appropriate chord markup.  Then you can just call the chord name procedure >> twice and the combiner once. > Actually, wouldn't this be better in the markup functions? Write a > generic function called combine-markup that just takes two markups, a > flag to say next to each other or one above the other, and the gap (if > any) between them. There's already ly:stencil-combine-at-edge that does a combination of two stencils.  See Notation Reference, A.17. column and center-column can also be used to do the vertical alignment, and line does the horizontal alignment. Your function would call either one or the other of these, as well as parenthesize, in order to combine the two chord names. Thanks, Carl --- ---- Join the Frogs!
Open this post in threaded view
|

## Re: chord-name-engraver plus capo - schemeing away ...

 In reply to this post by Wols Lists On 8/29/10 1:43 PM, "Wols Lists" <[hidden email]> wrote: >  On 28/08/10 19:17, Neil Puttock wrote: >> On 28 August 2010 19:02, Carl Sorensen <[hidden email]> wrote: >> >>> There's a work in process to rewrite the chord name function.  I think that >>> the approach that Anthony is taking is correct. >> Is it ever going to be finished?  It's been in process for about a >> year unless I'm mistaken; you posted a patch on Rietveld from Thomas >> earlier this year, but I haven't seen progress since. >> >> I still think it's better to do this in scheme (and that doesn't mean >> as a scheme engraver); even if we ever get to the stage where the >> chord name infrastructure does get rewritten, it shouldn't prevent >> other enhancements being made earlier, especially if they're >> implemented in a modular fashion. >> >> Cheers, >> Neil >> > I'm quite happy to do it Scheme, and thanks for all the stuff you've > sent/pointed me at to look at. Only thing is, at the moment it's as > clear to me as double-italian (As a german-speaker (my second language), > double-dutch isn't too bad ... :-) > > All being well, I'll start on the capo-indicating-engraver in Scheme > tomorrow, so expect a flurry of "how on earth do I do this!" emails :-) Why do you want to do this as a scheme engraver?  It seems to sit very nicely as part of the ChordName engraver, which is already written.  Note that Neil's comment above indicates that he doesn't mean *as a scheme engraver*. Other than as an academic exercise to write an engraver in Scheme, this doesn't seem to me to be the best way to get the functionality you want. Thanks, Carl --- ---- Join the Frogs!
Open this post in threaded view
|

## Re: chord-name-engraver plus capo - schemeing away ...

 On 30/08/10 02:17, Carl Sorensen wrote: > > > On 8/29/10 1:43 PM, "Wols Lists" <[hidden email]> wrote: > >>  On 28/08/10 19:17, Neil Puttock wrote: >>> >> I'm quite happy to do it Scheme, and thanks for all the stuff you've >> sent/pointed me at to look at. Only thing is, at the moment it's as >> clear to me as double-italian (As a german-speaker (my second language), >> double-dutch isn't too bad ... :-) >> >> All being well, I'll start on the capo-indicating-engraver in Scheme >> tomorrow, so expect a flurry of "how on earth do I do this!" emails :-) > Why do you want to do this as a scheme engraver?  It seems to sit very > nicely as part of the ChordName engraver, which is already written.  Note > that Neil's comment above indicates that he doesn't mean *as a scheme > engraver*. Ummm. How do I do that then? I agree it makes a lot of sense, but this is the bit that returns "Capo 3 (A)", so I can't do it in process_music, because it's not processing music, afaict. And it needs a valid key signature, so I'll need to test that, etc etc. This is where I really need a bit of guidance and hand-holding because I'm now in the position of "I know what I want to do, but I don't know where to start, and I don't know what to look at". (That said, it's just struck me that maybe the key signature engraver would be a good place to look! I'll look there, but any guidance would be appreciated.) > Other than as an academic exercise to write an engraver in Scheme, this > doesn't seem to me to be the best way to get the functionality you want. > I got that Neil wasn't saying "do it in Scheme", but as I thought I needed a new engraver, I thought Scheme was the best language to do it in. Cheers, Wol --- ---- Join the Frogs!