A Javascript test code for modifying ties and slurs with mouse

classic Classic list List threaded Threaded
31 messages Options
12
Reply | Threaded
Open this post in threaded view
|

A Javascript test code for modifying ties and slurs with mouse

Paolo Prete-3
I just created a javascript script to change the slurs of the .svg file produced by Lilypond using the mouse, as I had announced. The coordinates of the control points of the associated Bezier curve can be reported in the corresponding .ly file and this completely avoids the time consuming trial and error process we were talking about. The script is 100% Javascript native, without any additional library and I tried it on the Firefox and Chromium browsers. Let's see how it works.

1) Create a score using the template that shows the control points, implemented by Aaron (please, re-indent it); I added a small change to set some attributes on the generated svg tags:

http://lilybin.com/29lnbd/4

2) Generate with Lilypond the .svg file and add to it the Javascript script implemented by me. To test everything, let's use JsFiddle:

https://jsfiddle.net/61pb9Le4/

My script is in the lower left pane; in the upper left pane I pasted the .svg file generated by Lilypond. Note that, to make the script work, if you create a new JsFiddle, you need to select  "LOAD TYPE" option =  "No wrap - bottom of <body>".

3) Modify the slurs by moving the control points with the mouse

4) The coordinates of the modified slur can be displayed by right-clicking on one of the slur's control points. A string will appear in the form:

 "shape # '((x1. y1) (x2. y2) (x1. y1) (x3. y3) (x4. y4)) PhrasingSlur"

or

 "shape # '((x1. y1) (x2. y2) (x1. y1) (x3. y3) (x4. y4)) Slur"

or

"shape # '((x1. y1) (x2. y2) (x1. y1) (x3. y3) (x4. y4)) Tie"

This string must be copied to the .ly file, near the slur to be modified.

.....................

I wrote all this really in a hurry, and the code needs to be improved at various points. But the first tests seem to work. Now I'm trying to figure out what is the best (and portable) way to automatically include the Javascript script in the .svg file generated by Lilypond ...

HTH
P

Reply | Threaded
Open this post in threaded view
|

Re: A Javascript test code for modifying ties and slurs with mouse

Flaming Hakama by Elaine

---------- Forwarded message ----------
From: Paolo Pr <[hidden email]>
To: lilypond-user <[hidden email]>
Cc: 
Bcc: 
Date: Thu, 12 Dec 2019 17:52:58 +0100
Subject: A Javascript test code for modifying ties and slurs with mouse
I just created a javascript script to change the slurs of the .svg file produced by Lilypond using the mouse, as I had announced. The coordinates of the control points of the associated Bezier curve can be reported in the corresponding .ly file and this completely avoids the time consuming trial and error process we were talking about. The script is 100% Javascript native, without any additional library and I tried it on the Firefox and Chromium browsers. Let's see how it works.

1) Create a score using the template that shows the control points, implemented by Aaron (please, re-indent it); I added a small change to set some attributes on the generated svg tags:

http://lilybin.com/29lnbd/4

2) Generate with Lilypond the .svg file and add to it the Javascript script implemented by me. To test everything, let's use JsFiddle:

https://jsfiddle.net/61pb9Le4/

My script is in the lower left pane; in the upper left pane I pasted the .svg file generated by Lilypond. Note that, to make the script work, if you create a new JsFiddle, you need to select  "LOAD TYPE" option =  "No wrap - bottom of <body>".

3) Modify the slurs by moving the control points with the mouse

4) The coordinates of the modified slur can be displayed by right-clicking on one of the slur's control points. A string will appear in the form:

 "shape # '((x1. y1) (x2. y2) (x1. y1) (x3. y3) (x4. y4)) PhrasingSlur"

or

 "shape # '((x1. y1) (x2. y2) (x1. y1) (x3. y3) (x4. y4)) Slur"

or

"shape # '((x1. y1) (x2. y2) (x1. y1) (x3. y3) (x4. y4)) Tie"

This string must be copied to the .ly file, near the slur to be modified.

.....................

I wrote all this really in a hurry, and the code needs to be improved at various points. But the first tests seem to work. Now I'm trying to figure out what is the best (and portable) way to automatically include the Javascript script in the .svg file generated by Lilypond ...

HTH
P

 
This is fantastic!

I often leave mediocre slurs and ties as is, just because wrangling them in code is a pain.  This will make it much more likely that I'll have the bandwidth to improve them.

This may help folks who want to try this out, here is how I understand the intended approach and how I was able to reproduce it locally.


1) Prepare the score for control point tweaking

Include in your lilypond files this new definition

showControlPoints = #(grob-transformer 'stencil (lambda (grob orig)
...

As well as this layout context

\layout {
\context {
\Voice
\override PhrasingSlur.stencil = #showControlPoints
\override PhrasingSlur.output-attributes = #'((class . "lilySlur")(slurtype . "PhrasingSlur"))
\override Slur.stencil = #showControlPoints
\override Slur.output-attributes = #'((class . "lilySlur")(slurtype . "Slur"))
\override Tie.stencil = #showControlPoints
\override Tie.output-attributes = #'((class . "lilySlur")(slurtype . "Tie"))  
}
}

2) Create the SVG version.

run lilypond with the option -dbackend=svg


3) Create an HTML page that allows editing

Save the JavaScript code in a file, such as show-control-points.js.

Create an HTML document like this:

<html>
<head><title>Editing Lilypond curves</title>
</head>
<body>
<svg...>...</svg>
<script src="show-control-points.js"></script>
</body>
</html>


I tried to figure out how to include the SVG file by reference, but either using <img src=""> or <object src="">.  But that did not work, since it would produce objects that do not have width or height attributes accessible via JavaScript.  Seems like the SVG has to be inline in the HTML document for this approach to work.

In terms of workflow, I would probably create this HTML document subsequent to creating the SVG using a script:

#!/usr/local/bin/bash
# Usage: create-html-for-svg.sh svgFileName htmlFileName
SVG=$1
HTML=$1
echo "<html>" > $HTML
echo "<head><title>Editing Lilypond curves</title>" >> $HTML
echo "</head>" >> $HTML
echo "<body>" >> $HTML
echo "" >> $HTML
cat $SVG >> $HTML
echo "" >> $HTML
echo "<script src="edit-control-points.js"></script>" >> $HTML
echo "</body>" >> $HTML
echo "</html>" >> $HTML
echo "" >> $HTML

Then invoke it like:
$ create-html-for-svg.sh example.svg edit-curves.html


4) Open HTML page in a browser and edit curves

move the points around, right click to get the \shape definition,


5) Update lilypond source

For each curve you modify, apply that shape modification in your lilyond source.

To generate the final document, remove the \layout section that we added in step 1.



Thanks, 

Elaine Alt
415 . 341 .4954                                           "Confusion is highly underrated"
[hidden email]
Producer ~ Composer ~ Instrumentalist ~ Educator
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
 
Reply | Threaded
Open this post in threaded view
|

Re: A Javascript test code for modifying ties and slurs with mouse

Urs Liska-3

I have to second Elaine's comment.
Due to a very heavy workload right now I didn't have the opportunity to have a look at your example earlier,  but now I *really* like what I see.

I think that you a) probably should go forward implementing a standalone solution of your approach, but that b) this should also be integrated into Frescobaldi, because this would probably kick it off and make it even more widely known. Plus, Frescobaldi should make it easier to write the code back into the LilyPond file. There are 2-3 people who would be more than willing to help you with the integration of the functionality in Frescobaldi.

Best
Urs

Am 13.12.19 um 23:49 schrieb Flaming Hakama by Elaine:

---------- Forwarded message ----------
From: Paolo Pr <[hidden email]>
To: lilypond-user <[hidden email]>
Cc: 
Bcc: 
Date: Thu, 12 Dec 2019 17:52:58 +0100
Subject: A Javascript test code for modifying ties and slurs with mouse
I just created a javascript script to change the slurs of the .svg file produced by Lilypond using the mouse, as I had announced. The coordinates of the control points of the associated Bezier curve can be reported in the corresponding .ly file and this completely avoids the time consuming trial and error process we were talking about. The script is 100% Javascript native, without any additional library and I tried it on the Firefox and Chromium browsers. Let's see how it works.

1) Create a score using the template that shows the control points, implemented by Aaron (please, re-indent it); I added a small change to set some attributes on the generated svg tags:

http://lilybin.com/29lnbd/4

2) Generate with Lilypond the .svg file and add to it the Javascript script implemented by me. To test everything, let's use JsFiddle:

https://jsfiddle.net/61pb9Le4/

My script is in the lower left pane; in the upper left pane I pasted the .svg file generated by Lilypond. Note that, to make the script work, if you create a new JsFiddle, you need to select  "LOAD TYPE" option =  "No wrap - bottom of <body>".

3) Modify the slurs by moving the control points with the mouse

4) The coordinates of the modified slur can be displayed by right-clicking on one of the slur's control points. A string will appear in the form:

 "shape # '((x1. y1) (x2. y2) (x1. y1) (x3. y3) (x4. y4)) PhrasingSlur"

