On 26/02/17 11:32, Thomas Morley wrote:
2017-02-26 12:12 GMT+01:00 Anthony Youngman <antli...@youngman.org.uk>:
On 26/02/17 10:52, Thomas Morley wrote:

If the chordNameFunction (ignatzek-chord-names) does not do what we
want, we should improve it, but not drop a plethora of
lily-functionality.

And yes, ignatzek-chord-names is insufficient in the sense that it's
hard up to impossible to tweak ChordName-printing sufficiently without
rewriting major parts of it.

Just to throw another big spanner into the works ...

I wrote some code which I submitted to lilypond to handle guitar capos. So,
for example, if you said something like "\capo 3", when you entered a chord
of C, it printed the chord name as "C(A)". This is *normal* practice when
printing music to accompany singers - the piano score has the guitar chords
on it.

My code didn't get into lilypond proper (I was asked to make a load of
changes, and I couldn't cope - my scheme-fu wasn't up to it), BUT. You need
to be careful that any changes you make don't break that use case - even if
I didn't get it in, I'm sure somebody else will want it in future.

Cheers,
Wol

Do we have a tracker-issue for it?

I don't know. But I'm attaching the patches. I could dig in to it, but I suspect you just want the patches date-stamped 1st August (the others are probably draft versions).

I had it working on my system, so the code does run successfully, at least with the version of lilypond that was current at the time.

Cheers,
Wol
>From a3ecdace013082f319987bd7aa98aa54d9decd0b Mon Sep 17 00:00:00 2001
From: Wol <anth...@youngman.org.uk>
Date: Wed, 20 Jul 2011 18:49:43 +0100
Subject: [PATCH 1/3] Add capo-handler function for guitar chords

---
 scm/chord-name.scm |   24 ++++++++++++++++++++++++
 1 files changed, 24 insertions(+), 0 deletions(-)

diff --git a/scm/chord-name.scm b/scm/chord-name.scm
index 79b0189..6910044 100644
--- a/scm/chord-name.scm
+++ b/scm/chord-name.scm
@@ -170,3 +170,27 @@ FOOBAR-MARKUP) if OMIT-ROOT is given and non-false.
 	 (alist (map chord-to-exception-entry elts)))
     (filter (lambda (x) (cdr x)) alist)))
 
