Autor Thema: Tagging - erweiterte Filterfunktionen, tag-Bearbeitungs-Funktionen  (Gelesen 2133 mal)

Arnold

  • Member
Tagging - erweiterte Filterfunktionen, tag-Bearbeitungs-Funktionen
« am: Montag, 26. September 2011, 11:17 »
Hallo,

da ich dazu neige, lieber zu viele als zu wenige Verschachtelungsebenen meine »Schnipsel« anzulegen (zumindest beim Bearbeiten bzw. Arrangieren, weniger beim Transponieren), und dann auch noch außer MIDI, Partitur und Einzelstimmen auch noch Ersatzstimmen erzeuge (z. Bsp. transponiert, in anderem Schlüssel, die Stichnoten mal oben mal unten, ...) fühlte ich mich mit nur zwei Tag-Filter-Funktionen schon recht eingeengt.

Nach ein bischen Arbeit habe ich nun fünf Tag-Bearbeitungsfunktionen, zwei neue Filterfunktionen für ge-Tag-te Elemente (und noch eine Variante zu einer der neuen Filterfunktionen), und dann noch eine spezielle Repeat-Unfold-Funktion mit Tag-Filterung (und auch dazu eine abgeleitete Variante) erstellt.

Erkennt jemand noch Bedarf für eine weitere wichtige Tag-Bearbeitungs- oder -Filter-Funktionalität? Vielleicht kann ich die ja auch noch programmieren.

Und viel Spaß damit, wenn ihr die beiliegenden Funktionen jetzt schon anwenden könnt.

Arnold

harm6

  • Member
Re: Tagging - erweiterte Filterfunktionen, tag-Bearbeitungs-Funktionen
« Antwort #1 am: Dienstag, 27. September 2011, 02:46 »
Hallo Arnold,

klasse Arbeit!

Kennst Du darüber hinaus eine Möglichkeit eine Art tag,label oder marker an ein grob zu binden?
Sinn der Sache wäre die markierten Objekte später auszulesen und andere Obekte anhand der Eigenschaften der markierten grobs zu platzieren.
In dem folgenden Beispiel wird eine nicht existierende Eigenschaft von grobs überschrieben und diese "Markierung" benutzt um ein markup dazwischen zu zentrieren. Das führt natürlich zu Warnmeldungen und ich kann mir nicht vorstellen, daß das in komplizierteren Situationen noch funktioniert.

\version "2.14.2"