or

 "shape # '((x1. y1) (x2. y2) (x1. y1) (x3. y3) (x4. y4)) Slur"

or

"shape # '((x1. y1) (x2. y2) (x1. y1) (x3. y3) (x4. y4)) Tie"

This string must be copied to the .ly file, near the slur to be modified.

.....................

I wrote all this really in a hurry, and the code needs to be improved at various points. But the first tests seem to work. Now I'm trying to figure out what is the best (and portable) way to automatically include the Javascript script in the .svg file generated by Lilypond ...

HTH
P

 
This is fantastic!

I often leave mediocre slurs and ties as is, just because wrangling them in code is a pain.  This will make it much more likely that I'll have the bandwidth to improve them.

This may help folks who want to try this out, here is how I understand the intended approach and how I was able to reproduce it locally.


1) Prepare the score for control point tweaking

Include in your lilypond files this new definition

showControlPoints = #(grob-transformer 'stencil (lambda (grob orig)
...

As well as this layout context

\layout {
\context {
\Voice
\override PhrasingSlur.stencil = #showControlPoints
\override PhrasingSlur.output-attributes = #'((class . "lilySlur")(slurtype . "PhrasingSlur"))
\override Slur.stencil = #showControlPoints
\override Slur.output-attributes = #'((class . "lilySlur")(slurtype . "Slur"))
\override Tie.stencil = #showControlPoints
\override Tie.output-attributes = #'((class . "lilySlur")(slurtype . "Tie"))  
}
}

2) Create the SVG version.

run lilypond with the option -dbackend=svg


3) Create an HTML page that allows editing

Save the JavaScript code in a file, such as show-control-points.js.

Create an HTML document like this:

<html>
<head><title>Editing Lilypond curves</title>
</head>
<body>
<svg...>...</svg>
<script src="show-control-points.js"></script>
</body>
</html>


I tried to figure out how to include the SVG file by reference, but either using <img src=""> or <object src="">.  But that did not work, since it would produce objects that do not have width or height attributes accessible via JavaScript.  Seems like the SVG has to be inline in the HTML document for this approach to work.

In terms of workflow, I would probably create this HTML document subsequent to creating the SVG using a script:

#!/usr/local/bin/bash
# Usage: create-html-for-svg.sh svgFileName htmlFileName
SVG=$1
HTML=$1
echo "<html>" > $HTML
echo "<head><title>Editing Lilypond curves</title>" >> $HTML
echo "</head>" >> $HTML
echo "<body>" >> $HTML
echo "" >> $HTML
cat $SVG >> $HTML
echo "" >> $HTML
echo "<script src="edit-control-points.js"></script>" >> $HTML
echo "</body>" >> $HTML
echo "</html>" >> $HTML
echo "" >> $HTML

Then invoke it like:
$ create-html-for-svg.sh example.svg edit-curves.html


4) Open HTML page in a browser and edit curves

move the points around, right click to get the \shape definition,


5) Update lilypond source

For each curve you modify, apply that shape modification in your lilyond source.

To generate the final document, remove the \layout section that we added in step 1.



Thanks, 

Elaine Alt
415 . 341 .4954                                           "Confusion is highly underrated"
[hidden email]
Producer ~ Composer ~ Instrumentalist ~ Educator
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
 
Reply | Threaded
Open this post in threaded view
|

Re: A Javascript test code for modifying ties and slurs with mouse

Paolo Prete-3
Thanks Urs and Elaine for your appreciation.

Note that the same algo I wrote  with (relatively) short code can be applied for many other properties as well (for example: extra-offset) which are painful to control through the trial and error method...
I'll be on #irc (channel #lilypond) in the next days, so I can talk easily there with any (welcome) collaborator. My nickname is 'paolopr'. 
Before integrating the script into Frescobaldi, I would like to conclude the standalone part. 

First of all, I need to add with Lilypond a <script>  tag to the svg file just before the ending </svg> tag  in the following way:

1) 
....
 <script xlink:href="lilyEasySlurs.js"></script>
</svg> 

OR in the following way:

2)
....
<script>
<![CDATA[
    ...javascript code...
]]>
</script>
</svg>

With method 2) I have a 100% Lilypond solution, and the produced svg is ready do be used for modifying slurs, without having to integrate the script manually
I searched in the API, but could not find any function for doing that. 

To Eliane: note that you don't have to make a HTML document for that, nor to rename to ".html" the ".svg" file. Just add the <script> tag as I explained (note the xlink:href property) before the end </svg> tag., and open the file with a normal browser.
As soon as we fix points 1) and 2) I can write a how-to, which will be very short.

Best,
P


On Sat, Dec 14, 2019 at 12:40 AM Urs Liska <[hidden email]> wrote:

I have to second Elaine's comment.
Due to a very heavy workload right now I didn't have the opportunity to have a look at your example earlier,  but now I *really* like what I see.

I think that you a) probably should go forward implementing a standalone solution of your approach, but that b) this should also be integrated into Frescobaldi, because this would probably kick it off and make it even more widely known. Plus, Frescobaldi should make it easier to write the code back into the LilyPond file. There are 2-3 people who would be more than willing to help you with the integration of the functionality in Frescobaldi.

Best
Urs

Am 13.12.19 um 23:49 schrieb Flaming Hakama by Elaine:

---------- Forwarded message ----------
From: Paolo Pr <[hidden email]>
To: lilypond-user <[hidden email]>
Cc: 
Bcc: 
Date: Thu, 12 Dec 2019 17:52:58 +0100
Subject: A Javascript test code for modifying ties and slurs with mouse
I just created a javascript script to change the slurs of the .svg file produced by Lilypond using the mouse, as I had announced. The coordinates of the control points of the associated Bezier curve can be reported in the corresponding .ly file and this completely avoids the time consuming trial and error process we were talking about. The script is 100% Javascript native, without any additional library and I tried it on the Firefox and Chromium browsers. Let's see how it works.

1) Create a score using the template that shows the control points, implemented by Aaron (please, re-indent it); I added a small change to set some attributes on the generated svg tags:

http://lilybin.com/29lnbd/4

2) Generate with Lilypond the .svg file and add to it the Javascript script implemented by me. To test everything, let's use JsFiddle:

https://jsfiddle.net/61pb9Le4/

My script is in the lower left pane; in the upper left pane I pasted the .svg file generated by Lilypond. Note that, to make the script work, if you create a new JsFiddle, you need to select  "LOAD TYPE" option =  "No wrap - bottom of <body>".

3) Modify the slurs by moving the control points with the mouse

4) The coordinates of the modified slur can be displayed by right-clicking on one of the slur's control points. A string will appear in the form:

 "shape # '((x1. y1) (x2. y2) (x1. y1) (x3. y3) (x4. y4)) PhrasingSlur"

or

 "shape # '((x1. y1) (x2. y2) (x1. y1) (x3. y3) (x4. y4)) Slur"

or

"shape # '((x1. y1) (x2. y2) (x1. y1) (x3. y3) (x4. y4)) Tie"

This string must be copied to the .ly file, near the slur to be modified.

.....................

I wrote all this really in a hurry, and the code needs to be improved at various points. But the first tests seem to work. Now I'm trying to figure out what is the best (and portable) way to automatically include the Javascript script in the .svg file generated by Lilypond ...

HTH
P

 
This is fantastic!

I often leave mediocre slurs and ties as is, just because wrangling them in code is a pain.  This will make it much more likely that I'll have the bandwidth to improve them.

This may help folks who want to try this out, here is how I understand the intended approach and how I was able to reproduce it locally.


1) Prepare the score for control point tweaking

Include in your lilypond files this new definition

showControlPoints = #(grob-transformer 'stencil (lambda (grob orig)
...

As well as this layout context

\layout {
\context {
\Voice
\override PhrasingSlur.stencil = #showControlPoints
\override PhrasingSlur.output-attributes = #'((class . "lilySlur")(slurtype . "PhrasingSlur"))
\override Slur.stencil = #showControlPoints
\override Slur.output-attributes = #'((class . "lilySlur")(slurtype . "Slur"))
\override Tie.stencil = #showControlPoints
\override Tie.output-attributes = #'((class . "lilySlur")(slurtype . "Tie"))  
}
}

2) Create the SVG version.

run lilypond with the option -dbackend=svg


3) Create an HTML page that allows editing

Save the JavaScript code in a file, such as show-control-points.js.

Create an HTML document like this:

<html>
<head><title>Editing Lilypond curves</title>
</head>
<body>
<svg...>...</svg>
<script src="show-control-points.js"></script>
</body>
</html>


I tried to figure out how to include the SVG file by reference, but either using <img src=""> or <object src="">.  But that did not work, since it would produce objects that do not have width or height attributes accessible via JavaScript.  Seems like the SVG has to be inline in the HTML document for this approach to work.

In terms of workflow, I would probably create this HTML document subsequent to creating the SVG using a script:

