Score anzeigen, wenn nicht im "include"

Begonnen von Köbi, Sonntag, 23. Juli 2017, 16:21

« vorheriges - nächstes »

Köbi

Hallo zusammen

Ich bin auch wieder mal am Noten schreiben und ärgere mich über ein Detail-Problem, für das es doch eine Lösung geben müsste...

Wie zum guten Stil gehört, lege ich pro Stimme eine Datei an (VoiceA.ly und VoiceB.ly). In Main.ly führe ich sie dann zusammen, um Einzelstimmen und Partitur auszugeben.

In VoiceA/B darf ich deshalb keine Score-Umgebung haben (sonst wird die ja auch immer ausgegeben). In der Praxis  ist es bei mir so, dass, wenn ich z.B. an VoiceA.ly arbeite, ich gerne einen optischen Eindruck davon haben möchte, wie es aussieht. Dazu kann ich ein "\VoiceA" einfügen, darf aber nicht vergessen, dies wieder zu löschen/auszukommentieren, wenn ich fertig bin. Wie macht ihr das? Gibt es keine elegantere Lösung?

Eine Idee von mir ist, dass ich weiss, ob eine Datei direkt aufgerufen wurde oder als include in eine andere Datei eingebunden wurde. Gibt es dazu ein System-Funktion, die ich abfragen könnte?

Um das zu wissen, habe ich mir die folgende Konstruktion gebaut (nicht elegant, aber es funktioniert):

VoiceA.ly

\version "2.19.64"

c_VoiceA = "c_VoiceA"
#(if (not (defined? 'rName))
     (define rName c_VoiceA)
     )