#(define ((center-between tags extra-Y-offset) grob)
   (let* ((refp (ly:grob-system grob))
          (all-grobs (ly:grob-array->list (ly:grob-object refp 'all-elements)))
          (X-extent (lambda (q) (ly:grob-extent q refp X)))
          (targets (filter (lambda (q) (equal? (ly:grob-property q 'tags) tags)) all-grobs)))
         
     ; center between right of grob to left and left of grob to right
     (cons
       (- (- (interval-center (X-extent grob))
    (/ (+ (cdr (X-extent (car targets)))
  (car (X-extent (cadr targets))))
2)))
           extra-Y-offset)))

\relative c' {
  \once \override Staff.TimeSignature #'tags = #"hello"
  \once \override TextScript #'extra-offset = #(center-between "hello" 0)
  c^"hello"
  c c
  \override Staff.BarLine #'tags = #"hello"
  c
}

Ich weiß da im Moment leider nicht weiter.

Gruß,
  Harm

Arnold

  • Member
Re: Tagging - erweiterte Filterfunktionen, tag-Bearbeitungs-Funktionen
« Antwort #2 am: Donnerstag, 29. September 2011, 10:04 »
Hallo Harm,

auch wenn diese Antwort eigentlich einen eingen Thread wert wäre, eine »an der Oberfläche kratzende« Antwort unter diesem Betreff.

So unsicher sieht deine Funktion gar nicht aus, gegen Strukturänderungen ist man nie sicher.
Ich habe leider noch die alte 2.12.3 bei mir installiert, dort gibt's noch keine Funktion ly:grob-array->list,
und das Beispiel von List auf Array umzubauen habe ich auch gelassen.

Ich habe noch »tags« in »tigs« umbenannt, damit auf einen noch unbenutzten Symbolnamen zugegriffen wird:
Es erscheinen die Meldungen:
Warnung: Eigenschafts-Typprüfung für »tigs« (backend-type?) kann nicht gefunden werden.  vielleicht ein Tippfehler?
Warnung: Zuweisung wird trotzdem durchgeführt

Zum Test habe ich einen Patch in der Datei »define-grob-properties.scm« ausgeführt, in die Tabelle innerhalb »(define-public all-user-grob-properties« habe ich die Zeile »(tigs ,string? "Tag marker in grob for function center-between")« eingefügt.
Dann entfallen diese Warnungsmeldungen.
Benutzte ich »tags«, dann kam die Fehlermeldung, daß dieses Backend-Property bereits definiert ist.
Ich habe leider keine Funktion, um diese Typ-Prüfungs-Tabellen via »\include "xxx.ly"« zu erweitern, und in der Installation herumzuändern ist auch keine gute Lösung.

Außerdem, da \tag auch eine SCHEME-Music-Function ist (music-functions-init.ly), könnte man sich auch ein eigenes \tig definieren. Man muß wohl ein bischen aufpassen, denn hier kann man nicht davon ausgehen, daß es das Symbol 'tigs in der ly:music?-Struktur bereits gibt, also eventuell erst angelegt werden muß. Und dann müßte man zu jedem Grob seine "Ursache" suchen, um darin den Wert von 'tigs auslesen zu können.


Ich habe bei Tests für eine Griffnotenschrift das Problem gehabt, daß ich die Position des Notenkopfes relativ zum Notenhals nicht Lilypond überlassen darf sondern selbst setzen muß. Zum Überfluß ist der Zahlenwert von X-offset aber davon abhängig, ob der Notenhals nach oben oder nach unten zeigt.
So erzeugte ich eine Funktion, welche zum Notenkopf den Notenhals sucht und dessen Richtung bestimmt, und abhängig von der Richtung den einen oder anderen Wert aus dem Grob des Notenkopfes zurückgibt. Diese Funktion konnte ich mit »\override NoteHead #'X-offset = #get-predefined-x« global setzen.
Beim Tweak dieser Hilfswerte in den Notenkopf-Grob (z. Bsp. » < \tweak #'xposUP #0.0 \tweak #'xposDOWN #1.25 c'>«) kam eine ganz ähnliche Warnungsmeldung:
Warnung: cannot find property type-check for xposUP
Warnung: Zuweisung wird trotzdem durchgeführt

Diese Warnungen konnte ich dann umgehen, indem der Tweak mittels einer Scheme-Prozedur ausgeführt wurde. Damit konnte ich sogar mehrere Werte zusammen übergeben (» < \StX #0.0 #1.25 c'>«), also mehrere Attribute für das Notehead-Grob gemeinsam setzen.

Beispiel:
StX = #(define-music-function (parser location xpos-down xpos-up music) (number? number? ly:music?)
 (set! (ly:music-property music 'tweaks)
  (acons 'xposDOWN xpos-down
   (acons 'xposUP xpos-up
    (ly:music-property music 'tweaks))))
 music)


Ansonsten:
Nicht jedes Grob ist so einfach und eindeutig mit einem Attribut zu versehen wie der Notenkopf. An die Vorzeichen der Notenköpfe kommt man zum Beispiel nur indirekt - vielleicht am bequemsten mit einer before-line-breaking-Prozedur, welche Attribute vom Notenkopf auf dessen Vorzeichen überträgt.
Und um einen \prall in einen »Prall mit einem Vorzeichen darüber« zu verwandeln, dabei das Vorzeichen aber abhängig vom Pitch des zugehörigen Notenkopfes auszuwählen (damit \transpose möglich wird), hat man bei »\once \override Script #'before-line-breaking« noch das Problemchen, daß man auch andere Artikulationen (z. Bsp \upbow) auf der gleichen Note an die before-line-breaking-Prozedur angetragen bekommt.
Übrigens: vom reference-notehead (Grob) zum Pitch ging's beim \prall via »(ly:event-property (event-cause reference-notehead) 'pitch)«.

Arnold

harm6

  • Member
Re: Tagging - erweiterte Filterfunktionen, tag-Bearbeitungs-Funktionen
« Antwort #3 am: Freitag, 30. September 2011, 01:32 »
Hallo Arnold,

vielen Dank erstmal für Deine ausführliche und sehr hilfreiche Antwort!

Ich hatte noch nicht die Zeit allen Aspekten Deiner Ausführungen nachzugehen, aber ich scheine einen Weg gefunden zu haben ein neues "grob-custom-property" anzulegen, ohne in define-grob-properties.scm herumzupfuschen.

Zumindest gibt der Code keine Warnmeldung zurück und tut was er soll:

\version "2.14.2"

#(define (define-grob-custom-property symbol type? description)
  (if (not (equal? (object-property symbol 'backend-doc) #f))
      (ly:error (_ "symbol ~S redefined") symbol))

  (set-object-property! symbol 'backend-type? type?)
  (set-object-property! symbol 'backend-doc description)
  symbol)
 
#(define all-user-grob-custom-properties
  (map
   (lambda (x)
     (apply define-grob-custom-property x))

   `(
     (tigs ,string? "Tag marker in grob for function center-between")
     )))

#(define ((center-between tags extra-Y-offset) grob)
   (let* ((refp (ly:grob-system grob))
          (all-grobs (ly:grob-array->list (ly:grob-object refp 'all-elements)))
          (X-extent (lambda (q) (ly:grob-extent q refp X)))
          (targets (filter (lambda (q) (equal? (ly:grob-property q 'tigs) tags)) all-grobs)))
         
     ; center between right of grob to left and left of grob to right
     (cons
       (- (- (interval-center (X-extent grob))
    (/ (+ (cdr (X-extent (car targets)))
  (car (X-extent (cadr targets))))
2)))
           extra-Y-offset)))

\relative c' {
  \once \override Staff.TimeSignature #'tigs = #"hello"
  \once \override TextScript #'extra-offset = #(center-between "hello" 0)
  c^"hello"
  c c %\once \override NoteHead #'test = ##f
  c
  \once \override Staff.BarLine #'tigs = #"hello"
 
 
  \once \override TextScript #'extra-offset = #(center-between "bla" 0)
  \once \override NoteHead #'tigs = #"bla"
  c^"xy|yx"
  \once \override NoteHead #'tigs = #"bla"
  c
  c
  c

  \once \override Script #'extra-offset = #(center-between "blub" 0)
  \once \override Stem #'tigs = #"blub"
  c\turn
  \once \override Stem #'tigs = #"blub"
  c c
  c
}

Ein interface an das neue grob-property anzuschließen wäre der nächste Schritt. Aber in define-grob-interfaces.scm steht:

Zitat
;; The interfaces defined here generally have no code (e.g.,
;; dynamic-interface), or have callbacks defined entirely in
;; scheme.  Others interfaces are defined in lily/*.cc with the
;; ADD_INTERFACE function.

Insofern habe ich meine Zweifel, ob das gelingen kann.

Gruß und Danke,
  Harm

EDIT: Im Code stand noch \once \override NoteHead #'test = ##f aus einem früheren Versuch. Ist jetzt auskommentiert.
« Letzte Änderung: Samstag, 1. Oktober 2011, 13:10 von harm6 »