#!/usr/local/bin/bash
# Usage: create-html-for-svg.sh svgFileName htmlFileName
SVG=$1
HTML=$1
echo "<html>" > $HTML
echo "<head><title>Editing Lilypond curves</title>" >> $HTML
echo "</head>" >> $HTML
echo "<body>" >> $HTML
echo "" >> $HTML
cat $SVG >> $HTML
echo "" >> $HTML
echo "<script src="edit-control-points.js"></script>" >> $HTML
echo "</body>" >> $HTML
echo "</html>" >> $HTML
echo "" >> $HTML

Then invoke it like:
$ create-html-for-svg.sh example.svg edit-curves.html


4) Open HTML page in a browser and edit curves

move the points around, right click to get the \shape definition,


5) Update lilypond source

For each curve you modify, apply that shape modification in your lilyond source.

To generate the final document, remove the \layout section that we added in step 1.



Thanks, 

Elaine Alt
415 . 341 .4954                                           "Confusion is highly underrated"
[hidden email]
Producer ~ Composer ~ Instrumentalist ~ Educator
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
 
Reply | Threaded
Open this post in threaded view
|

Re: A Javascript test code for modifying ties and slurs with mouse

Carl Sorensen-3
In reply to this post by Urs Liska-3

Paolo,

 

I really appreciate your doing this.

 

However, I would like to see us improve the *automatic* handling of slurs in LilyPond, so that \shape is almost never needed (much like extra-offset for standard music).  I’m not asking for you to do any work on improving the automatic slur handling, but I would love to have us have a collection of slurs automatically created by LilyPond along with the revised slurs created by \shape.  That would give us a test library to be able to test improvements in the LilyPond slur code.

 

I’ve created issue #5638

https://sourceforge.net/p/testlilyissues/issues/5638/

as a place for users to place snippets that give bad automatic slurs and that show improved slurs by using \shape.   I’d invite everybody who finds ugly slurs to post both the ugly slur code and the improved slur code.

 

Thanks,

 

Carl

 

 

From: Urs Liska <[hidden email]>
Date: Friday, December 13, 2019 at 4:40 PM
To: <[hidden email]>
Subject: Re: A Javascript test code for modifying ties and slurs with mouse

 

I have to second Elaine's comment.
Due to a very heavy workload right now I didn't have the opportunity to have a look at your example earlier,  but now I *really* like what I see.

I think that you a) probably should go forward implementing a standalone solution of your approach, but that b) this should also be integrated into Frescobaldi, because this would probably kick it off and make it even more widely known. Plus, Frescobaldi should make it easier to write the code back into the LilyPond file. There are 2-3 people who would be more than willing to help you with the integration of the functionality in Frescobaldi.

Best
Urs

Am 13.12.19 um 23:49 schrieb Flaming Hakama by Elaine:

 

---------- Forwarded message ----------
From: Paolo Pr <[hidden email]>
To: lilypond-user <[hidden email]>
Cc: 
Bcc: 
Date: Thu, 12 Dec 2019 17:52:58 +0100
Subject: A Javascript test code for modifying ties and slurs with mouse

I just created a javascript script to change the slurs of the .svg file produced by Lilypond using the mouse, as I had announced. The coordinates of the control points of the associated Bezier curve can be reported in the corresponding .ly file and this completely avoids the time consuming trial and error process we were talking about. The script is 100% Javascript native, without any additional library and I tried it on the Firefox and Chromium browsers. Let's see how it works.

1) Create a score using the template that shows the control points, implemented by Aaron (please, re-indent it); I added a small change to set some attributes on the generated svg tags:

http://lilybin.com/29lnbd/4

2) Generate with Lilypond the .svg file and add to it the Javascript script implemented by me. To test everything, let's use JsFiddle:

https://jsfiddle.net/61pb9Le4/

My script is in the lower left pane; in the upper left pane I pasted the .svg file generated by Lilypond. Note that, to make the script work, if you create a new JsFiddle, you need to select  "LOAD TYPE" option =  "No wrap - bottom of <body>".

3) Modify the slurs by moving the control points with the mouse

4) The coordinates of the modified slur can be displayed by right-clicking on one of the slur's control points. A string will appear in the form:

 "shape # '((x1. y1) (x2. y2) (x1. y1) (x3. y3) (x4. y4)) PhrasingSlur"

or

 "shape # '((x1. y1) (x2. y2) (x1. y1) (x3. y3) (x4. y4)) Slur"

or

"shape # '((x1. y1) (x2. y2) (x1. y1) (x3. y3) (x4. y4)) Tie"

This string must be copied to the .ly file, near the slur to be modified.

.....................

I wrote all this really in a hurry, and the code needs to be improved at various points. But the first tests seem to work. Now I'm trying to figure out what is the best (and portable) way to automatically include the Javascript script in the .svg file generated by Lilypond ...

HTH
P

 

This is fantastic!

I often leave mediocre slurs and ties as is, just because wrangling them in code is a pain.  This will make it much more likely that I'll have the bandwidth to improve them.

This may help folks who want to try this out, here is how I understand the intended approach and how I was able to reproduce it locally.


1) Prepare the score for control point tweaking

Include in your lilypond files this new definition

showControlPoints = #(grob-transformer 'stencil (lambda (grob orig)
...

As well as this layout context

\layout {
\context {
\Voice
\override PhrasingSlur.stencil = #showControlPoints
\override PhrasingSlur.output-attributes = #'((class . "lilySlur")(slurtype . "PhrasingSlur"))
\override Slur.stencil = #showControlPoints
\override Slur.output-attributes = #'((class . "lilySlur")(slurtype . "Slur"))
\override Tie.stencil = #showControlPoints
\override Tie.output-attributes = #'((class . "lilySlur")(slurtype . "Tie"))  
}
}

2) Create the SVG version.

run lilypond with the option -dbackend=svg


3) Create an HTML page that allows editing

Save the JavaScript code in a file, such as show-control-points.js.

Create an HTML document like this:

<html>
<head><title>Editing Lilypond curves</title>
</head>
<body>
<svg...>...</svg>
<script src="show-control-points.js"></script>
</body>
</html>


I tried to figure out how to include the SVG file by reference, but either using <img src=""> or <object src="">.  But that did not work, since it would produce objects that do not have width or height attributes accessible via JavaScript.  Seems like the SVG has to be inline in the HTML document for this approach to work.

In terms of workflow, I would probably create this HTML document subsequent to creating the SVG using a script:

#!/usr/local/bin/bash
# Usage: create-html-for-svg.sh svgFileName htmlFileName
SVG=$1
HTML=$1
echo "<html>" > $HTML
echo "<head><title>Editing Lilypond curves</title>" >> $HTML
echo "</head>" >> $HTML
echo "<body>" >> $HTML
echo "" >> $HTML
cat $SVG >> $HTML
echo "" >> $HTML
echo "<script src="edit-control-points.js"></script>" >> $HTML
echo "</body>" >> $HTML
echo "</html>" >> $HTML
echo "" >> $HTML

Then invoke it like:
$ create-html-for-svg.sh example.svg edit-curves.html


4) Open HTML page in a browser and edit curves

move the points around, right click to get the \shape definition,


5) Update lilypond source

For each curve you modify, apply that shape modification in your lilyond source.

To generate the final document, remove the \layout section that we added in step 1.



Thanks, 

 

Elaine Alt

415 . 341 .4954                                           "Confusion is highly underrated"

[hidden email]

Producer ~ Composer ~ Instrumentalist ~ Educator
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

 

Reply | Threaded
Open this post in threaded view
|

Re: A Javascript test code for modifying ties and slurs with mouse

Aaron Hill
In reply to this post by Paolo Prete-3
On 2019-12-13 5:59 pm, Paolo Pr wrote:

> First of all, I need to add with Lilypond a <script>  tag to the svg
> file
> just before the ending </svg> tag  in the following way:
>
> 1)
> ....
>  <script xlink:href="lilyEasySlurs.js"></script>
> </svg>
>
> OR in the following way:
>
> 2)
> ....
> <script>
> <![CDATA[
>     ...javascript code...
> ]]>
> </script>
> </svg>

Well, one could use (abuse?) the embedded-svg stencil command:

%%%%
\version "2.19.83"

svg-script = #(define-scheme-function (body) (string?)
   (markup #:stencil (ly:make-stencil (list 'embedded-svg
     (string-join (list "<script type=\"text/javascript\"><![CDATA["
       body "]]></script>") "\n")) '(0 . 0) '(0 . 0))))