+(define-public (capo-handler pitches bass inversion context)
+  (let (chord-function (ly:context-property context 'chordNameFunction #f))
+    (capo-pitch (ly:context-property context 'capoPitch #f))
+    (if  (not (capo-pitch))                 ;; if there's no capo pitch or no chord
+      (chord-function pitches bass inversion context)     ;; call the chordNameFunction as of old
+      (let ((new-pitches                                       ;; else transpose the pitches and do the chord twice
+            (map (lambda (p)
+              (ly:pitch-transpose p capo-pitch))
+          pitches))
+          (new-bass
+            (and (ly:pitch? bass)
+              (ly:pitch-transpose bass capo-pitch)))
+          (new-inversion
+            (and (ly:pitch? inversion)
+              (ly:pitch-transpose inversion
+          capo-pitch)))
+
+          (capo-markup (make-parenthesize-markup (chord-function new-pitches new-bass new-inversion context)))
+          (markup (chord-function pitches bass  inversion context))
+
+          (capo-vertical (ly:context-property context 'capoVertical #f))
+          (if (capo-vertical)
+            (make-column-markup (list markup capo-markup))
+            (make-line-markup (list markup (make-hspace-markup 1) capo-markup))))))))
-- 
1.7.3.4

>From 355b7eda2d9de45e355d60831bb7851731a4de36 Mon Sep 17 00:00:00 2001
From: Wol <anth...@youngman.org.uk>
Date: Sat, 30 Jul 2011 23:36:17 +0100
Subject: [PATCH 1/5] final commit I hope

---
 lily/chord-name-engraver.cc       |    4 ++--
 scm/chord-name.scm                |   28 ++++++++++++++++++++++++++++
 scm/define-context-properties.scm |    2 ++
 3 files changed, 32 insertions(+), 2 deletions(-)

diff --git a/lily/chord-name-engraver.cc b/lily/chord-name-engraver.cc
index d0ced5a..2442cdb 100644
--- a/lily/chord-name-engraver.cc
+++ b/lily/chord-name-engraver.cc
@@ -124,8 +124,8 @@ Chord_name_engraver::process_music ()
 
       pitches = scm_sort_list (pitches, Pitch::less_p_proc);
 
-      SCM name_proc = get_property ("chordNameFunction");
-      markup = scm_call_4 (name_proc, pitches, bass, inversion,
+      SCM capo_proc = ly_lily_module_constant ("capo-handler");
+      markup = scm_call_4 (capo_proc, pitches, bass, inversion,
           context ()->self_scm ());
     }
   /*
diff --git a/scm/chord-name.scm b/scm/chord-name.scm
index 79b0189..035b213 100644
--- a/scm/chord-name.scm
+++ b/scm/chord-name.scm
@@ -170,3 +170,31 @@ FOOBAR-MARKUP) if OMIT-ROOT is given and non-false.
 	 (alist (map chord-to-exception-entry elts)))
     (filter (lambda (x) (cdr x)) alist)))
 
+(define-public (capo-handler pitches bass inversion context)
+  (let ((chord-function
+          (ly:context-property context 'chordNameFunction 'jazz-chord-names))
+        (capo-pitch (ly:context-property context 'capoPitch '())))
+    (if (not capo-pitch)
+        (chord-function pitches bass inversion context)  ;; call the chordNameFunction as of old
+        (let* ((new-pitches   ;; else transpose the pitches and do the chord twice
+               (map (lambda (p)
+                       (ly:pitch-transpose p capo-pitch))
+                    pitches))
+               (new-bass
+                 (if (ly:pitch? bass)
+                     (ly:pitch-transpose bass capo-pitch)
+                     '()))
+               (new-inversion
+                 (if (ly:pitch? inversion)
+                     (ly:pitch-transpose inversion capo-pitch)
+                     '()))
+               (capo-markup
+                 (make-parenthesize-markup
+                   (chord-function new-pitches new-bass new-inversion context)))
+               (name-markup (chord-function pitches bass  inversion context))
+               (capo-vertical (ly:context-property context 'capoVertical #f)))
+          (if capo-vertical
+              (make-column-markup (list name-markup capo-markup))
+              (make-line-markup (list name-markup
+                                      (make-hspace-markup 1)
+                                      capo-markup)))))))
diff --git a/scm/define-context-properties.scm b/scm/define-context-properties.scm
index dab5211..d17f72f 100644
--- a/scm/define-context-properties.scm
+++ b/scm/define-context-properties.scm
@@ -135,6 +135,8 @@ that normally end on beats.")
      (beatStructure ,list? "List of @code{baseMoment}s that are combined
 to make beats.")
 
+     (capoPitch ,ly:pitch? "The pitch to transpose chords down by when using the capo.")
+     (capoVertical ,boolean? "Whether to display actual and transposed pitches above each other or not.")
      (chordChanges ,boolean? "Only show changes in chords scheme?")
      (chordNameExceptions ,list? "An alist of chord exceptions.
 Contains @code{(@var{chord} . @var{markup})} entries.")
-- 
1.7.3.4

>From 788e84dfcde232ff096c0502958ae2a95a78d03b Mon Sep 17 00:00:00 2001
From: Wol <anth...@youngman.org.uk>
Date: Fri, 29 Jul 2011 22:43:13 +0100
Subject: [PATCH] Modify chord handling to handle guitar capos

chord-name-engraver now calls a shim between it and the chord formatter
in order to print capo chords

chord-name-scm has had capo-handler added. If requested it prints both
the original chord, and the transposed chord.

define-context-properties adds the properties capoPitch to declare the
capo transposition, and capoVertical to make the chords print in column
rather than row form.
---
 lily/chord-name-engraver.cc       |    4 ++--
 scm/chord-name.scm                |   28 ++++++++++++++++++++++++++++
 scm/define-context-properties.scm |    2 ++
 3 files changed, 32 insertions(+), 2 deletions(-)

diff --git a/lily/chord-name-engraver.cc b/lily/chord-name-engraver.cc
index d0ced5a..2442cdb 100644
--- a/lily/chord-name-engraver.cc
+++ b/lily/chord-name-engraver.cc
@@ -124,8 +124,8 @@ Chord_name_engraver::process_music ()
 
       pitches = scm_sort_list (pitches, Pitch::less_p_proc);
 
-      SCM name_proc = get_property ("chordNameFunction");
-      markup = scm_call_4 (name_proc, pitches, bass, inversion,
+      SCM capo_proc = ly_lily_module_constant ("capo-handler");
+      markup = scm_call_4 (capo_proc, pitches, bass, inversion,
           context ()->self_scm ());
     }
   /*
diff --git a/scm/chord-name.scm b/scm/chord-name.scm
index 79b0189..98506d0 100644
--- a/scm/chord-name.scm
+++ b/scm/chord-name.scm
@@ -170,3 +170,31 @@ FOOBAR-MARKUP) if OMIT-ROOT is given and non-false.
 	 (alist (map chord-to-exception-entry elts)))
     (filter (lambda (x) (cdr x)) alist)))
 
+(define-public (capo-handler pitches bass inversion context)
+  (let ((chord-function
+          (ly:context-property context 'chordNameFunction 'jazz-chord-names))
+        (capo-pitch (ly:context-property context 'capoPitch #f)))
+    (if (not capo-pitch)
+        (chord-function pitches bass inversion context)  ;; call the chordNameFunction as of old
+        (let* ((new-pitches   ;; else transpose the pitches and do the chord twice
+               (map (lambda (p)
+                       (ly:pitch-transpose p capo-pitch))
+                    pitches))
+               (new-bass
+                 (if (ly:pitch? bass)
+                     (ly:pitch-transpose bass capo-pitch)
+                     '()))
+               (new-inversion
+                 (if (ly:pitch? inversion)
+                     (ly:pitch-transpose inversion capo-pitch)
+                     '()))
+               (capo-markup
+                 (make-parenthesize-markup
+                   (chord-function new-pitches new-bass new-inversion context)))
+               (name-markup (chord-function pitches bass  inversion context))
+               (capo-vertical (ly:context-property context 'capoVertical #f)))
+          (if capo-vertical
+              (make-column-markup (list name-markup capo-markup))
+              (make-line-markup (list name-markup
+                                      (make-hspace-markup 1)
+                                      capo-markup)))))))
diff --git a/scm/define-context-properties.scm b/scm/define-context-properties.scm
index dab5211..d17f72f 100644
--- a/scm/define-context-properties.scm
+++ b/scm/define-context-properties.scm
@@ -135,6 +135,8 @@ that normally end on beats.")
      (beatStructure ,list? "List of @code{baseMoment}s that are combined
 to make beats.")
 
+     (capoPitch ,ly:pitch? "The pitch to transpose chords down by when using the capo.")
+     (capoVertical ,boolean? "Whether to display actual and transposed pitches above each other or not.")
      (chordChanges ,boolean? "Only show changes in chords scheme?")
      (chordNameExceptions ,list? "An alist of chord exceptions.
 Contains @code{(@var{chord} . @var{markup})} entries.")
-- 
1.7.3.4

>From 1fac8b04ed35228fd043e5143199eaaef34890db Mon Sep 17 00:00:00 2001
From: Wol <anth...@youngman.org.uk>
Date: Wed, 20 Jul 2011 18:52:24 +0100
Subject: [PATCH 2/3] Add capo properties to define-context-properties

---
 scm/define-context-properties.scm |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/scm/define-context-properties.scm b/scm/define-context-properties.scm
index dab5211..d17f72f 100644
--- a/scm/define-context-properties.scm
+++ b/scm/define-context-properties.scm
@@ -135,6 +135,8 @@ that normally end on beats.")
      (beatStructure ,list? "List of @code{baseMoment}s that are combined
 to make beats.")
 
+     (capoPitch ,ly:pitch? "The pitch to transpose chords down by when using the capo.")
+     (capoVertical ,boolean? "Whether to display actual and transposed pitches above each other or not.")
      (chordChanges ,boolean? "Only show changes in chords scheme?")
      (chordNameExceptions ,list? "An alist of chord exceptions.
 Contains @code{(@var{chord} . @var{markup})} entries.")
-- 
1.7.3.4

>From fa8b9103ad01ec813807eedf9cea8fedb03d6f94 Mon Sep 17 00:00:00 2001
From: Wol <anth...@youngman.org.uk>
Date: Sun, 31 Jul 2011 17:10:13 +0100
Subject: [PATCH 2/5] Document the use of the capoPitch and capoVertical properties

---
 Documentation/notation/chords.itely |   50 +++++++++++++++++++++++++++++++++++
 1 files changed, 50 insertions(+), 0 deletions(-)

diff --git a/Documentation/notation/chords.itely b/Documentation/notation/chords.itely
index 1109075..982ed4b 100644
--- a/Documentation/notation/chords.itely
+++ b/Documentation/notation/chords.itely
@@ -506,6 +506,56 @@ Rests passed to a @code{ChordNames} context will cause the
 }
 @end lilypond
 
+@cindex Transposing guitar chords for capo
+
+If the @code{capoPitch} property is set, then the chords will additionally be printed
+transposed for a guitar with the capo set appropriately. By default the chords are 
+printed on one line, but if the @code{capoVertical} property is set, the chords will be
+printed one above the other.
+
+In make-pitch, leave the first argument at 0, the second argument is the
+interval (-2 is a third), and the third argument adjusts it up or down a
+semitone.
+
+@lilypond[verbatim,quote,ragged-right]
+<<
+  \new ChordNames \chordmode {
+    c1
+    r1
+    g1
+    c1
+    \break
+    c1
+    r1
+    g1
+    c1
+    \break
+    c1
+    r1
+    g1
+    c1
+  }
+  \chordmode {
+    c1
+    r1
+    g1
+    c1
+    \break
+    \set ChordNames.capoPitch = #(ly:make-pitch 0 -2 -1/2)
+    c1
+    r1
+    g1
+    c1
+    \break
+    \set ChordNames.capoVertical = ##t
+    c1
+    r1
+    g1
+    c1
+  }
+>>
+@end lilypond
+
 @snippets
 
 @c Keep index entries with following snippet
-- 
1.7.3.4

>From cf59539f59324583bbe595343e6ea3ca0c754791 Mon Sep 17 00:00:00 2001
From: Wol <anth...@youngman.org.uk>
Date: Sun, 31 Jul 2011 23:13:38 +0100
Subject: [PATCH 3/5] Add regression test for guitar capos

---
 input/regression/chord-capo.ly |   44 ++++++++++++++++++++++++++++++++++++++++
 1 files changed, 44 insertions(+), 0 deletions(-)
 create mode 100644 input/regression/chord-capo.ly

diff --git a/input/regression/chord-capo.ly b/input/regression/chord-capo.ly
new file mode 100644
index 0000000..aa669e2
--- /dev/null
+++ b/input/regression/chord-capo.ly
@@ -0,0 +1,44 @@
+\version "2.14.0"
+
+\header{
+  texidoc="Properties capoPitch, capoVertical: display chordnames, suitably 
+transposed for a guitar capo, either in a line or one above the other.
+"
+}
+
+<<
+  \new ChordNames \chordmode {
+    c1
+    r1
+    g1
+    c1
+    \break
+    c1
+    r1
+    g1
+    c1
+    \break
+    c1
+    r1
+    g1
+    c1
+  }
+  \chordmode {
+    c1
+    r1
+    g1
+    c1
+    \break
+    \set ChordNames.capoPitch = #(ly:make-pitch 0 -2 -1/2)
+    c1
+    r1
+    g1
+    c1
+    \break
+    \set ChordNames.capoVertical = ##t
+    c1
+    r1
+    g1
+    c1
+  }
+>>
-- 
1.7.3.4

>From 3426c1bb03d1df09f918bbaefc19d3a6c466268c Mon Sep 17 00:00:00 2001
From: Wol <anth...@youngman.org.uk>
Date: Wed, 20 Jul 2011 19:01:18 +0100
Subject: [PATCH 3/3] Modify chord-name-engraver to call capo-handler

---
 lily/chord-name-engraver.cc |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/lily/chord-name-engraver.cc b/lily/chord-name-engraver.cc
index d0ced5a..2442cdb 100644
--- a/lily/chord-name-engraver.cc
+++ b/lily/chord-name-engraver.cc
@@ -124,8 +124,8 @@ Chord_name_engraver::process_music ()
 
       pitches = scm_sort_list (pitches, Pitch::less_p_proc);
 
-      SCM name_proc = get_property ("chordNameFunction");
-      markup = scm_call_4 (name_proc, pitches, bass, inversion,
+      SCM capo_proc = ly_lily_module_constant ("capo-handler");
+      markup = scm_call_4 (capo_proc, pitches, bass, inversion,
           context ()->self_scm ());
     }
   /*
-- 
1.7.3.4

>From b255a409f0ebdbb327ec460e235fa6aee04c9f26 Mon Sep 17 00:00:00 2001
From: Wol <anth...@youngman.org.uk>
Date: Mon, 1 Aug 2011 15:18:26 +0100
Subject: [PATCH 4/5] Delete chord-capo

---
 input/regression/chord-capo.ly |   44 ----------------------------------------
 1 files changed, 0 insertions(+), 44 deletions(-)
 delete mode 100644 input/regression/chord-capo.ly

diff --git a/input/regression/chord-capo.ly b/input/regression/chord-capo.ly
deleted file mode 100644
index aa669e2..0000000
--- a/input/regression/chord-capo.ly
+++ /dev/null
@@ -1,44 +0,0 @@
-\version "2.14.0"
-
-\header{
-  texidoc="Properties capoPitch, capoVertical: display chordnames, suitably 
-transposed for a guitar capo, either in a line or one above the other.
-"
-}
-
-<<
-  \new ChordNames \chordmode {
-    c1
-    r1
-    g1
-    c1
-    \break
-    c1
-    r1
-    g1
-    c1
-    \break
-    c1
-    r1
-    g1
-    c1
-  }
-  \chordmode {
-    c1
-    r1
-    g1
-    c1
-    \break
-    \set ChordNames.capoPitch = #(ly:make-pitch 0 -2 -1/2)
-    c1
-    r1
-    g1
-    c1
-    \break
-    \set ChordNames.capoVertical = ##t
-    c1
-    r1
-    g1
-    c1
-  }
->>
-- 
1.7.3.4

>From 7259e0952b29775e4ec93014b09814c8e22bd26f Mon Sep 17 00:00:00 2001
From: Wol <anth...@youngman.org.uk>
Date: Mon, 1 Aug 2011 15:19:46 +0100
Subject: [PATCH 5/5] Add regression test for guitar capos

---
 input/regression/chord-capo.ly |   28 ++++++++++++++++++++++++++++
 1 files changed, 28 insertions(+), 0 deletions(-)
 create mode 100644 input/regression/chord-capo.ly

diff --git a/input/regression/chord-capo.ly b/input/regression/chord-capo.ly
new file mode 100644
index 0000000..789f47d
--- /dev/null
+++ b/input/regression/chord-capo.ly
@@ -0,0 +1,28 @@
+\version "2.14.0"
+
+\header{
+  texidoc="Properties capoPitch, capoVertical: display chordnames, suitably 
+transposed for a guitar capo, either in a line or one above the other.
+"
+}
+
+<<
+  \new ChordNames \chordmode {
+    c1
+    g1
+    c1
+    g1
+    c1
+    g1
+  }
+  \chordmode {
+    c1
+    g1
+    \set ChordNames.capoPitch = #(ly:make-pitch 0 -2 -1/2)
+    c1
+    g1
+    \set ChordNames.capoVertical = ##t
+    c1
+    g1
+  }
+>>
-- 
1.7.3.4

_______________________________________________
lilypond-user mailing list
lilypond-user@gnu.org
https://lists.gnu.org/mailman/listinfo/lilypond-user

Reply via email to