2024年05月05日

LilyPond いろいろ

 久しぶりに LilyPond を引っ張り出して、昔の自作曲の清書をしています。久しぶりに使うと、いろいろ問題が発生します。

1. Point and Click が効かない

 以前 Emacs で ly ファイルを編集していた時、"Point-and-Click" を実装しました。スコアの PDF に埋め込まれた textedit://... というリンクをクリックすると、対応するエディタが開く、という便利なものです。その後、mi での編集に移行しました。拙作 "LilyRunner" で、"Script to respond to click on PDF" のボックスに下のように記述します。

#!/bin/sh
# $1 = file, $2 = line, $3 = column
/usr/bin/osascript <<EOF
tell application "mi"
  open ("$1" as POSIX file)
  activate
  tell paragraph $2 of document 1 to select character $3
end tell
EOF

 これで mi で Lilypond ファイルを編集して、たいへん快適に使っていたはずなのですが、今回久しぶりに引っ張り出すと、クリックで mi を立ち上げる機能が効かない。わりと直近に編集してたはずだけど、どうやってたんだっけ? いろいろ試行錯誤して、PDF をプレビュー.app ではなくて Safari で開けばよい、ということを思い出しました。

20240505-1.jpg

2. 違うバージョンの LilyPond って共存できるんか?

 ずっと LilyPond 2.12.3 という超古いバージョンを使っていたのですが、最近のバージョンと共存できるんかな? 実は、2.12.3 は MIDI 出力の時にアーティキュレーション(スタッカートなど)をサポートしてない、という問題点があって、その時だけでも新しいバージョンを使いたいな、と思っていたのです。

 最新の 2.24 は 10.14 Mojave では動かないため、2.22 をダウンロードして、試してみました。LilyRunner で 2.22 のアプリケーションパッケージを指定すると、ちゃんと動いた! 微妙に縦方向のスペーシングが違うのがおわかりでしょうか。

20240505-2.jpg

 これで、「ガチガチに 2.12 で最適化した既存のコード」は 2.12 で、新しく書くコードは 2.22 で、と使い分けることができるようになりました。

3. Scheme コードの修正

 LilyPond 2.22 を使うと、2.12 で作成した ly ファイルは修正なしでもおおむね解釈してくれます(出力結果のレイアウトはかなり変わる)。しかし、Scheme コードでカスタマイズしていると、ちょっと厄介です。例えば、「スラーを調整する」というテクニックで、下のコードを使うのですが、これが 2.22 で動かない。

shapeSlur =
  #(define-music-function (parser location offsets) (list?)
    #{ \once \override Slur #'control-points = #(alter-curve $offsets) #})

#(define ((alter-curve offsets) grob)
   (let ((coords (ly:slur::calc-control-points grob)))
     (define (add-offsets coords offsets)
       (if (null? coords)
       '()
       (cons
     (cons (+ (caar coords) (car offsets))
           (+ (cdar coords) (cadr offsets)))
     (add-offsets (cdr coords) (cddr offsets)))))
     (add-offsets coords offsets)))

 これの修正は簡単で、$offsetoffset と書き直せばよいのですが、できれば 2.12 でも 2.22 でもコンパイルできるようにしておきたい。ちょっと試行錯誤しました。

  • LilyPond のマニュアル Usage の 2.6 に "Writing code to support multiple versions" という記述があります。ly:version? という関数を使えばよい、とあるのですが、その下に "This function has been introduced in LilyPond 2.21.80" と書いてあります。つまり、2.12 では使えない!
  • Internals Reference の 4. Scheme functions を探してみると、ly:version というのがあります。"Return the current lilypond version as a list, e.g., (1 3 127 uu1)." ということなので、これを使えばよさそう。この関数は 2.12 にもあります。
  • コンパイル中にメッセージを出して、いろいろ試してみたい。ly:message というのがあるのですが、説明が "A Scheme callable function to issue the message str. The message is formatted with format and rest." とあるだけで、なんだかよくわかりません。
  • LilyPond のアプリケーションパッケージの中を探索します。ly:message で grep したら何か手がかりが見つからんかな? いろいろ出てきました。
    $ cd /Applications/LilyPond.app/Contents/Resources/share
    $ grep ly:message `find . -name '*.scm'`
    ./lilypond/current/scm/documentation-lib.scm:  (ly:message (_ "Processing ~S...") name))
    ./lilypond/current/scm/documentation-lib.scm:  (ly:message (_ "Writing ~S...") x))
    ./lilypond/current/scm/stencil.scm:	  (ly:message "Writing ~a" outname)
    ./lilypond/current/scm/layout-page-dump.scm:    (ly:message "Writing page layout to ~a" name)
    ...
    
    試しに入力ファイルに #(ly:message "ly:version is ~a" (ly:version)) と書いてみると、LilyPond の出力に "ly:version is (2 22 2)" と表示されました。これでよさそうです。

 いろいろお試しコードを書いて試してみた結果、下のようになりました。これで、2.12 と 2.22 のどちらでも通ります。"2022" のところは、本来は文法が変更されたバージョンを特定して書くべきですが、手元には 2.12 と 2.22 しかないので、「2.22 以上」と指定しておけば事足ります。

shapeSlur =
  #(define-music-function (parser location offsets) (list?)
    (if (>= (+ (* (car (ly:version)) 1000) (cadr (ly:version))) 2022)
      #{ \once \override Slur #'control-points = #(alter-curve offsets) #}
      #{ \once \override Slur #'control-points = #(alter-curve $offsets) #}))
タグ:Mac 音楽
Posted at 2024年05月05日 21:24:48
email.png