{ g'4 a' \tweak Accidental.output-attributes #'((id . "flat")) bes'2 }

\svg-script
#"var flat = document.getElementById('flat');
   flat.style.color = 'red';
   function spin(what, amount) {
     let angle = 0.0;
     return function () {
       const bbox = what.getBBox();
       const xform = ['rotate(',
         (angle = (angle + amount) % 360.0),
         bbox.x + 0.5 * bbox.width,
         bbox.y + 0.75 * bbox.height, ')'];
       what.setAttribute('transform', xform.join(' '));
     }
   }
   setInterval(spin(flat, 5), 100);"
%%%%

This adds a top-level \markup that contains a stencil to instruct
output-svg.scm to write the specified string to the output.


-- Aaron Hill

Reply | Threaded
Open this post in threaded view
|

Re: A Javascript test code for modifying ties and slurs with mouse

Paolo Prete-3
In reply to this post by Carl Sorensen-3
Hello Carl,

my script is not intended for replacing the automatic handling of slurs. I agree that the automatic handling should be the preferred way and the development of the script is somewhat "off-topic" here (but I did not know the right ml where to post it and I needed some other help for coding in Scheme). 
However, I think that the manual placement is necessary in two cases, even with a "perfect" Lilypond:

1) for very complex scores (for example: contemporary classical music)
2) when the automatic placement is correct (no collisions), but not good to see.

I think then that the two features can coexist. Consider that the few lines of codes I wrote show another feature of Lilypond: it can generate svg for easy-scripting too...

Best,
P

On Sat, Dec 14, 2019 at 3:49 AM Carl Sorensen <[hidden email]> wrote:

Paolo,

 

I really appreciate your doing this.

 

However, I would like to see us improve the *automatic* handling of slurs in LilyPond, so that \shape is almost never needed (much like extra-offset for standard music).  I’m not asking for you to do any work on improving the automatic slur handling, but I would love to have us have a collection of slurs automatically created by LilyPond along with the revised slurs created by \shape.  That would give us a test library to be able to test improvements in the LilyPond slur code.

 

I’ve created issue #5638

https://sourceforge.net/p/testlilyissues/issues/5638/

as a place for users to place snippets that give bad automatic slurs and that show improved slurs by using \shape.   I’d invite everybody who finds ugly slurs to post both the ugly slur code and the improved slur code.

 

Thanks,

 

Carl

 

 

From: Urs Liska <[hidden email]>
Date: Friday, December 13, 2019 at 4:40 PM
To: <[hidden email]>
Subject: Re: A Javascript test code for modifying ties and slurs with mouse

 

I have to second Elaine's comment.
Due to a very heavy workload right now I didn't have the opportunity to have a look at your example earlier,  but now I *really* like what I see.

I think that you a) probably should go forward implementing a standalone solution of your approach, but that b) this should also be integrated into Frescobaldi, because this would probably kick it off and make it even more widely known. Plus, Frescobaldi should make it easier to write the code back into the LilyPond file. There are 2-3 people who would be more than willing to help you with the integration of the functionality in Frescobaldi.

Best
Urs

Am 13.12.19 um 23:49 schrieb Flaming Hakama by Elaine:

 

---------- Forwarded message ----------
From: Paolo Pr <[hidden email]>
To: lilypond-user <[hidden email]>
Cc: 
Bcc: 
Date: Thu, 12 Dec 2019 17:52:58 +0100
Subject: A Javascript test code for modifying ties and slurs with mouse

I just created a javascript script to change the slurs of the .svg file produced by Lilypond using the mouse, as I had announced. The coordinates of the control points of the associated Bezier curve can be reported in the corresponding .ly file and this completely avoids the time consuming trial and error process we were talking about. The script is 100% Javascript native, without any additional library and I tried it on the Firefox and Chromium browsers. Let's see how it works.

1) Create a score using the template that shows the control points, implemented by Aaron (please, re-indent it); I added a small change to set some attributes on the generated svg tags:

http://lilybin.com/29lnbd/4

2) Generate with Lilypond the .svg file and add to it the Javascript script implemented by me. To test everything, let's use JsFiddle:

https://jsfiddle.net/61pb9Le4/

My script is in the lower left pane; in the upper left pane I pasted the .svg file generated by Lilypond. Note that, to make the script work, if you create a new JsFiddle, you need to select  "LOAD TYPE" option =  "No wrap - bottom of <body>".

3) Modify the slurs by moving the control points with the mouse

4) The coordinates of the modified slur can be displayed by right-clicking on one of the slur's control points. A string will appear in the form:

 "shape # '((x1. y1) (x2. y2) (x1. y1) (x3. y3) (x4. y4)) PhrasingSlur"

or

 "shape # '((x1. y1) (x2. y2) (x1. y1) (x3. y3) (x4. y4)) Slur"

or

"shape # '((x1. y1) (x2. y2) (x1. y1) (x3. y3) (x4. y4)) Tie"

This string must be copied to the .ly file, near the slur to be modified.

.....................

I wrote all this really in a hurry, and the code needs to be improved at various points. But the first tests seem to work. Now I'm trying to figure out what is the best (and portable) way to automatically include the Javascript script in the .svg file generated by Lilypond ...

HTH
P

 

This is fantastic!

I often leave mediocre slurs and ties as is, just because wrangling them in code is a pain.  This will make it much more likely that I'll have the bandwidth to improve them.

This may help folks who want to try this out, here is how I understand the intended approach and how I was able to reproduce it locally.


1) Prepare the score for control point tweaking

Include in your lilypond files this new definition

showControlPoints = #(grob-transformer 'stencil (lambda (grob orig)
...

As well as this layout context

\layout {
\context {
\Voice
\override PhrasingSlur.stencil = #showControlPoints
\override PhrasingSlur.output-attributes = #'((class . "lilySlur")(slurtype . "PhrasingSlur"))
\override Slur.stencil = #showControlPoints
\override Slur.output-attributes = #'((class . "lilySlur")(slurtype . "Slur"))
\override Tie.stencil = #showControlPoints
\override Tie.output-attributes = #'((class . "lilySlur")(slurtype . "Tie"))  
}
}

2) Create the SVG version.

run lilypond with the option -dbackend=svg


3) Create an HTML page that allows editing

Save the JavaScript code in a file, such as show-control-points.js.

Create an HTML document like this:

<html>
<head><title>Editing Lilypond curves</title>
</head>
<body>
<svg...>...</svg>
<script src="show-control-points.js"></script>
</body>
</html>


I tried to figure out how to include the SVG file by reference, but either using <img src=""> or <object src="">.  But that did not work, since it would produce objects that do not have width or height attributes accessible via JavaScript.  Seems like the SVG has to be inline in the HTML document for this approach to work.

In terms of workflow, I would probably create this HTML document subsequent to creating the SVG using a script:

#!/usr/local/bin/bash
# Usage: create-html-for-svg.sh svgFileName htmlFileName
SVG=$1
HTML=$1
echo "<html>" > $HTML
echo "<head><title>Editing Lilypond curves</title>" >> $HTML
echo "</head>" >> $HTML
echo "<body>" >> $HTML
echo "" >> $HTML
cat $SVG >> $HTML
echo "" >> $HTML
echo "<script src="edit-control-points.js"></script>" >> $HTML
echo "</body>" >> $HTML
echo "</html>" >> $HTML
echo "" >> $HTML

Then invoke it like:
$ create-html-for-svg.sh example.svg edit-curves.html


4) Open HTML page in a browser and edit curves

move the points around, right click to get the \shape definition,


5) Update lilypond source

For each curve you modify, apply that shape modification in your lilyond source.

To generate the final document, remove the \layout section that we added in step 1.



Thanks, 

 

Elaine Alt

415 . 341 .4954                                           "Confusion is highly underrated"

[hidden email]

Producer ~ Composer ~ Instrumentalist ~ Educator
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

 

Reply | Threaded
Open this post in threaded view
|

Re: A Javascript test code for modifying ties and slurs with mouse

Carl Sorensen-3

 

 

From: Paolo Pr <[hidden email]>
Date: Friday, December 13, 2019 at 8:38 PM
To: Carl Sorensen <[hidden email]>
Cc: Urs Liska <[hidden email]>, "[hidden email]" <[hidden email]>
Subject: Re: A Javascript test code for modifying ties and slurs with mouse

 

Hello Carl,

 

my script is not intended for replacing the automatic handling of slurs. I agree that the automatic handling should be the preferred way and the development of the script is somewhat "off-topic" here (but I did not know the right ml where to post it and I needed some other help for coding in Scheme). 

 

I totally understand that your script is just intended to simplify the manual placing of slurs.  And it’s a great tool to have in our engraving toolbox.  I’m glad you’re writing it, and providing a graphical way to handle things.  Thanks for doing it.  But I’m concerned that we’ll rely too much on the manual tool instead of improving the automatic tool, which is the main goal of LilyPond.

 

However, I think that the manual placement is necessary in two cases, even with a "perfect" Lilypond:

 

  1. for very complex scores (for example: contemporary classical music)

It’s possible that contemporary music may be too complex for automatic slur creation to handle.

 

  1. when the automatic placement is correct (no collisions), but not good to see.

 

I don’t agree that this would be necessary if we had a “perfect” lilypond.  But I don’t know that we can ever get a “perfect” lilypond.  I hope we can get a *better* lilypond.  Currently lilypond creates several different collision-free placements and selects the best one based on a number of different demerits (measures of ugly slurs).  I believe that we can develop better automatic slur creation.  The first step to this is to have some correct, but not good to see, examples, along with better examples.  Then we can try to improve the automatic parameters.

 

I think then that the two features can coexist. Consider that the few lines of codes I wrote show another feature of Lilypond: it can generate svg for easy-scripting too...

 

