]> git.donarmstrong.com Git - lilypond.git/commitdiff
New tablature features
authorMarc Hohl <marc@hohlart.de>
Fri, 10 Jul 2009 08:53:06 +0000 (10:53 +0200)
committerCarl Sorensen <c_sorensen@byu.edu>
Tue, 4 Aug 2009 12:47:23 +0000 (06:47 -0600)
this patch includes:
1) tablature is now "numbers only" as default
2) dead notes and palm mute is supported
3) "tied to" fret numbers become invisible
   (or parenthesized after line breaks or in a second volta)
4) the slope of glissando lines points in the right direction
5) grace notes (even parenthesized) are represented by smaller
   fret numbers.

15 files changed:
input/regression/dead-notes.ly [new file with mode: 0644]
input/regression/modern-tab-clef-scaled.ly [new file with mode: 0644]
input/regression/modern-tab-clef.ly [new file with mode: 0644]
input/regression/palm-mute.ly [new file with mode: 0644]
input/regression/tablature-full-notation.ly [new file with mode: 0644]
input/regression/tablature-glissando.ly [new file with mode: 0644]
input/regression/tablature-grace-notes.ly [new file with mode: 0644]
input/regression/tablature-tie-behaviour.ly [new file with mode: 0644]
ly/engraver-init.ly
ly/property-init.ly
scm/lily.scm
scm/music-functions.scm
scm/output-lib.scm
scm/parser-clef.scm
scm/tablature.scm [new file with mode: 0644]