VoiceA = \relative { \repeat unfold 8 { c'4 d e f } }

#(if (equal? rName c_VoiceA) (ly:parser-parse-string (ly:parser-clone) "
  \\VoiceA
"))



VoiceB.ly

\version "2.19.64"

c_VoiceB = "c_VoiceB"
#(if (not (defined? 'rName))
     (define rName c_VoiceB)
     )

VoiceB = \relative { \repeat unfold 8 { e'4 f g a } }

#(if (equal? rName c_VoiceB) (ly:parser-parse-string (ly:parser-clone) "
  \\VoiceB
"))


Main.ly

\version "2.19.54"

rName = "Main"

\include "VoiceA.ly"
\include "VoiceB.ly"

% Einzelstimmen
\book {
  \bookOutputSuffix "VoiceA"
  \VoiceA
}
\book {
  \bookOutputSuffix "VoiceB"
  \VoiceB
}

% Partitur
\book {
  \bookOutputSuffix "Partitur"
  <<
    \new Staff \VoiceA
    \new Staff \VoiceB
  >>
}



Hat jemand eine bessere Idee?

Gruss, Köbi

ingmar

#1
Hallo,


ich würde das auch ziemlich genau so machen.

Ich habe mir aber eine andere Vorgehensweise angewöhnt, die zumindest bei nicht sehr komplexen Stimmen gut funktioniert:

* Schreib die Stimme zunächst einfach als \relative { ... }
* Kompiliere und mach dein erstes Proof-Reading
* Dann erst schreib die Variablenzuordnung davor.

Ist vielleicht zu naheliegend, und wird wie gesagt nicht überall passen. Bei mir funktioniert es gut.


Gruß,
--ingmar

ingmar

Hallo köbi,

brauchst du das noch? - wenn ja, hier ein paar Überlegungen:

  • Ein includiertes Stück Code "weiß" offenbar nicht, dass es includiert wurde. Es betrachtet sich als ein Stück des Files, das es aufgerufen hat. Ein Nebeneffekt ist, dass es auch seinen originalen Namen nicht zu kennen scheint - auch nicht einmal seinen originalen Dateipfad. Zumindest hab ich nix gefunden, was nichts heißen sollte.
  • Nach deinem Code zu urteilen, willst du unten im File möglichst immer den gleichen Code stehen haben, so dass du ihn schnell einkopieren oder (in Frescobaldi) per Snippet einfliegen kannst.
  • Du scheinst immer die gleichen Namen für deine "Parts" zu verwenden. Und zwar immer genau ein Part pro File.
Die Idee, im aufrufenden File eine Variable zu definieren, ist sicher richtig. Du nutzt sie aber auch, um den Namen des Parts dort festzuhalten, den du wieder von Hand eintragen musst. Da hast du doch wieder Handarbeit! Es müsste doch reichen, nur auf Vorhandensein der variablen zu testen und den Namen der Variablen durch Probieren zu finden. Ich würde etwas so vorgehen (ich nenne die Methode "fly", das kann ich mir merken):

1. In Main.ly:
fly = ##t (oder irgendein anderer Wert)

2. In den Einzelstimmenfiles:
\include "../f.ly" (oder irgendein anderes, immergleiches File)

3. ...und im gerade aufgerufenen File f.ly:
Von A bis Z die Variablen partA bis partZ bilden und auf deren Existenz prüfen. Sobald die erste gefunden ist ( #(if (defined?) ...), diese in \score stellen und ausführen.

Vielleicht hilft die Anregung weiter.

Gruß,
--ingmar

Köbi

Hallo Ingmar

Danke für deine Ausführungen. So ganz begriffen habe ich es nicht, da müsste ich ein konkretes Beispiel haben.

Ich denke, ich bleibe meinem System, immerhin funktioniert es soweit.

Gruss
Köbi

martinusbaum

hallo,
habe das erste Beispiel noch nicht kapiert, insbesondere den Teil nach den Notennamen. Wenn ich es richtig verstanden habe, geht es darum, aus einem include-File heraus eine Notendatei zu erstellen und dazu den score-Teil aus- oder zuzuschalten. Da wäre ich um ein vollständiges Beispiel dankbar.
Darf ich um Nachhilfe bitten? Herzlichen Dank! martinusbaum

Köbi

Hallo martinusbaum

Zitat von: martinusbaum am Sonntag,  7. Januar 2018, 12:54
habe das erste Beispiel noch nicht kapiert, ...

Meinst du den ersten Beitrag, der von mir ist?

Zitat von: martinusbaum am Sonntag,  7. Januar 2018, 12:54
... insbesondere den Teil nach den Notennamen.

Meinst du das #(if (equal? rName c_Voice?

Falls bei beiden Fragen "ja", hier eine detailliertere Erklärung:

Am Anfang von VoiceA.ly (VoiceB.ly analog) steht ja folgendes:

c_VoiceA = "c_VoiceA"
#(if (not (defined? 'rName))
     (define rName c_VoiceA)
     )

Da bedeutet:
- Zuerst setze ich die Variable c_VoiceA (c steht für Constant) auf den Wert "c_VoiceA".
- Dann überprüfe ich, ob es bereits eine Variable mit dem Namen rName (r steht für Root) gibt. Wenn nicht, erstelle ich die Variable rName mit dem Wert der Variablen c_VoiceA. Die Variable hat also jetzt den Wert "c_VoiceA".
Achtung: Bitte nicht den Namen der Variable (den ich jeweils OHNE Anführungs- und Schlusszeichen geschrieben habe) mit dem Wert der Variablen (den ich jeweils MIT Anführungs- und Schlusszeichen geschrieben habe) verwechseln.


  • Wenn ich also am Noten schreiben bin und direkt in VoiceA.ly arbeite und kompiliere (in meinem Fall in Frescobaldi Strg+M drücke), dann hat die Variable rName den Wert "c_VoiceA".
  • Wenn ich in Main.ly bin und kompiliere, wird die Variable rName auf den Wert "Main" gesetzt. VoiceA.ly wird included und der Wert der Variablen nicht verändert.

Am Schluss der Datei steht folgendes:

#(if (equal? rName c_VoiceA) (ly:parser-parse-string (ly:parser-clone) "
  \\VoiceA
"))

Das bedeutet:
- Mit if (equal? rName c_VoiceA) überprüfe ich, ob der Wert der Variablen rName gleich dem Wert der Variablen c_VoiceA ist. Also, ob die beiden Variablen gleich sind.
- Falls die beiden Variablen gleich sind, wird \\VoiceA ausgeführt, ansonsten nicht.

Oder anders gesagt: Wenn ich in VoiceA.ly arbeite, werden die Noten ausgegeben, ansonsten nicht.

Zitat von: martinusbaum am Sonntag,  7. Januar 2018, 12:54
Da wäre ich um ein vollständiges Beispiel dankbar.

Das Beispiel IST vollständig.

Gruss
Köbi

martinusbaum

hallo
danke für die Erklärung!
Wenn ich die drei Dateien erstelle, die Versionsnummer ändere und dann
VoiceA unter 2.18.2 kompiliere, erhalte ich:

..../VoiceA.ly:11:2: Fehler: GUILE signalisierte einen Fehler für den hier beginnenden Ausdruck
#
(if (equal? rName c_VoiceA) (ly:parser-parse-string (ly:parser-clone) "

Wrong number of arguments to ly:parser-clone
schwerer Fehler: gescheiterte Dateien: ".../VoiceA.ly"
Wurde mit dem Return-Code 1 beendet.

Deshalb glaube ich, dass ich irgendetwas nicht verstanden habe..
Wenn ich main kompiliere, geht es....

Malte

Zitat von: martinusbaum am Sonntag,  7. Januar 2018, 19:48
Wenn ich die drei Dateien erstelle, die Versionsnummer ändere und dann
VoiceA unter 2.18.2 kompiliere, erhalte ich:
[...]
Deshalb glaube ich, dass ich irgendetwas nicht verstanden habe..
Ja, und zwar, daß Versionsnummern nicht zum Spaß dastehen und deshalb nicht einfach geändert werden können ;) Tatsächlich hat sich nämlich von 2.18 zu 2.19 einiges geändert bei Funktionen, die mit parsern zu tun haben. Wenn du die Dokumentationen der Funktion ly:parser-clone für 2.18 und 2.19 anschaust, siehst du, daß 2.18 noch ein Argument vom Typ parser-smob brauchte. Probier mal, an der Stelle einfach ,,parser" zu ergänzen. Hab den Thread nicht gelesen, deshalb weiß ich nicht, ob das allein schon ausreicht.

martinusbaum

jetzt habe ich es zwar immer noch nicht ganz durchschaut, aber die Lösung ist wie folgt:

für Version 2.18.2 muss die Zeile lauten:
[#(if (equal? rName c_VoiceA) (ly:parser-parse-string (ly:parser-clone parser) "
  \\VoiceA
"))

]

Danke, das ist eine Erleichterung! Dieser Code bekommt bei mir einen Stammplatz!

Manuela

Möglicherweise habe ich irgendwas nicht verstanden, ich kann den include-Teil leider momentan nicht testen, da nur Online-Lily zur Hand.

Hat die Definition der Variablennamen in Abhängigkeit vom Dateinamen noch irgendwo anders eine Verwendung? Wenn nicht, könnte man den Code vereinfachen zu

\version "2.19.48"

VoiceA = \relative { \repeat unfold 8 { c'4 d e f } }

#(if (not (defined? 'rName))
(ly:parser-parse-string (ly:parser-clone) "\\VoiceA" ))


Im Mainteil die Variable rname definieren.
Danke für eure Hilfe
viele Grüße
-- Manuela

Köbi

Hallo Manuela

Bei der (nur) zweistufigen Datei-Hierarchie in diesem Beispiel würde deine Variante auch gehen. In der Praxis habe ich eine mehrstufige Hierarchie (Voice/Score/Bookpart/Book). Und auf jeder Stufe möchte ich "etwas sehen", wenn ich gerade daran am Arbeiten bin. Darum habe ich bei mir in jeder Datei die Konstruktion mit dem rName.

Gruss, Köbi

Manuela

Zitat von: Köbi am Dienstag,  9. Januar 2018, 18:52
Bei der (nur) zweistufigen Datei-Hierarchie in diesem Beispiel würde deine Variante auch gehen. In der Praxis habe ich eine mehrstufige Hierarchie (Voice/Score/Bookpart/Book). Und auf jeder Stufe möchte ich "etwas sehen", wenn ich gerade daran am Arbeiten bin. Darum habe ich bei mir in jeder Datei die Konstruktion mit dem rName.

Dachte ich mir, dass es komplizierter ist.  ;)

Magst du nicht den Aufbau deiner Dateien hier im Forum beschreiben? Ich bin immer auf der Suche, wie ich meine Eingabestrukturen verbessern kann.
Danke für eure Hilfe
viele Grüße
-- Manuela

Be-3

Hallo zusammen,

gerade, wenn es aufwendiger wird, lege ich mir meist einfach eigens Test-Datei an, in der die Stimmen includiert werden und ich dann je nach Bedarf eine passende \score-Umgebung einrichte.

Gründe:

  • oft möchte ich ganze Gruppen (z. B. nur die Holzbläser) sehen
  • der \partcombine-Befehl hat ja seine Tücken und wenn ich im Gegensatz zu den Einzelstimmen in der Partitur aus Platzgründen Stimmen in einer Zeile zusammenfassen (oder auch Harfe in der Partitur einzeilig darstellen) möchte, nutze ich lieber ein spezielles Test-File statt der Stimmen-Inlcudes.
  • In Frescobaldi (das kommt ja offensichtlich im Ursprungspost zur Anwendung) läßt sich per "Lilypond->Immer dieses Dokument setzen" problemlos an der Include-Datei mit den Stimmen arbeiten, während trotzdem immer das gewählte Test-File compiliert wird.

Viele Grüße
Torsten