Unquestionably the two features can coexist.  I just hope we can collect enough examples to improve the automatic workings.

 

Thanks,

 

Carl

 

Reply | Threaded
Open this post in threaded view
|

Re: A Javascript test code for modifying ties and slurs with mouse

Urs Liska-3
I'd just like to add that the trade-off between simplifying manual tweaking and better automatic result has always been an issue of discussion. IIRC it had also been raised in oppodition to including \shape...

Urs


Am 14. Dezember 2019 04:46:17 MEZ schrieb Carl Sorensen <[hidden email]>:

 

 

From: Paolo Pr <[hidden email]>
Date: Friday, December 13, 2019 at 8:38 PM
To: Carl Sorensen <[hidden email]>
Cc: Urs Liska <[hidden email]>, "[hidden email]" <[hidden email]>
Subject: Re: A Javascript test code for modifying ties and slurs with mouse

 

Hello Carl,

 

my script is not intended for replacing the automatic handling of slurs. I agree that the automatic handling should be the preferred way and the development of the script is somewhat "off-topic" here (but I did not know the right ml where to post it and I needed some other help for coding in Scheme). 

 

I totally understand that your script is just intended to simplify the manual placing of slurs.  And it’s a great tool to have in our engraving toolbox.  I’m glad you’re writing it, and providing a graphical way to handle things.  Thanks for doing it.  But I’m concerned that we’ll rely too much on the manual tool instead of improving the automatic tool, which is the main goal of LilyPond.

 

However, I think that the manual placement is necessary in two cases, even with a "perfect" Lilypond:

 

  1. for very complex scores (for example: contemporary classical music)

It’s possible that contemporary music may be too complex for automatic slur creation to handle.

 

  1. when the automatic placement is correct (no collisions), but not good to see.

 

I don’t agree that this would be necessary if we had a “perfect” lilypond.  But I don’t know that we can ever get a “perfect” lilypond.  I hope we can get a *better* lilypond.  Currently lilypond creates several different collision-free placements and selects the best one based on a number of different demerits (measures of ugly slurs).  I believe that we can develop better automatic slur creation.  The first step to this is to have some correct, but not good to see, examples, along with better examples.  Then we can try to improve the automatic parameters.

 

I think then that the two features can coexist. Consider that the few lines of codes I wrote show another feature of Lilypond: it can generate svg for easy-scripting too...

 

Unquestionably the two features can coexist.  I just hope we can collect enough examples to improve the automatic workings.

 

Thanks,

 

Carl

 


--
Diese Nachricht wurde von meinem Android-Gerät mit K-9 Mail gesendet.
Reply | Threaded
Open this post in threaded view
|

Re: A Javascript test code for modifying ties and slurs with mouse

Paolo Prete-3
In reply to this post by Aaron Hill
Thanks Aaron, it did the trick.

However, how can I make it work for multiple pages output?

On Sat, Dec 14, 2019 at 4:26 AM Aaron Hill <[hidden email]> wrote:
On 2019-12-13 5:59 pm, Paolo Pr wrote:
> First of all, I need to add with Lilypond a <script>  tag to the svg
> file
> just before the ending </svg> tag  in the following way:
>
> 1)
> ....
>  <script xlink:href="lilyEasySlurs.js"></script>
> </svg>
>
> OR in the following way:
>
> 2)
> ....
> <script>
> <![CDATA[
>     ...javascript code...
> ]]>
> </script>
> </svg>

Well, one could use (abuse?) the embedded-svg stencil command:

%%%%
\version "2.19.83"

svg-script = #(define-scheme-function (body) (string?)
   (markup #:stencil (ly:make-stencil (list 'embedded-svg
     (string-join (list "<script type=\"text/javascript\"><![CDATA["
       body "]]></script>") "\n")) '(0 . 0) '(0 . 0))))

{ g'4 a' \tweak Accidental.output-attributes #'((id . "flat")) bes'2 }

\svg-script
#"var flat = document.getElementById('flat');
   flat.style.color = 'red';
   function spin(what, amount) {
     let angle = 0.0;
     return function () {
       const bbox = what.getBBox();
       const xform = ['rotate(',
         (angle = (angle + amount) % 360.0),
         bbox.x + 0.5 * bbox.width,
         bbox.y + 0.75 * bbox.height, ')'];
       what.setAttribute('transform', xform.join(' '));
     }
   }
   setInterval(spin(flat, 5), 100);"
%%%%

This adds a top-level \markup that contains a stencil to instruct
output-svg.scm to write the specified string to the output.


-- Aaron Hill

Reply | Threaded
Open this post in threaded view
|

Re: A Javascript test code for modifying ties and slurs with mouse

Stefano Troncaro
Hi Paolo,

Since Aaron's svg-script function creates an empty \markup, you can use the properties oddFooterMarkup and evenFooterMarkup of the \paper block to have your script embedded at the end of every page. Look:

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\version "2.19.83"

svg-script = #(define-scheme-function (body) (string?)
   (markup #:stencil (ly:make-stencil (list 'embedded-svg
     (string-join (list "<script type=\"text/javascript\"><![CDATA["
       body "]]></script>") "\n")) '(0 . 0) '(0 . 0))))

script-for-every-page = \svg-script
#"var flat = document.getElementById('flat');
   flat.style.color = 'red';
   function spin(what, amount) {
     let angle = 0.0;
     return function () {
       const bbox = what.getBBox();
       const xform = ['rotate(',
         (angle = (angle + amount) % 360.0),
         bbox.x + 0.5 * bbox.width,
         bbox.y + 0.75 * bbox.height, ')'];
       what.setAttribute('transform', xform.join(' '));
     }
   }
   setInterval(spin(flat, 5), 100);"

\paper {
  oddFooterMarkup = \script-for-every-page
  evenFooterMarkup = \script-for-every-page
}

{ g'4 a' \tweak Accidental.output-attributes #'((id . "flat")) bes'2 \pageBreak
  g'4 a' \tweak Accidental.output-attributes #'((id . "flat")) bes'2 }

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

Love what your script is doing so far!

Hope that helps,
Stefano

El sáb., 14 dic. 2019 a las 18:39, Paolo Prete (<[hidden email]>) escribió:
Thanks Aaron, it did the trick.

However, how can I make it work for multiple pages output?

On Sat, Dec 14, 2019 at 4:26 AM Aaron Hill <[hidden email]> wrote:
On 2019-12-13 5:59 pm, Paolo Pr wrote:
> First of all, I need to add with Lilypond a <script>  tag to the svg
> file
> just before the ending </svg> tag  in the following way:
>
> 1)
> ....
>  <script xlink:href="lilyEasySlurs.js"></script>
> </svg>
>
> OR in the following way:
>
> 2)
> ....
> <script>
> <![CDATA[
>     ...javascript code...
> ]]>
> </script>
> </svg>

Well, one could use (abuse?) the embedded-svg stencil command:

%%%%
\version "2.19.83"

svg-script = #(define-scheme-function (body) (string?)
   (markup #:stencil (ly:make-stencil (list 'embedded-svg
     (string-join (list "<script type=\"text/javascript\"><![CDATA["
       body "]]></script>") "\n")) '(0 . 0) '(0 . 0))))

{ g'4 a' \tweak Accidental.output-attributes #'((id . "flat")) bes'2 }

\svg-script
#"var flat = document.getElementById('flat');
   flat.style.color = 'red';
   function spin(what, amount) {
     let angle = 0.0;
     return function () {
       const bbox = what.getBBox();
       const xform = ['rotate(',
         (angle = (angle + amount) % 360.0),
         bbox.x + 0.5 * bbox.width,
         bbox.y + 0.75 * bbox.height, ')'];
       what.setAttribute('transform', xform.join(' '));
     }
   }
   setInterval(spin(flat, 5), 100);"
%%%%

This adds a top-level \markup that contains a stencil to instruct
output-svg.scm to write the specified string to the output.


-- Aaron Hill

Reply | Threaded
Open this post in threaded view
|

Re: A Javascript test code for modifying ties and slurs with mouse

Flaming Hakama by Elaine
In reply to this post by Paolo Prete-3
 
From: Paolo Pr <[hidden email]>
To: Urs Liska <[hidden email]>
Cc: lilypond-user <[hidden email]>
Date: Sat, 14 Dec 2019 02:59:58 +0100
Subject: Re: A Javascript test code for modifying ties and slurs with mouse
Thanks Urs and Elaine for your appreciation.

Note that the same algo I wrote  with (relatively) short code can be applied for many other properties as well (for example: extra-offset) which are painful to control through the trial and error method...
I'll be on #irc (channel #lilypond) in the next days, so I can talk easily there with any (welcome) collaborator. My nickname is 'paolopr'. 
Before integrating the script into Frescobaldi, I would like to conclude the standalone part. 

First of all, I need to add with Lilypond a <script>  tag to the svg file just before the ending </svg> tag  in the following way:

1) 
....
 <script xlink:href="lilyEasySlurs.js"></script>
</svg> 