diff --git a/input/regression/dead-notes.ly b/input/regression/dead-notes.ly
new file mode 100644 (file)
index 0000000..253fdd5
--- /dev/null
@@ -0,0 +1,26 @@
+\version "2.13.4"
+
+\header{ texidoc = "Muted notes (also called dead notes) are supported
+                    within normal staves and tablature."
+       }
+
+deadnotes = \relative c,, {
+   e8. \deadNotesOn e16 \deadNotesOff g4 a b |
+   e8. \deadNote e16 g4 a b |
+   e,4. \deadNote { e8 e e } e4 |
+   < e, \deadNote b' e >8 < e \deadNote b' e > < e \deadNote b' e >4 < e \deadNote b' e >4 r
+   \bar "|."
+}
+
+\context StaffGroup <<
+  \context Staff <<
+    \clef "bass_8"
+    \deadnotes
+  >>
+  \context TabStaff <<
+    \set TabStaff.stringTunings = #bass-tuning
+    \deadnotes
+  >>
+>>
+
+
diff --git a/input/regression/modern-tab-clef-scaled.ly b/input/regression/modern-tab-clef-scaled.ly
new file mode 100644 (file)
index 0000000..12caf11
--- /dev/null
@@ -0,0 +1,39 @@
+\version "2.13.4"
+
+\header{ texidoc = "The sans serif style tab clef is automatically adjusted to
+                    different string spacings."
+       }
+
+guitar = \relative c {
+  c4 d e f
+  e4 d c2
+}
+
+\score {
+  <<
+    \new Staff {
+      \clef "treble_8"
+      \guitar
+    }
+    \new TabStaff {
+      \clef "moderntab"
+      \set TabStaff.stringTunings = #guitar-tuning
+      \guitar
+    }
+  >>
+}
+
+\score {
+  <<
+    \new Staff {
+      \clef "treble_8"
+      \guitar
+    }
+    \new TabStaff {
+      \clef "moderntab"
+      \set TabStaff.stringTunings = #guitar-tuning
+      \override TabStaff.StaffSymbol #'staff-space = #1.0 % default value is 1.5
+      \guitar
+    }
+  >>
+}
\ No newline at end of file
diff --git a/input/regression/modern-tab-clef.ly b/input/regression/modern-tab-clef.ly
new file mode 100644 (file)
index 0000000..d95fb23
--- /dev/null
@@ -0,0 +1,44 @@
+\version "2.13.4"
+
+\header{ texidoc = "Sans serif style tab clefs are supported by @code{\\clef moderntab}.
+                    This alternative clef supports four- to seven-stringed instruments
+                    and is scaled automatically."
+       }
+
+bass = \relative c, {
+  c4 d e f
+  e4 d c2
+}
+
+guitar = \relative c {
+  c4 d e f
+  e4 d c2
+}
+
+\score {
+  <<
+    \new Staff {
+      \clef "bass_8"
+      \bass
+    }
+    \new TabStaff {
+      \clef "moderntab"
+      \set TabStaff.stringTunings = #bass-four-string-tuning
+      \bass
+    }
+  >>
+}
+
+\score {
+  <<
+    \new Staff {
+      \clef "treble_8"
+      \guitar
+    }
+    \new TabStaff {
+      \clef "moderntab"
+      \set TabStaff.stringTunings = #guitar-seven-string-tuning
+      \guitar
+    }
+  >>
+}
\ No newline at end of file
diff --git a/input/regression/palm-mute.ly b/input/regression/palm-mute.ly
new file mode 100644 (file)
index 0000000..33123f3
--- /dev/null
@@ -0,0 +1,27 @@
+\version "2.13.4"
+
+\header{ texidoc = "The palm mute technique for stringed instruments
+                    is supported by triangle-shaped note heads."
+       }
+
+palmmute = \relative c, {
+    \time 4/4
+    e8^\markup { \musicglyph #"noteheads.u2do"  = palm mute }
+    \palmMuteOn e e \palmMuteOff  e e  \palmMute e e e |
+    e8 \palmMute { e e e } e e e e |
+    \palmMuteOn < e b' e >8 e e e < e b' e >2 \palmMuteOff |
+    < \palmMute e b' e >8 \palmMute { e e e } < \palmMute e b' e >2
+    \bar "|."
+}
+
+\context StaffGroup <<
+  \context Staff <<
+    \clef "G_8"
+    \palmmute
+  >>
+  \context TabStaff <<
+    \palmmute
+  >>
+>>
+
+
diff --git a/input/regression/tablature-full-notation.ly b/input/regression/tablature-full-notation.ly
new file mode 100644 (file)
index 0000000..80a4868
--- /dev/null
@@ -0,0 +1,36 @@
+\version "2.13.4"
+
+\header{ texidoc = "As default, tablature staves show only the fret numbers, because
+                    in most situations, they are combined with normal staves.
+                    When used without standard notation, @code{tabFullNotation}
+                    can be used."
+       }
+
+tabstuff = {
+  \time 3/4
+  c4^"test" d( e)
+  f4\f g a^\fermata
+  c8\<\( c16 c ~ c2\!
+  c'2.\)
+  \mark \default
+  R2.
+  r4 d4 r8 e
+  \times 3/4 { b4 c \glissando d\5 \glissando c }
+  c4. d-_( e\varcoda)
+  ->f g~ a\prall g\thumb e-.
+  \bar "|."
+}
+
+\score {
+  <<
+    \new Staff { \clef "G_8" \tabstuff }
+    \new TabStaff   { \tabstuff }
+  >>
+}
+
+\score {
+  \new TabStaff {
+    \tabFullNotation
+    \tabstuff
+  }
+}
diff --git a/input/regression/tablature-glissando.ly b/input/regression/tablature-glissando.ly
new file mode 100644 (file)
index 0000000..17db67a
--- /dev/null
@@ -0,0 +1,23 @@
+\version "2.13.4"
+
+\header{ texidoc = "Glissando lines in tablature have the right slope."
+       }
+
+\paper { ragged-right = ##f } % strech the staff to make glissando lines visible
+
+glissandotest = \relative c {
+   c4\5 \glissando d\5 \glissando e\5 f\5 |
+   c4\5 \glissando d\5 \glissando c2\5 |
+   c4\5 \glissando c'\4 c\4 \glissando c,\5
+  \bar "|."
+}
+
+\context StaffGroup <<
+  \context Staff <<
+    \clef "G_8"
+    \glissandotest
+  >>
+  \context TabStaff <<
+    \glissandotest
+  >>
+>>
diff --git a/input/regression/tablature-grace-notes.ly b/input/regression/tablature-grace-notes.ly
new file mode 100644 (file)
index 0000000..5012ddd
--- /dev/null
@@ -0,0 +1,24 @@
+\version "2.13.4"
+
+\header{ texidoc = "Fret numbers belonging to grace notes are smaller."
+       }
+
+gracenotes = \relative c {
+   c4 d e f
+   \grace e8 c4 d e f
+   \grace \parenthesize e8 c4 d e f
+   \appoggiatura e8 c4 d e f
+   \acciaccatura e8 c4 d e f
+   \bar "|."
+}
+
+\context StaffGroup <<
+  \context Staff <<
+    \clef "G_8"
+    \gracenotes
+  >>
+  \context TabStaff <<
+    \gracenotes
+  >>
+>>
+
diff --git a/input/regression/tablature-tie-behaviour.ly b/input/regression/tablature-tie-behaviour.ly
new file mode 100644 (file)
index 0000000..8760c9f
--- /dev/null
@@ -0,0 +1,31 @@
+\version "2.13.4"
+
+\header{ texidoc = "In tablature, notes that are tied to are invisible
+                    except after a line break or within a second volta;
+                    here, the fret number is displayed in parentheses."
+       }
+
+tietest = \relative c {
+  \override Voice.StringNumber #'transparent = ##t % remove circled string numbers
+  \repeat volta 2 {
+    f2 ~ f4  e
+    g8 g ~ g g ~ g g~ g g ~
+    g1
+    c1 ~ \break  c2 ~ c
+    < c\3 e\2 g\1 >4 < c\3 e\2 g\1 > ~ < c\3 e\2 g\1 >\laissezVibrer r
+    c4. d8 e2 ~
+  }
+  \alternative { { e2 r } { e2\repeatTie e2^\fermata } }
+  \bar "|."
+}
+
+\context StaffGroup <<
+  \context Staff <<
+    \clef "G_8"
+    \tietest
+  >>
+  \context TabStaff <<
+    \tietest
+  >>
+>>
+
index 9d19e92cdb5922243959925b399d9c7c4f88bc8d..348d1a8c4759950e7f89eb8c8335f1d1fcd3bd9b 100644 (file)
@@ -628,6 +628,7 @@ automatically when an output definition (a @code{\score} or
     (Voice Stem direction ,UP)
     (Voice Stem font-size -3)
     (Voice NoteHead font-size -3)
+    (Voice TabNoteHead font-size -4)
     (Voice Dots font-size -3)
     (Voice Stem length-fraction 0.8)
     (Voice Stem no-stem-extend #t)
@@ -716,12 +717,39 @@ context."
 
   %% No accidental in tablature !
   \remove "Accidental_engraver"
-
-  \override Glissando #'extra-dy = #0.75
+  %% remove stems, beams, dots and rests ...
+  \override Stem #'stencil = ##f
+  \override Beam #'stencil = ##f
+  \override Dots #'stencil = ##f
+  \override Rest #'stencil = ##f
+  \override MultiMeasureRest #'stencil = ##f
+  %% ... all kinds of ties/slurs
+  \override Tie  #'stencil = ##f
+  \override RepeatTie #'stencil = ##f
+  \override LaissezVibrerTie #'stencil = ##f
+  \override Slur #'stencil = ##f
+  \override PhrasingSlur #'stencil = ##f
+  %% 'tied to' fret numbers become invisible or parenthesized, respectively)
+  \override Tie #'after-line-breaking = #tie::handle-tab-tie
+  \override RepeatTie #'after-line-breaking = #repeat-tie::parenthesize-tab-note-head
+  %% ... and all kinds of markups, spanners etc.
+  \override TupletBracket #'stencil = ##f
+  \override TupletNumber #'stencil = ##f
+  \override DynamicText #'transparent = ##t
+  \override DynamicTextSpanner #'stencil = ##f
+  \override TextSpanner #'stencil = ##f
+  \override Hairpin #'transparent = ##t
+  \override Script #'stencil = ##f
+  \override TextScript #'stencil = ##f
+  %% the direction for glissando lines will be automatically corrected
+  \override Glissando #'extra-dy = #glissando::calc-tab-extra-dy
   \override Glissando #'bound-details #'right = #`((attach-dir . ,LEFT)
                                                   (padding . 0.3))
   \override Glissando #'bound-details #'left = #`((attach-dir . ,RIGHT)
                                                   (padding . 0.3))
+  %% dead notes
+  \override TabNoteHead #'glyph-name = #tab-note-head::calc-glyph-name
+  \override TabNoteHead #'stencil = #tab-note-head::whiteout-if-style-set
 }
 
 \context {
@@ -746,6 +774,14 @@ context."
   \remove "Accidental_engraver"
   \remove "Key_engraver"
   \remove "String_number_engraver"
+  %% the clef handler
+  \override Clef #'stencil = #clef::print-modern-tab-if-set
+  %% no time signature
+  \override TimeSignature #'stencil = ##f
+  %% better parentheses in a TabStaff
+  \override ParenthesesItem #'stencils = #parentheses-item::calc-tabstaff-parenthesis-stencils
+  %% no arpeggios
+  \override Arpeggio #'stencil = ##f
   %% Special "TAB" clef
   clefGlyph = #"clefs.tab"
   clefPosition = #0
index fd5c766ef78fe816196e2c7fee3c78b6fee3c61c..f91c4b8d85dd760af497e4c99e95d66a71466b67 100644 (file)
@@ -420,3 +420,84 @@ pointAndClickOff = #(define-music-function (parser location) ()
 pointAndClickOn = #(define-music-function (parser location) ()
                       (ly:set-option 'point-and-click #t)
                       (make-music 'SequentialMusic 'void #t))
+
+palmMuteOn = {
+  \override NoteHead #'style = #'do
+}
+
+palmMuteOff = {
+  \revert NoteHead #'style
+}
+
+palmMute =
+#(define-music-function (parser location note) (ly:music?)
+  ;; are we inside a <...>?
+  (if (eq? (ly:music-property note 'name) 'NoteEvent)
+      ;; yes -> add a tweak
+      (begin (set! (ly:music-property note 'tweaks)
+                    (acons 'style 'do (ly:music-property note 'tweaks)))
+      note)
+      ;; no -> use predefined commands to switch to triangle-shaped note heads
+      #{
+        \palmMuteOn
+        $note
+        \palmMuteOff
+      #}))
+
+deadNotesOn = {
+  \override TabNoteHead #'style = #'cross
+  \override NoteHead #'style = #'cross
+}
+
+deadNotesOff = {
+  \revert TabNoteHead #'style
+  \revert NoteHead #'style
+}
+
+deadNote =
+#(define-music-function (parser location note) (ly:music?)
+  ;; are we inside a <...>?
+  (if (eq? (ly:music-property note 'name) 'NoteEvent)
+      ;; yes -> add a tweak
+      (begin (set! (ly:music-property note 'tweaks)
+                    (acons 'style 'cross (ly:music-property note 'tweaks)))
+       note)
+       ;; no -> use predefined commmands for changing
+       ;; note head and tablature fret signs
+       #{
+         \deadNotesOn
+         $note
+         \deadNotesOff
+       #}))
+
+tabFullNotation = {
+  % time signature
+  \revert TabStaff.TimeSignature #'stencil
+  % stems (the half note gets a double stem)
+  \override TabVoice.Stem #'stencil = #tabvoice::draw-double-stem-for-half-notes
+  % beams, dots
+  \revert TabVoice.Beam #'stencil
+  \revert TabVoice.Dots #'stencil
+  \revert TabVoice.Tie #'stencil
+  \revert TabVoice.Tie #'after-line-breaking
+  \revert TabVoice.RepeatTie #'stencil
+  \revert TabVoice.RepeatTie #'after-line-braking
+  \revert TabVoice.LaissezVibrerTie #'stencil
+  \revert TabVoice.Slur #'stencil
+  \revert PhrasingSlur #'stencil
+  % tuplet stuff
+  \revert TabVoice.TupletBracket #'stencil
+  \revert TabVoice.TupletNumber #'stencil
+  % dynamic signs
+  \revert DynamicText #'transparent
+  \revert DynamicTextSpanner #'stencil
+  \revert TabVoice.DynamicTextSpanner #'stencil
+  \revert TabVoice.Hairpin #'transparent
+  % rests
+  \revert TabVoice.Rest #'stencil
+  \revert TabVoice.MultiMeasureRest #'stencil
+  % markups etc.
+  \revert TabVoice.Script #'stencil
+  \revert TabVoice.TextScript #'stencil
+  \revert TabStaff.Arpeggio #'stencil
+}
index 7aa8c05c20f35563ed41b2510beda2b90867c0c4..783679ca046cef7a6bccc05014b0b5be662a9cf2 100644 (file)
@@ -397,6 +397,7 @@ LilyPond safe mode.  The syntax is the same as `define*-public'."
     "paper.scm"
     "backend-library.scm"
     "x11-color.scm"
+    "tablature.scm"
 
     ;; must be after everything has been defined
     "safe-lily.scm"))
index c5e6f2da0125fe661f03cd95d858b7de4d35b545..1372a15a526e34cb6009c190d56d69cf231692a8 100644 (file)
@@ -384,6 +384,7 @@ i.e.  this is not an override"
                        ;; TODO: take this from voicedGraceSettings or similar.
                        '((Voice Stem font-size -3)
                          (Voice NoteHead font-size -3)
+                          (Voice TabNoteHead font-size -4)
                          (Voice Dots font-size -3)
                          (Voice Stem length-fraction 0.8)
                          (Voice Stem no-stem-extend #t)
index f9b920f37d172e03b7c170a0f853505e8844bd1d..db1181f740d87e27264992185eca317470ccdd84 100644 (file)
   ))
 
 
-; default tunings for common string instruments
-(define-public guitar-tuning '(4 -1 -5 -10 -15 -20))
-(define-public guitar-open-g-tuning '(2 -1 -5 -10 -17 -22))
-(define-public bass-tuning '(-17 -22 -27 -32))
-(define-public mandolin-tuning '(16 9 2 -5))
-
-;; tunings for 5-string banjo
-(define-public banjo-open-g-tuning '(2 -1 -5 -10 7))
-(define-public banjo-c-tuning '(2 -1 -5 -12 7))
-(define-public banjo-modal-tuning '(2 0 -5 -10 7))
-(define-public banjo-open-d-tuning '(2 -3 -6 -10 9))
-(define-public banjo-open-dm-tuning '(2 -3 -6 -10 9))
-;; convert 5-string banjo tuning to 4-string by removing the 5th string
-(define-public (four-string-banjo tuning)
-  (reverse (cdr (reverse tuning))))
-
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;; note heads
 
index fff8f1b83d2ec880dba7a496e5f51775fe9a7ca7..a6d178eaeff9fbb95c07dc6108e71d062b6293aa 100644 (file)
                       (sort (map car supported-clefs) string<?)))
          (make-music 'Music)))))
 
+;; a function to add new clefs at runtime
+(define-public (add-new-clef clef-name clef-glyph clef-position octavation c0-position)
+  "Append the entries for a clef symbol to supported clefs and c0-pitch-alist"
+  (set! supported-clefs
+        (acons clef-name (list clef-glyph clef-position octavation) supported-clefs))
+  (set! c0-pitch-alist
+        (acons clef-glyph c0-position c0-pitch-alist)))
diff --git a/scm/tablature.scm b/scm/tablature.scm
new file mode 100644 (file)
index 0000000..3d92e76
--- /dev/null
@@ -0,0 +1,178 @@
+;;;; tablature.scm
+;;;;
+;;;; source file of the GNU LilyPond music typesetter
+;;;;
+;;;; (c) 2009 Marc Hohl <marc@hohlart.de>
+
+;; default tunings for common string instruments
+;; guitar tunings
+(define-public guitar-tuning '(4 -1 -5 -10 -15 -20))
+(define-public guitar-seven-string-tuning '(4 -1 -5 -10 -15 -20 -25))
+(define-public guitar-drop-d-tuning '(4 -1 -5 -10 -15 -22))
+(define-public guitar-open-g-tuning '(2 -1 -5 -10 -17 -22))
+;; bass tunings
+(define-public bass-tuning '(-17 -22 -27 -32))
+(define-public bass-four-string-tuning '(-17 -22 -27 -32))
+(define-public bass-drop-d-tuning '(-17 -22 -27 -34))
+(define-public bass-five-string-tuning '(-17 -22 -27 -32 -37))
+(define-public bass-six-string-tuning '(-12 -17 -22 -27 -32 -37))
+;; mandolin
+(define-public mandolin-tuning '(16 9 2 -5))
+;; tunings for 5-string banjo
+(define-public banjo-open-g-tuning '(2 -1 -5 -10 7))
+(define-public banjo-c-tuning '(2 -1 -5 -12 7))
+(define-public banjo-modal-tuning '(2 0 -5 -10 7))
+(define-public banjo-open-d-tuning '(2 -3 -6 -10 9))
+(define-public banjo-open-dm-tuning '(2 -3 -6 -10 9))
+;; convert 5-string banjo tuning to 4-string by removing the 5th string
+(define-public (four-string-banjo tuning)
+  (reverse (cdr (reverse tuning))))
+
+;; for more control over glyph-name calculations,
+;; we use a custom callback for tab noteheads
+;; which will ignore 'style = 'do
+(define-public (tab-note-head::calc-glyph-name grob)
+  (let ((style (ly:grob-property grob 'style)))
+   (case style
+      ((cross) "2cross"))))
+
+;; ensure we only call notehead callback when
+;; 'style = 'cross
+(define-public (tab-note-head::whiteout-if-style-set grob)
+  (let ((style (ly:grob-property grob 'style)))
+       (if (and (symbol? style)
+                (eq? style 'cross))
+           (stencil-whiteout (ly:note-head::print grob))
+           (ly:text-interface::print grob))))
+
+;; definitions for the "moderntab" clef:
+;; the "moderntab" clef will be added to the list of known clefs,
+;; so it can be used as any other clef: \clef "moderntab"
+(add-new-clef "moderntab" "markup.moderntab" 0 0 0)
+
+;; define sans serif-style tab-Clefs as a markup:
+(define-builtin-markup-command (customTabClef layout props num-strings staff-space)
+  (integer? number?)
+  music
+  ()
+  "Draw a tab clef sans-serif style."
+  (define (square x) (* x x))
+  (let* ((scale-factor (/ staff-space 1.5))
+         (font-size (- (* num-strings 1.5 scale-factor) 7))
+         (base-skip (* (square (+ (* num-strings 0.195) 0.4)) scale-factor)))
+
+        (interpret-markup layout props
+           (markup #:vcenter #:bold
+                   #:override (cons 'font-family 'sans)
+                   #:fontsize font-size
+                   #:override (cons 'baseline-skip base-skip)
+                   #:left-align #:center-column ("T" "A" "B")))))
+
+;; this function decides which clef to take
+(define-public (clef::print-modern-tab-if-set grob)
+  (let ((glyph (ly:grob-property grob 'glyph)))
+       ;; which clef is wanted?
+       (if (string=? glyph "markup.moderntab")
+           ;; if it is "moderntab", we'll draw it
+           (let* ((staff-symbol (ly:grob-object grob 'staff-symbol))
+                  (line-count   (ly:grob-property staff-symbol 'line-count))
+                  (staff-space  (ly:grob-property staff-symbol 'staff-space 1)))
+                 (grob-interpret-markup grob (make-customTabClef-markup line-count staff-space)))
+           ;; otherwise, we simply use the default printing routine
+           (ly:clef::print grob))))
+
+;; if stems are drawn, it is nice to have a double stem for
+;; (dotted) half notes to distinguish them from quarter notes:
+(define-public (tabvoice::draw-double-stem-for-half-notes grob)
+  (let ((stem (ly:stem::print grob)))
+
+       ;; is the note a (dotted) half note?
+       (if (= 1 (ly:grob-property grob 'duration-log))
+           ;; yes -> draw double stem
+           (ly:stencil-combine-at-edge stem X RIGHT stem 0.5)
+           ;; no -> draw simple stem
+           stem)))
+
+;; as default, the glissando line between fret numbers goes
+;; upwards, here we have a function to correct this behavior:
+(define-public (glissando::calc-tab-extra-dy grob)
+  (let* ((original (ly:grob-original grob))
+         (left-bound (ly:spanner-bound original LEFT))
+         (right-bound (ly:spanner-bound original RIGHT))
+         (left-pitch (ly:event-property (event-cause left-bound) 'pitch))
+         (right-pitch (ly:event-property (event-cause right-bound) 'pitch)))
+
+    (if (< (ly:pitch-semitones right-pitch) (ly:pitch-semitones left-pitch))
+        -0.75
+         0.75)))
+
+;; for ties in tablature, fret numbers that are tied to should be invisible,
+;; except for 'tied to' numbers after a line break;; these will be
+;; parenthesized (thanks to Neil for his solution):
+(define-public (parenthesize-tab-note-head grob)
+  ;; Helper function to parenthesize tab noteheads,
+  ;; since we can't use ParenthesesItem at this stage
+  ;; This is basically the same as the C++ function
+  ;; in accidental.cc, converted to Scheme
+  (let* ((font (ly:grob-default-font grob))
+         (open (stencil-whiteout
+                 (ly:font-get-glyph font "accidentals.leftparen")))
+         (close (stencil-whiteout
+                  (ly:font-get-glyph font "accidentals.rightparen")))
+         (me (ly:text-interface::print grob)))
+        (ly:stencil-combine-at-edge
+         (ly:stencil-combine-at-edge
+          me
+          X
+          LEFT
+          open)
+         X
+         RIGHT
+         close)))
+
+;; ParenthesesItem doesn't work very well for TabNoteHead, since
+;; the parentheses are too small and clash with the staff-lines
+;; Define a callback for the 'stencils property which will tweak
+;; the parentheses' appearance for TabNoteHead
+(define-public (parentheses-item::calc-tabstaff-parenthesis-stencils grob)
+   ;; the grob we want to parenthesize
+   (let ((victim (ly:grob-array-ref (ly:grob-object grob 'elements) 0)))
+     ;; check whether it's a notehead
+     (if (grob::has-interface victim 'note-head-interface)
+         (begin
+           ;; tweak appearance before retrieving
+           ;; list of stencils '(left-paren right-paren)
+           ;; get the font-size from victim (=TabNoteHead) to handle
+           ;; grace notes properly
+           (ly:grob-set-property! grob 'font-size
+                                  (ly:grob-property victim 'font-size))
+           (ly:grob-set-property! grob 'padding 0)
+           ;; apply whiteout to each element of the list
+           (map stencil-whiteout
+                (parentheses-item::calc-parenthesis-stencils grob)))
+         (parentheses-item::calc-parenthesis-stencils grob))))
+
+;; the handler for ties in tablature;; split ties yield in a parenthesized
+;; fret number, otherwise the fret number will be invisible.
+(define-public (tie::handle-tab-tie grob)
+   (let* ((original (ly:grob-original grob))
+          (tied-tab-note-head (ly:spanner-bound grob RIGHT))
+          (siblings (if (ly:grob? original)
+                        (ly:spanner-broken-into original) '())))
+
+     (if (and (>= (length siblings) 2)
+              (eq? (car (last-pair siblings)) grob))
+         ;; tie is split -> parenthesize
+         (ly:grob-set-property! tied-tab-note-head 'stencil
+                                (lambda (grob) (parenthesize-tab-note-head grob)))
+
+         ;; tie is not split -> make fret number invisible
+         (ly:grob-set-property! tied-tab-note-head 'transparent #t))))
+
+;; repeat ties occur within alternatives in a repeat construct;
+;; the correspondig fret numbers are shown in parentheses:
+(define-public (repeat-tie::parenthesize-tab-note-head grob)
+  (let ((tied-tab-note-head (ly:grob-object grob 'note-head)))
+
+        (ly:grob-set-property! tied-tab-note-head 'stencil
+                               (lambda (grob) (parenthesize-tab-note-head grob)))))
\ No newline at end of file