Custom note heads in LilyPond - lilypond

I am attempting to replace the default note heads with custom graphics in Lilypond. I've read the documentation under A. 10.3 Graphic which explains how to use \markup to add graphics to a score, however I'm stuck at being able to use those to replace note heads. My question is how can I replace the default note heads for custom ones?

If I understand correctly, you want to make some noteheads substituted by arbitrary graphics. Assuming you already have the graphic in EPS format as sol.eps, this code uses it to change a 'g' to a picture of a sun ('sol' is Spanish for 'sun'):
cabezaSol = {
\once \override NoteHead #'stencil = #ly:text-interface::print
\once \override NoteHead #'text =
\markup {
\general-align #Y #CENTER {
\epsfile #X #2 #"./sol.eps"
}
}
}
{ e'4 f' \cabezaSol g' }

Related

how to show symbols on top of LilyPond scores?

Santa offered a toy keyboard to my 4-year-old. He enjoys the provided scores, but I'd like to add some songs that we sing together and that are not included in the basic set. Every Key has a symbol (circle, triangle, square) and a color (blue, yellow, purple, red, orange) that is displayed on top of the music score, to help him figure out which keys to press.
I'm not a musician, but I do have a basic understanding on how to write music scores. I've never used lilypond, but I'm a developer and I know latex.
I tried searching for a way to add extra symbols, but I'm not sure this is feasible.
You can draw theses symbols by using some of the various graphics commands found on this page:
https://lilypond.org/doc/v2.24/Documentation/notation/graphic
Store these as markup macros at the top of the LilyPond file, and then call them in the score at the appropriate places.
\version "2.24.0"
blueTriangle = \markup {
\left-align
\with-color "blue"
\triangle ##t
}
orangeCircle = \markup {
\left-align
\with-color "orange"
\draw-circle #1 #0 ##t
}
purpleCircle = \markup {
\left-align
\with-color "purple"
\draw-circle #1 #0 ##t
}
greenSquare = \markup {
\left-align
\with-color "green"
\filled-box #'(0 . 2) #'(0 . 2) #0
}
\new Staff {
g4^\blueTriangle
d'^\orangeCircle
b'^\purpleCircle
f''^\greenSquare
}
This will be a bit tedious if you are placing a symbol above every note. But if you know Scheme you can probably devise a function that reads the note letters and octaves and places the correct symbol in automatically.

How to hide measure numbers in Lilypond?

In Lilypond, by default measure numbers are printed in each new line.
How to hide these numbers?
Thanks
It is actually at the end of the documentation:
\layout {
\context {
\Score
\omit BarNumber
}
}

Multiple dynamic markings under one note

I am working with Lilypond and can't figure out how to place two dynamic markings under a whole note. I want it to start piano and then become forte but I don't want to use a crescendo. I'd also rather not indicate two tied half notes. Just p then f under a whole note. This is common in older notation which I am typesetting. Thank you.
You can add one single markup that contains multiple elements to a single note:
\version "2.18.2"
{
f'1 _\markup { \dynamic { f p } }
}
There's an example in the Notation Reference, where it says: "Spacer rests are needed to engrave multiple marks on one note."
If you adapt it to your case, you might write:
\version "2.18.2"
{
R1 |
<< f'1\p { s1\f } >> |
}
However, this triggers the following warning:
warning: Two simultaneous absolute-dynamic events, junking this one
and only the first dynamic mark is printed.
So you must place the second dynamic mark on a different musical moment:
\version "2.18.2"
{
R1 |
<< f'1\p { s4. s16\f s s2 } >> |
}

Lyrics for additional verses in LilyPond?

Is there a way in LilyPond to simply list the lyrics corresponding to
additional verses after the end of the music, with one paragraph per verse?
(N.B. This exact question has been asked before, in 2001, but the first answer ("read this book") references a dead URL, while the second (use \context Lyrics) does not work for me, I get LilyPond syntax errors.)
Here's a song under which I want to write the additional verses.
\header{
title = "Hello World"
}
\score {
\relative {
\time 2/4
\clef treble
\key a \major
cis''2 | a4 fis \bar "|."
}
\addlyrics {
He -- | llo world
}
\layout { }
\midi { }
}
\version "2.18.2"
(Sorry about the syntax highlighting, <!-- language: lang-lilypond --> is not yet supported in the Google Code Prettyfier that SO uses.)
I'd like to add verses 2, 3, and 4 underneath, separated from the music, just as words.
I got an answer from Knute Snortum on the LiliyPond mailing list here
After my score block I can add a markup block like this
\markup {
\column {
\line { \null }
\line { 2. Here I go }
}
}
It turns out that this is covered in the LilyPond documentation (printing stanzas at the end) but they use the term 'stanza' and so my searching for 'verse' did not lead me there.
(It is also worth noting this discussion on meta. Posting LilyPond questions here is likely to lead to down-votes since it is not considered programming by many of the SO community. A better Stack Exchange site to post LilyPond questions to is the Music: Practice and Theory Stack Exchange, though, as I found, the LilyPond mailing list is currently the place most likely to elicit full and prompt answers.)

CSS: text-transform not working properly for Turkish characters

The implementations of the major browsers seem to have problems with text-transform: uppercase with Turkish characters. As far as I know (I'm not Turkish.) there are four different i characters: ı i I İ where the last two are the uppercase representations of the former two.
However applying text-transform:uppercase to ı i, the browsers (checked IE, Firefox, Chrome and Safari) results in I I which is not correct and may change the meaning of the words so much so that they become insults. (That's what I've been told)
As my research for solutions did not reveal any my question is: Are there workarounds for this issue? The first workaround might be to remove text-transform: uppercase entirely but that's some sort of last resort.
Funny thing, the W3C has tests for this problem on their site, but lack of further information about this issue. http://www.w3.org/International/tests/tests-html-css/tests-text-transform/generate?test=5
I appreciate any help and looking forward to your answers :-)
Here's a codepen
You can add lang attribute and set its value to tr to solve this:
<html lang="tr"> or <div lang="tr">
Here is working example.
Here's a quick and dirty workaround example - it's faster than I thought (tested in a document with 2400 tags -> no delay). But I see that js workarounds are not the very best solution
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=ISO-8859-3">
</head>
<body>
<div style="text-transform:uppercase">a b c ç d e f g ğ h ı i j k l m n o ö p r s ş t u ü v y z (source)</div> <div>A B C Ç D E F G Ğ H I İ J K L M N O Ö P R S Ş T U Ü V Y Z (should be like this)</div>
<script>
function getStyle(element, style) {
var result;
if (document.defaultView && document.defaultView.getComputedStyle) {
result = document.defaultView.getComputedStyle(element, '').getPropertyValue(style);
} else if(element.currentStyle) {
style = style.replace(/\-(\w)/g, function (strMatch, p1) {
return p1.toUpperCase();
});
result = element.currentStyle[style];
}
return result;
}
function replaceRecursive(element) {
if (element && element.style && getStyle(element, 'text-transform') == 'uppercase') {
element.innerHTML = element.innerHTML.replace(/ı/g, 'I');
element.innerHTML = element.innerHTML.replace(/i/g, 'İ'); // replaces 'i' in tags too, regular expression should be extended if necessary
}
if (!element.childNodes || element.childNodes.length == 0) return;
for (var n in element.childNodes) {
replaceRecursive(element.childNodes[n]);
}
}
window.onload = function() { // as appropriate 'ondomready'
alert('before...');
replaceRecursive(document.getElementsByTagName('body')[0]);
alert('...after');
}
</script>
</body>
</html>
Here's my enhanced version of alex's code that I am using in production:
(function($) {
function getStyle(element, style) {
var result;
if (document.defaultView && document.defaultView.getComputedStyle) {
result = document.defaultView.getComputedStyle(element, '').getPropertyValue(style);
} else if(element.currentStyle) {
style = style.replace(/\-(\w)/g, function (strMatch, p1) {
return p1.toUpperCase();
});
result = element.currentStyle[style];
}
return result;
}
function replaceRecursive(element, lang) {
if(element.lang) {
lang = element.lang; // Maintain language context
}
if (element && element.style && getStyle(element, 'text-transform') == 'uppercase') {
if (lang == 'tr' && element.value) {
element.value = element.value.replace(/ı/g, 'I');
element.value = element.value.replace(/i/g, 'İ');
}
for (var i = 0; i < element.childNodes.length; ++i) {
if (lang == 'tr' && element.childNodes[i].nodeType == Node.TEXT_NODE) {
element.childNodes[i].textContent = element.childNodes[i].textContent.replace(/ı/g, 'I');
element.childNodes[i].textContent = element.childNodes[i].textContent.replace(/i/g, 'İ');
} else {
replaceRecursive(element.childNodes[i], lang);
}
}
} else {
if (!element.childNodes || element.childNodes.length == 0) return;
for (var i = 0; i < element.childNodes.length; ++i) {
replaceRecursive(element.childNodes[i], lang);
}
}
}
$(document).ready(function(){ replaceRecursive(document.getElementsByTagName('html')[0], ''); })
})(jQuery);
Note that I am using jQuery here only for the ready() function. The jQuery compatibility wrapper is also as a convenient way to namespace the functions. Other than that, the two functions do not rely on jQuery at all, so you could pull them out.
Compared to alex's original version this one solves a couple problems:
It keeps track of the lang attribute as it recurses through, since if you have mixed Turkish and other latin content you will get improper transforms on the non-Turkish without it. Pursuant to this I pass in the base html element, not the body. You can stick lang="en" on any tag that is not Turkish to prevent improper capitalization.
It applies the transformation only to TEXT_NODES because the previous innerHTML method did not work with mixed text/element nodes such as labels with text and checkboxes inside them.
While having some notable deficiencies compared to a server side solution, it also has some major advantages, the chief of which is guaranteed coverage without the server-side having to be aware of what styles are applied to what content. If any of the content is being indexed and shown in Google summaries (for example) it is much better if it stays lowercase when served.
The next version of Firefox Nightly (which should become Firefox 14) has a fix for this problem and should handle the case without any hack (as the CSS3 specs request it).
The gory details are available in that bug : https://bugzilla.mozilla.org/show_bug.cgi?id=231162
They also fixed the problem for font-variant I think (For those not knowing what font-variant does, see https://developer.mozilla.org/en/CSS/font-variant , not yet up-to-date with the change but the doc is browser-agnostic and a wiki, so...)
The root cause of this problem must be incorrect handling of these turkish characters by unicode library used in all these browsers. So I doubt there is an front-end-side fix for that.
Someone has to report this issue to the developers of these unicode libs, and it would be fixed in few weeks/months.
If you can't rely on text-transform and browsers you will have to render your text in uppercase yourself on the server (hope you're not uppercasing the text as the user types it).
You should have a better support for internationalisation there.
This work-around requires some Javascript. If you don't want to do that, but have something server side that can preprocess the text, this idea will work there too (I think).
First, detect if you are running in Turkish. If you are, then scan whatever you are going to uppercase to see if it contains the problem characters. If they do, replace all of those characters with the uppercase version of them. Then apply the uppercase CSS. Since the problem characters are already uppercase, that should be a totally fine (ghetto) work around. For Javascript, I envision having to deal with some .innerHTML on your impacted elements.
Let me know if you need any implementation details, I have a good idea of how to do this in Javascript using Javascript string manipulation methods. This general idea should get you most of the way there (and hopefully get me a bounty!)
-Brian J. Stinar-