OR in the following way:

2)
....
<script>
<![CDATA[
    ...javascript code...
]]>
</script>
</svg>

With method 2) I have a 100% Lilypond solution, and the produced svg is ready do be used for modifying slurs, without having to integrate the script manually
I searched in the API, but could not find any function for doing that. 

To Eliane: note that you don't have to make a HTML document for that, nor to rename to ".html" the ".svg" file. Just add the <script> tag as I explained (note the xlink:href property) before the end </svg> tag., and open the file with a normal browser.
As soon as we fix points 1) and 2) I can write a how-to, which will be very short.

Best,
P

Great, I was unaware of that capability of SVGs to link to scripts.

Which means that integration is trivial.
Here is an example script to create the svg, post-process it to insert the link, then open it in a browser:

#!/usr/local/bin/bash
# Usage: buildLilyEasySlurs.sh file-base-name

FILE_BASE_NAME="lily-easy-slurs"
if [ "$1" != "" ]; then
    FILE_BASE_NAME=$1
fi

SVG="$FILE_BASE_NAME.svg"
LILYPOND="$FILE_BASE_NAME.ly"

if [ -e "$SVG" ]; then
    rm $SVG
fi

lilypond -dbackend=svg $LILYPOND

perl -p -i -e 's|</svg>||' $SVG
echo "<script xlink:href=\"lilyEasySlurs.js\"></script>" >> $SVG
echo "</svg>" >> $SVG

open -a "Google Chrome" $SVG



Of course, opening the browser from the command line syntax will vary with your OS and browser;  this above works for Chrome on mac.


Thanks, 

Elaine Alt
415 . 341 .4954                                           "Confusion is highly underrated"
[hidden email]
Producer ~ Composer ~ Instrumentalist ~ Educator
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

 
Reply | Threaded
Open this post in threaded view
|

Re: A Javascript test code for modifying ties and slurs with mouse

Flaming Hakama by Elaine
In reply to this post by Paolo Prete-3

From: Stefano Troncaro <[hidden email]>
To: Paolo Prete <[hidden email]>
Cc: Aaron Hill <[hidden email]>, lilypond-user <[hidden email]>
Date: Sat, 14 Dec 2019 19:13:43 -0300
Subject: Re: A Javascript test code for modifying ties and slurs with mouse
Hi Paolo,

Since Aaron's svg-script function creates an empty \markup, you can use the properties oddFooterMarkup and evenFooterMarkup of the \paper block to have your script embedded at the end of every page. Look:

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\version "2.19.83"

svg-script = #(define-scheme-function (body) (string?)
   (markup #:stencil (ly:make-stencil (list 'embedded-svg
     (string-join (list "<script type=\"text/javascript\"><![CDATA["
       body "]]></script>") "\n")) '(0 . 0) '(0 . 0))))

script-for-every-page = \svg-script
#"var flat = document.getElementById('flat');
   flat.style.color = 'red';
   function spin(what, amount) {
     let angle = 0.0;
     return function () {
       const bbox = what.getBBox();
       const xform = ['rotate(',
         (angle = (angle + amount) % 360.0),
         bbox.x + 0.5 * bbox.width,
         bbox.y + 0.75 * bbox.height, ')'];
       what.setAttribute('transform', xform.join(' '));
     }
   }
   setInterval(spin(flat, 5), 100);"

\paper {
  oddFooterMarkup = \script-for-every-page
  evenFooterMarkup = \script-for-every-page
}

{ g'4 a' \tweak Accidental.output-attributes #'((id . "flat")) bes'2 \pageBreak
  g'4 a' \tweak Accidental.output-attributes #'((id . "flat")) bes'2 }

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

Love what your script is doing so far!

Hope that helps,
Stefano

El sáb., 14 dic. 2019 a las 18:39, Paolo Prete (<[hidden email]>) escribió:
Thanks Aaron, it did the trick.

However, how can I make it work for multiple pages output?

Here is an approach to this issue: create an HTML document that includes each SVG.
In which case, you don't need to embed the script in the SVG, you can link it once in the HTML file:

Here is the MWE

% lily-easy-slurs.ly
\version "2.19.45"
\include "lily-easy-slurs.ily"
figure = \relative c' { g4_\( a' b2 ~ | \noBreak 2 ( e8 d ) c,4 \) | }
{ \figure \pageBreak \figure }


Here is the script to run lilypond on the MWE, then create an HTML file that includes all the SVGs, and open it:

#!/usr/local/bin/bash
# Usage: buildLilyEasySlurs.sh file-base-name

FILE_BASE_NAME="lily-easy-slurs"
if [ "$1" != "" ]; then
    FILE_BASE_NAME=$1
fi

LILYPOND="$FILE_BASE_NAME.ly"
HTML="$FILE_BASE_NAME.html"

rm "$FILE_BASE_NAME*.svg"

lilypond -dbackend=svg $LILYPOND

echo "<html>" > $HTML
echo "<head><title>Editing Lilypond curves</title>" >> $HTML
echo "</head>" >> $HTML
echo "<body>" >> $HTML

for SVG in `ls -1 $FILE_BASE_NAME-*.svg`; do    
    echo "SVG is $SVG"
    echo "" >> $HTML
    cat $SVG >> $HTML
done

echo "" >> $HTML
echo "<script src="lilyEasySlurs.js"></script>" >> $HTML
echo "</body>" >> $HTML
echo "</html>" >> $HTML
echo "" >> $HTML

open -a "Google Chrome" $HTML
 

HTH, 

Elaine Alt
415 . 341 .4954                                           "Confusion is highly underrated"
[hidden email]
Producer ~ Composer ~ Instrumentalist ~ Educator
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
Reply | Threaded
Open this post in threaded view
|

Re: A Javascript test code for modifying ties and slurs with mouse

Paolo Prete-3
In reply to this post by Stefano Troncaro
Hi Stefano,

your suggestion produces the script for every page, but it requires to manually add a property in the \paper scope. Instead, I would like to automatically set this property, and leave the user to set all the score properties (including the paper's one) without messing up the code adding pieces of the template of the script. So to obtain something like (which is much cleaner):

\include "JSSVGSlurTuner.ly"

{

     \addJSSVGSlurTuner



}



















On Sat, Dec 14, 2019 at 11:13 PM Stefano Troncaro <[hidden email]> wrote:
Hi Paolo,

Since Aaron's svg-script function creates an empty \markup, you can use the properties oddFooterMarkup and evenFooterMarkup of the \paper block to have your script embedded at the end of every page. Look:

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\version "2.19.83"

svg-script = #(define-scheme-function (body) (string?)
   (markup #:stencil (ly:make-stencil (list 'embedded-svg
     (string-join (list "<script type=\"text/javascript\"><![CDATA["
       body "]]></script>") "\n")) '(0 . 0) '(0 . 0))))

script-for-every-page = \svg-script
#"var flat = document.getElementById('flat');
   flat.style.color = 'red';
   function spin(what, amount) {
     let angle = 0.0;
     return function () {
       const bbox = what.getBBox();
       const xform = ['rotate(',
         (angle = (angle + amount) % 360.0),
         bbox.x + 0.5 * bbox.width,
         bbox.y + 0.75 * bbox.height, ')'];
       what.setAttribute('transform', xform.join(' '));
     }
   }
   setInterval(spin(flat, 5), 100);"

\paper {
  oddFooterMarkup = \script-for-every-page
  evenFooterMarkup = \script-for-every-page
}

{ g'4 a' \tweak Accidental.output-attributes #'((id . "flat")) bes'2 \pageBreak
  g'4 a' \tweak Accidental.output-attributes #'((id . "flat")) bes'2 }

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

Love what your script is doing so far!

Hope that helps,
Stefano

El sáb., 14 dic. 2019 a las 18:39, Paolo Prete (<[hidden email]>) escribió:
Thanks Aaron, it did the trick.

However, how can I make it work for multiple pages output?

On Sat, Dec 14, 2019 at 4:26 AM Aaron Hill <[hidden email]> wrote:
On 2019-12-13 5:59 pm, Paolo Pr wrote:
> First of all, I need to add with Lilypond a <script>  tag to the svg
> file
> just before the ending </svg> tag  in the following way:
>
> 1)
> ....
>  <script xlink:href="lilyEasySlurs.js"></script>
> </svg>
>
> OR in the following way:
>
> 2)
> ....
> <script>
> <![CDATA[
>     ...javascript code...
> ]]>
> </script>
> </svg>

Well, one could use (abuse?) the embedded-svg stencil command:

%%%%
\version "2.19.83"

svg-script = #(define-scheme-function (body) (string?)
   (markup #:stencil (ly:make-stencil (list 'embedded-svg
     (string-join (list "<script type=\"text/javascript\"><![CDATA["
       body "]]></script>") "\n")) '(0 . 0) '(0 . 0))))

{ g'4 a' \tweak Accidental.output-attributes #'((id . "flat")) bes'2 }

\svg-script
#"var flat = document.getElementById('flat');
   flat.style.color = 'red';
   function spin(what, amount) {
     let angle = 0.0;
     return function () {
       const bbox = what.getBBox();
       const xform = ['rotate(',
         (angle = (angle + amount) % 360.0),
         bbox.x + 0.5 * bbox.width,
         bbox.y + 0.75 * bbox.height, ')'];
       what.setAttribute('transform', xform.join(' '));
     }
   }
   setInterval(spin(flat, 5), 100);"
%%%%

This adds a top-level \markup that contains a stencil to instruct
output-svg.scm to write the specified string to the output.


-- Aaron Hill

Reply | Threaded
Open this post in threaded view
|

Re: A Javascript test code for modifying ties and slurs with mouse

Paolo Prete-3
In reply to this post by Stefano Troncaro
Hi Stefano,

your suggestion produces the script for every page, but it requires to manually add a property in the \paper scope. Instead, I would like to automatically set this property, and leave the user to set all the score properties (including the paper's one) without messing up the code adding pieces of the template of the script. So to obtain something like (which is much cleaner):

\include "JSSVGSlurTuner.ly"

{

     \addJSSVGSlurTuner

     ..... my score .....

}

Thanks for your help
P


On Sat, Dec 14, 2019 at 11:13 PM Stefano Troncaro <[hidden email]> wrote:
Hi Paolo,

Since Aaron's svg-script function creates an empty \markup, you can use the properties oddFooterMarkup and evenFooterMarkup of the \paper block to have your script embedded at the end of every page. Look:

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\version "2.19.83"

svg-script = #(define-scheme-function (body) (string?)
   (markup #:stencil (ly:make-stencil (list 'embedded-svg
     (string-join (list "<script type=\"text/javascript\"><![CDATA["
       body "]]></script>") "\n")) '(0 . 0) '(0 . 0))))

script-for-every-page = \svg-script
#"var flat = document.getElementById('flat');
   flat.style.color = 'red';
   function spin(what, amount) {
     let angle = 0.0;
     return function () {
       const bbox = what.getBBox();
       const xform = ['rotate(',
         (angle = (angle + amount) % 360.0),
         bbox.x + 0.5 * bbox.width,
         bbox.y + 0.75 * bbox.height, ')'];
       what.setAttribute('transform', xform.join(' '));
     }
   }
   setInterval(spin(flat, 5), 100);"

\paper {
  oddFooterMarkup = \script-for-every-page
  evenFooterMarkup = \script-for-every-page
}

{ g'4 a' \tweak Accidental.output-attributes #'((id . "flat")) bes'2 \pageBreak
  g'4 a' \tweak Accidental.output-attributes #'((id . "flat")) bes'2 }

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

Love what your script is doing so far!

Hope that helps,
Stefano

El sáb., 14 dic. 2019 a las 18:39, Paolo Prete (<[hidden email]>) escribió:
Thanks Aaron, it did the trick.

However, how can I make it work for multiple pages output?

On Sat, Dec 14, 2019 at 4:26 AM Aaron Hill <[hidden email]> wrote:
On 2019-12-13 5:59 pm, Paolo Pr wrote:
> First of all, I need to add with Lilypond a <script>  tag to the svg
> file
> just before the ending </svg> tag  in the following way:
>
> 1)
> ....
>  <script xlink:href="lilyEasySlurs.js"></script>
> </svg>
>
> OR in the following way:
>
> 2)
> ....
> <script>
> <![CDATA[
>     ...javascript code...
> ]]>
> </script>
> </svg>

Well, one could use (abuse?) the embedded-svg stencil command:

%%%%
\version "2.19.83"

svg-script = #(define-scheme-function (body) (string?)
   (markup #:stencil (ly:make-stencil (list 'embedded-svg
     (string-join (list "<script type=\"text/javascript\"><![CDATA["
       body "]]></script>") "\n")) '(0 . 0) '(0 . 0))))

{ g'4 a' \tweak Accidental.output-attributes #'((id . "flat")) bes'2 }

\svg-script
#"var flat = document.getElementById('flat');
   flat.style.color = 'red';
   function spin(what, amount) {
     let angle = 0.0;
     return function () {
       const bbox = what.getBBox();
       const xform = ['rotate(',
         (angle = (angle + amount) % 360.0),
         bbox.x + 0.5 * bbox.width,
         bbox.y + 0.75 * bbox.height, ')'];
       what.setAttribute('transform', xform.join(' '));
     }
   }
   setInterval(spin(flat, 5), 100);"
%%%%

This adds a top-level \markup that contains a stencil to instruct
output-svg.scm to write the specified string to the output.


-- Aaron Hill

Reply | Threaded
Open this post in threaded view
|

Re: A Javascript test code for modifying ties and slurs with mouse

Stefano Troncaro
Hi Paolo, I was also having that concern.

Elaine replied in a new thread with a solution for that, in which instead of adding the script to the svg files with lilypond you just use an external script. I haven't tested it yet but it seems to me like that'll be a cleaner approach, you just include the file with the function to show the control points and the layout definitions and that's all you need.

I guess you could make it even cleaner and have the shell script put the include statement in the .ly file.

I'd go with that solution for now. Now what I'm curious about is if there's a way to automate the process of bringing the modified shapes into the lilypond file instead of having to manually paste every one. I have no clue on how to achieve that honestly, but that'd be incredible.

HTH,
Stéfano

El sáb., 14 dic. 2019 a las 20:08, Paolo Prete (<[hidden email]>) escribió:
Hi Stefano,

your suggestion produces the script for every page, but it requires to manually add a property in the \paper scope. Instead, I would like to automatically set this property, and leave the user to set all the score properties (including the paper's one) without messing up the code adding pieces of the template of the script. So to obtain something like (which is much cleaner):

\include "JSSVGSlurTuner.ly"

{

     \addJSSVGSlurTuner

     ..... my score .....

}

Thanks for your help
P


On Sat, Dec 14, 2019 at 11:13 PM Stefano Troncaro <[hidden email]> wrote:
Hi Paolo,

Since Aaron's svg-script function creates an empty \markup, you can use the properties oddFooterMarkup and evenFooterMarkup of the \paper block to have your script embedded at the end of every page. Look:

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\version "2.19.83"

svg-script = #(define-scheme-function (body) (string?)
   (markup #:stencil (ly:make-stencil (list 'embedded-svg
     (string-join (list "<script type=\"text/javascript\"><![CDATA["
       body "]]></script>") "\n")) '(0 . 0) '(0 . 0))))

script-for-every-page = \svg-script
#"var flat = document.getElementById('flat');
   flat.style.color = 'red';
   function spin(what, amount) {
     let angle = 0.0;
     return function () {
       const bbox = what.getBBox();
       const xform = ['rotate(',
         (angle = (angle + amount) % 360.0),
         bbox.x + 0.5 * bbox.width,
         bbox.y + 0.75 * bbox.height, ')'];
       what.setAttribute('transform', xform.join(' '));
     }
   }
   setInterval(spin(flat, 5), 100);"

\paper {
  oddFooterMarkup = \script-for-every-page
  evenFooterMarkup = \script-for-every-page
}

{ g'4 a' \tweak Accidental.output-attributes #'((id . "flat")) bes'2 \pageBreak
  g'4 a' \tweak Accidental.output-attributes #'((id . "flat")) bes'2 }

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

Love what your script is doing so far!

Hope that helps,
Stefano

El sáb., 14 dic. 2019 a las 18:39, Paolo Prete (<[hidden email]>) escribió:
Thanks Aaron, it did the trick.

However, how can I make it work for multiple pages output?

On Sat, Dec 14, 2019 at 4:26 AM Aaron Hill <[hidden email]> wrote:
On 2019-12-13 5:59 pm, Paolo Pr wrote:
> First of all, I need to add with Lilypond a <script>  tag to the svg
> file
> just before the ending </svg> tag  in the following way:
>
> 1)
> ....
>  <script xlink:href="lilyEasySlurs.js"></script>
> </svg>
>
> OR in the following way:
>
> 2)
> ....
> <script>
> <![CDATA[
>     ...javascript code...
> ]]>
> </script>
> </svg>

Well, one could use (abuse?) the embedded-svg stencil command:

%%%%
\version "2.19.83"

svg-script = #(define-scheme-function (body) (string?)
   (markup #:stencil (ly:make-stencil (list 'embedded-svg
     (string-join (list "<script type=\"text/javascript\"><![CDATA["
       body "]]></script>") "\n")) '(0 . 0) '(0 . 0))))

{ g'4 a' \tweak Accidental.output-attributes #'((id . "flat")) bes'2 }

\svg-script
#"var flat = document.getElementById('flat');
   flat.style.color = 'red';
   function spin(what, amount) {
     let angle = 0.0;
     return function () {
       const bbox = what.getBBox();
       const xform = ['rotate(',
         (angle = (angle + amount) % 360.0),
         bbox.x + 0.5 * bbox.width,
         bbox.y + 0.75 * bbox.height, ')'];
       what.setAttribute('transform', xform.join(' '));
     }
   }
   setInterval(spin(flat, 5), 100);"
%%%%

This adds a top-level \markup that contains a stencil to instruct
output-svg.scm to write the specified string to the output.


-- Aaron Hill

Reply | Threaded
Open this post in threaded view
|

Re: A Javascript test code for modifying ties and slurs with mouse

Aaron Hill
In reply to this post by Paolo Prete-3
On 2019-12-14 6:16 am, Paolo Prete wrote:
> However, how can I make it work for multiple pages output?

Another approach would be to modify how LilyPond generates SVG output,
so that the script in question is inserted just before the closing
</svg> element:

%%%%
\version "2.19.83"

svg-script = #(define-void-function (body) (string?)
   (let* ((mod (resolve-module '(scm framework-svg)))
          (svg-end (module-ref mod 'svg-end #f)))
     (if (procedure? svg-end)
       (module-define! mod 'svg-end (lambda () (string-join
         (list "<script type=\"text/javascript\"><![CDATA["
               body "]]></script>" (svg-end)) "\n"))))))

\svg-script #"// TODO: Insert script here."
%%%%

This is improved in that no \markup is required.  This injection of
content happens at a point after LilyPond has processed each page of
music, so there are no unintended side-effects to the layout.

However, the above kludge modifies an undocumented, underlying
mechanism.  As such, this would be a case of "just because you can does
not necessarily mean you should".

As has been suggested, perhaps the best option would be to post-process
the SVG output from outside LilyPond.


-- Aaron Hill

Reply | Threaded
Open this post in threaded view
|

Re: A Javascript test code for modifying ties and slurs with mouse

Paolo Prete-3
Hello Aaron,

I understand that it is potentially dangerous because this is not API but we are accessing it like API. However, looking at the code, svg-end is referenced only inside its def file (framework-svg.scm), as a dummy append to the output file:


Then we can ask the maintainer of the file to add a 2-lines-of-code function for a proper override, and meanwhile use your solution without any problem/risk. What do you think?

On Sun, Dec 15, 2019 at 12:38 AM Aaron Hill <[hidden email]> wrote:
On 2019-12-14 6:16 am, Paolo Prete wrote:
> However, how can I make it work for multiple pages output?

Another approach would be to modify how LilyPond generates SVG output,
so that the script in question is inserted just before the closing
</svg> element:

%%%%
\version "2.19.83"

svg-script = #(define-void-function (body) (string?)
   (let* ((mod (resolve-module '(scm framework-svg)))
          (svg-end (module-ref mod 'svg-end #f)))
     (if (procedure? svg-end)
       (module-define! mod 'svg-end (lambda () (string-join
         (list "<script type=\"text/javascript\"><![CDATA["
               body "]]></script>" (svg-end)) "\n"))))))

\svg-script #"// TODO: Insert script here."
%%%%

This is improved in that no \markup is required.  This injection of
content happens at a point after LilyPond has processed each page of
music, so there are no unintended side-effects to the layout.

However, the above kludge modifies an undocumented, underlying
mechanism.  As such, this would be a case of "just because you can does
not necessarily mean you should".

As has been suggested, perhaps the best option would be to post-process
the SVG output from outside LilyPond.


-- Aaron Hill

Reply | Threaded
Open this post in threaded view
|

Re: A Javascript test code for modifying ties and slurs with mouse

Paolo Prete-3
In reply to this post by Stefano Troncaro
To Stefano and Elaine:

really, it's better to avoid scripting on scripting on scripting, IMHO. SVG is designed to be lovely coupled with JS, and the output file should be all-inclusive. Nor HTML is required. Only Lilypond and any SVG viewer (including browsers).  The override of internal stuff proposed by Aaron should be the solution for that, taking care to contact the maintainer of the code, meanwhile. I'm waiting for some feedback.
About the reverse process, I have some ideas, but want to meditate on them before proposing a solution. I'm not even sure that it's a good idea to automate the process...

On Sun, Dec 15, 2019 at 12:31 AM Stefano Troncaro <[hidden email]> wrote:
Hi Paolo, I was also having that concern.

Elaine replied in a new thread with a solution for that, in which instead of adding the script to the svg files with lilypond you just use an external script. I haven't tested it yet but it seems to me like that'll be a cleaner approach, you just include the file with the function to show the control points and the layout definitions and that's all you need.

I guess you could make it even cleaner and have the shell script put the include statement in the .ly file.

I'd go with that solution for now. Now what I'm curious about is if there's a way to automate the process of bringing the modified shapes into the lilypond file instead of having to manually paste every one. I have no clue on how to achieve that honestly, but that'd be incredible.

HTH,
Stéfano

El sáb., 14 dic. 2019 a las 20:08, Paolo Prete (<[hidden email]>) escribió:
Hi Stefano,

your suggestion produces the script for every page, but it requires to manually add a property in the \paper scope. Instead, I would like to automatically set this property, and leave the user to set all the score properties (including the paper's one) without messing up the code adding pieces of the template of the script. So to obtain something like (which is much cleaner):

\include "JSSVGSlurTuner.ly"

{

     \addJSSVGSlurTuner

     ..... my score .....

}

Thanks for your help
P


On Sat, Dec 14, 2019 at 11:13 PM Stefano Troncaro <[hidden email]> wrote:
Hi Paolo,

Since Aaron's svg-script function creates an empty \markup, you can use the properties oddFooterMarkup and evenFooterMarkup of the \paper block to have your script embedded at the end of every page. Look:

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\version "2.19.83"

svg-script = #(define-scheme-function (body) (string?)
   (markup #:stencil (ly:make-stencil (list 'embedded-svg
     (string-join (list "<script type=\"text/javascript\"><![CDATA["
       body "]]></script>") "\n")) '(0 . 0) '(0 . 0))))

script-for-every-page = \svg-script
#"var flat = document.getElementById('flat');
   flat.style.color = 'red';
   function spin(what, amount) {
     let angle = 0.0;
     return function () {
       const bbox = what.getBBox();
       const xform = ['rotate(',
         (angle = (angle + amount) % 360.0),
         bbox.x + 0.5 * bbox.width,
         bbox.y + 0.75 * bbox.height, ')'];
       what.setAttribute('transform', xform.join(' '));
     }
   }
   setInterval(spin(flat, 5), 100);"

\paper {
  oddFooterMarkup = \script-for-every-page
  evenFooterMarkup = \script-for-every-page
}

{ g'4 a' \tweak Accidental.output-attributes #'((id . "flat")) bes'2 \pageBreak
  g'4 a' \tweak Accidental.output-attributes #'((id . "flat")) bes'2 }

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

Love what your script is doing so far!

Hope that helps,
Stefano

El sáb., 14 dic. 2019 a las 18:39, Paolo Prete (<[hidden email]>) escribió:
Thanks Aaron, it did the trick.

However, how can I make it work for multiple pages output?

On Sat, Dec 14, 2019 at 4:26 AM Aaron Hill <[hidden email]> wrote:
On 2019-12-13 5:59 pm, Paolo Pr wrote:
> First of all, I need to add with Lilypond a <script>  tag to the svg
> file
> just before the ending </svg> tag  in the following way:
>
> 1)
> ....
>  <script xlink:href="lilyEasySlurs.js"></script>
> </svg>
>
> OR in the following way:
>
> 2)
> ....
> <script>
> <![CDATA[
>     ...javascript code...
> ]]>
> </script>
> </svg>

Well, one could use (abuse?) the embedded-svg stencil command:

%%%%
\version "2.19.83"

svg-script = #(define-scheme-function (body) (string?)
   (markup #:stencil (ly:make-stencil (list 'embedded-svg
     (string-join (list "<script type=\"text/javascript\"><![CDATA["
       body "]]></script>") "\n")) '(0 . 0) '(0 . 0))))

{ g'4 a' \tweak Accidental.output-attributes #'((id . "flat")) bes'2 }

\svg-script
#"var flat = document.getElementById('flat');
   flat.style.color = 'red';
   function spin(what, amount) {
     let angle = 0.0;
     return function () {
       const bbox = what.getBBox();
       const xform = ['rotate(',
         (angle = (angle + amount) % 360.0),
         bbox.x + 0.5 * bbox.width,
         bbox.y + 0.75 * bbox.height, ')'];
       what.setAttribute('transform', xform.join(' '));
     }
   }
   setInterval(spin(flat, 5), 100);"
%%%%

This adds a top-level \markup that contains a stencil to instruct
output-svg.scm to write the specified string to the output.


-- Aaron Hill

Reply | Threaded
Open this post in threaded view
|

Re: A Javascript test code for modifying ties and slurs with mouse

Étienne Beaulé
In reply to this post by Paolo Prete-3
I wouldn't worry so much about overriding that define, as svg-end can
only be used at that one spot or the output file would be corrupted.

A patch that included a proper override was provided 9 years but
ignored. I'll get the relevant parts of the patch up-to-date as it is
proving potential.

Thanks for your solution; I was discussing with OP on IRC the
potential ways to bodge the feature, but came up a bit short on both
your suggestions, Aaron. Also I didn't know about those undocumented
features!

Étienne

12