1 //=============================================================================
2 //  MusE Score
3 //  Linux Music Score Editor
4 //
5 //  Copyright (C) 2007 Werner Schweer and others
6 //
7 //  This program is free software; you can redistribute it and/or modify
8 //  it under the terms of the GNU General Public License version 2.
9 //
10 //  This program is distributed in the hope that it will be useful,
11 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
12 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 //  GNU General Public License for more details.
14 //
15 //  You should have received a copy of the GNU General Public License
16 //  along with this program; if not, write to the Free Software
17 //  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 //=============================================================================
19 //
20 // Lilypond export.
21 // For HISTORY, NEWS and TODOS: see end of file (Olav).
22 //
23 // Some revisions by olagunde@start.no As I have no prior knowledge of
24 // C or C++, I have to resort to techniques well known in standard
25 // Pascal as it was known in 1983, when I got my very short
26 // programming education in the "Programming for Poets" course.
27 
28 // I have written a primitive program that takes a full score output
29 // from exportly and adds separate parts to it:
30 // http://home.online.no/~olagu2/lyparts.cpp
31 // It does not work with other lilypond files.
32 
33 // Olav.
34 
35 
36 #include "libmscore/arpeggio.h"
37 #include "libmscore/articulation.h"
38 #include "libmscore/barline.h"
39 #include "libmscore/beam.h"
40 #include "libmscore/bracket.h"
41 #include "libmscore/chord.h"
42 #include "libmscore/clef.h"
43 #include "config.h"
44 #include "libmscore/dynamic.h"
45 #include "libmscore/element.h"
46 #include <fstream>
47 #include "libmscore/glissando.h"
48 #include "globals.h"
49 #include <iostream>
50 using std::cout;
51 #include "libmscore/hairpin.h"
52 #include "libmscore/harmony.h"
53 #include "libmscore/key.h"
54 #include "libmscore/keysig.h"
55 #include "libmscore/lyrics.h"
56 #include "libmscore/measure.h"
57 #include "libmscore/note.h"
58 #include "libmscore/ottava.h"
59 #include "libmscore/page.h"
60 #include "libmscore/part.h"
61 #include "libmscore/pedal.h"
62 #include "libmscore/pitchspelling.h"
63 #include "libmscore/repeat.h"
64 #include "libmscore/rest.h"
65 #include "libmscore/score.h"
66 #include "libmscore/segment.h"
67 #include "libmscore/slur.h"
68 #include "libmscore/staff.h"
69 #include <stdio.h>
70 #include <string.h>
71 #include <sstream>
72 #include "libmscore/style.h"
73 #include "libmscore/sym.h"
74 #include "libmscore/tempotext.h"
75 #include "libmscore/text.h"
76 #include "libmscore/timesig.h"
77 #include "libmscore/tremolo.h"
78 #include "libmscore/tuplet.h"
79 #include "libmscore/volta.h"
80 #include "libmscore/marker.h"
81 #include "libmscore/jump.h"
82 #include "musescore.h"
83 
84 namespace Ms {
85 
86 static  const int MAX_SLURS = 8;
87 static  const int BRACKSTAVES=64;
88 static  const int MAXPARTGROUPS = 8;
89 static const int VERSES = 8;
90 
91 //---------------------------------------------------------
92 //   ExportLy
93 //---------------------------------------------------------
94 
95 class ExportLy {
96   Score* score;
97   QFile f;
98   QTextStream os;
99   int level;        // indent level
100   int curTicks;
101   MScore::Direction stemDirection;
102   int indx;
103   bool partial; //length of pickupbar
104 
105   int  timedenom, z1, z2, z3, z4; //timesignatures
106   int barlen, wholemeasurerest;
107   QString wholemeasuretext;
108   bool pickup;
109   bool rehearsalnumbers;
110   bool donefirst; //to prevent doing things in first ordinary bar which are already done in pickupbar
111   bool graceswitch, gracebeam;
112   int gracecount;
113   int prevpitch, staffpitch, chordpitch;
114   int measurenumber, lastind, taktnr, staffInd;
115   bool repeatactive;
116   bool firstalt,secondalt;
117   enum voltatype {startending, endending, startrepeat, endrepeat, bothrepeat, doublebar, brokenbar, endbar, none};
118   struct  voltareg { voltatype voltart; int barno; };
119   struct voltareg  voltarray[255];
120   int tupletcount;
121   bool pianostaff;
122   bool slur;
123   const Slur* slurre[MAX_SLURS];
124   bool started[MAX_SLURS];
125   int phraseslur;
126   int slurstack;
127   int findSlur(const Slur* s) const;
128   const char *relativ, *staffrelativ;
129   bool voiceActive[VOICES];
130   int prevElTick;
131   bool ottvaswitch, jumpswitch;
132   char privateRehearsalMark;
133 
134   struct lybrackets
135   {
136     bool piano;
137     bool bracestart,brakstart, braceend, brakend;
138     int braceno, brakno;
139   };
140 
141   struct lybrackets lybracks[BRACKSTAVES];
142   void bracktest();
143 
144   struct staffnameinfo
145   {
146     QString voicename[VOICES];
147     QString  staffid, partname, partshort;
148     bool simultaneousvoices;
149     int numberofvoices;
150   };
151 
152   struct staffnameinfo staffname[32];
153 
154   QString cleannote, prevnote;
155 
156   struct InstructionAnchor
157 // Even if it is exactly the same thing as "direction" of music-xml,
158 // the word "instruction" is used in this file, so as not to cause
159 // confusion with "direction" of the exportxml-file.
160   {
161     Element* instruct;  // the element containing the instruction
162     Element* anchor;    // the element it is attached to
163     bool     start;     // whether it is attached to start or end
164     int      tick;      // the timestamp
165   };
166 
167   int nextAnchor;
168   struct InstructionAnchor anker;
169   struct InstructionAnchor anchors[1024];
170 
171   struct glisstablelem
172   {
173     Chord* chord;
174     int tick;
175     QString glisstext;
176     int type;
177   };
178   int glisscount;
179   struct glisstablelem glisstable[99];
180 
181   QString voicebuffer;
182   QTextStream out;
183   QString scorebuffer;
184   QTextStream scorout;
185   //  int numberofverses;
186 
187   bool nochord;
188   int chordcount;
189   void chordName(struct InstructionAnchor chordanchor);
190 
191   struct chordData
192   {
193     QString chrName;
194     QString extName;
195     int alt;
196     QString bsnName;
197     int bsnAlt;
198     int ticklen;
199     int tickpos;
200   };
201 
202   struct chordData thisHarmony;
203   struct chordData prevHarmony;
204   void resetChordData(struct chordData&);
205   QString chord2Name(int ch);
206 
207   struct chordPost //element of a list to store hamonies.
208   {
209     struct chordData cd;
210     struct chordPost * next;
211     struct chordPost * prev;
212   };
213   struct chordPost cp;
214   struct chordPost * chordHead;
215   struct chordPost * chordThis;
216 
217 
218   // one lyricsRecord for each staff. Each record have room for VERSES
219   // no. of verses.
220   struct lyricsData
221   {
222     QString verselyrics[VERSES];
223     QString voicename[VERSES];
224     QString staffname;
225     int tick[VERSES];
226     int segmentnumber[VERSES];
227   };
228 
229   struct lyricsRecord
230   {
231     int numberofverses;
232     struct lyricsData lyrdat;
233     struct lyricsRecord * next;
234     struct lyricsRecord *prev;
235   };
236 
237   //  struct lyricsRecord * lyrrec;
238   struct lyricsRecord * thisLyrics;
239   struct lyricsRecord * headOfLyrics;
240   struct lyricsRecord * tailOfLyrics;
241 
242 
243   void storeChord(struct InstructionAnchor chAnk);
244   void chordInsertList(chordPost *);
245   void printChordList();
246   void cleanupChordList();
247   void writeFingering (int&, QString fingering[5]);
248   void findLyrics();
249   void newLyricsRecord();
250   void cleanupLyrics();
251   void writeLyrics();
252   void connectLyricsToStaff();
253   void findGraceNotes(Note*,bool&, int);
254   void setOctave(int&, int&, int (&foo)[12]);
255   bool arpeggioTest(Chord* chord);
256   bool glissandotest(Chord*);
257   bool findNoteSymbol(Note*, QString &);
258   void buildGlissandoList(int strack, int etrack);
259   void writeStringInstruction(int &, QString stringarr[10]);
260   void findFingerAndStringno(Note* note, int&, int&, QString (&finger)[5], QString (&strng)[10]);
261   struct jumpOrMarkerLM
262   {
263     Marker* marker;
264     int measurenum;
265     bool start;
266   };
267 
268   int lastJumpOrMarker;
269   struct jumpOrMarkerLM  jumpOrMarkerList[100];
270 
271   void writeLilyHeader();
272   void writeLilyMacros();
273   void writePageFormat();
274   void writeScoreTitles();
275   void initJumpOrMarkerLMs();
276   void resetJumpOrMarkerLM(struct jumpOrMarkerLM &mlm);
277   void removeJumpOrMarkerLM(int);
278   void preserveJumpOrMarker(Element *, int, bool);
279   void printJumpOrMarker(int mnum, bool start);
280 
281   void anchortest();
282   void voltatest();
283   void jumptest();
284   void storeAnchor(struct InstructionAnchor);
285   void initAnchors();
286   void removeAnchor(int);
287   void resetAnchor(struct InstructionAnchor &ank);
288   bool findMatchInMeasure(int, Staff*, Measure*, int, int, bool);
289   bool findMatchInPart(int, Staff*, Score*, int, int, bool);
290 
291   void jumpAtMeasureStop(Measure*);
292   void findMarkerAtMeasureStart(Measure*);
293   void writeMeasuRestNum();
294   void writeTremolo(Chord *);
295 
296   void writeSymbol(QString);
297   void tempoText(TempoText *);
298   void words(Text *);
299   void hairpin(Hairpin* hp, int tick);
300   void ottava(Ottava* ot, int tick);
301   void pedal(Pedal* pd, int tick);
302   void dynamic(Dynamic*, int);
303   void textLine(Element*, int, bool);
304   void findTextProperties(Text* , QString&, int &);
305   bool textspannerdown;
306   // to avoid writing barlinecheck in the middle of a textspanner.
307   bool textspanswitch;
308   //from exportxml's class directionhandler:
309   void buildInstructionListPart(int strack, int etrack);
310   void buildInstructionList(Measure* m, int strack, int etrack);
311   void handleElement(Element* el);
312   void handlePreInstruction(Element * el);
313   void instructionJump(Jump*);
314   void instructionMarker(Marker*);
315   QString primitiveJump(Jump* );
316   QString primitiveMarker(Marker*);
317   int checkJumpOrMarker(int, bool, Element*&);
318   void writeCombinedMarker(int, Element* );
319   QString flatInInstrName(QString);
320 
321   void indent(); //buffer-string
322   void indentF(); //file
323   int getLen(int ticks, int* dots);
324   void writeLen(int);
325   void writeChordLen(int ticks);
326   QString tpc2name(int tpc);
327   QString tpc2purename(int tpc);
328 
329   void writeScore();
330   void stemDir(Chord *);
331   void writeVoiceMeasure(MeasureBase*, Staff*, int, int);
332   void writeKeySig(int);
333   void writeTimeSig(TimeSig*);
334   void writeClef(int);
335   void writeChord(Chord*, bool);
336   void writeRest(int, int);
337   void findVolta();
338   void findStartRepNoBarline(int &i, Measure*);
339   void writeBarline(Measure *);
340   int  voltaCheckBar(Measure *, int);
341   void writeVolta(int, int);
342   void findTuplets(ChordRest*);
343   void writeArticulation(ChordRest*);
344   void writeScoreBlock();
345   void checkSlur(Chord*, bool);
346   void doSlurStart(Chord*, bool);
347   void doSlurStop(Chord*);
348   void initBrackets();
349   void brackRegister(int, int, int, bool, bool);
350   void findBrackets();
351 
352 public:
ExportLy(Score * s)353   ExportLy(Score* s)
354   {
355     score  = s;
356     level  = 0;
357     curTicks = MScore::division;
358     slur   = false;
359     stemDirection = MScore::AUTO;
360   }
361   bool write(const QString& name);
362 };
363 
364 
365 //---------------------------------------------------------
366 // abs num value
367 //---------------------------------------------------------
numval(int num)368 int numval(int num)
369 {  if (num <0) return -num;
370   return num;
371 }
372 
373 
374 //---------------------------------------------------------
375 // initBrackets -- init array of brackets and braces info
376 //---------------------------------------------------------
377 
initBrackets()378 void ExportLy::initBrackets()
379 {
380   for (int i = 0; i < BRACKSTAVES; ++i)     //init bracket-array
381     {
382       lybracks[i].piano=false;
383       lybracks[i].bracestart=false;
384       lybracks[i].brakstart=false;
385       lybracks[i].braceend=false;
386       lybracks[i].brakend=false;
387       lybracks[i].braceno=0;
388       lybracks[i].brakno=0;
389     }
390 }
391 
392 
393 
394 //----------------------------------------------------------------
395 //   brackRegister register where partGroup Start, and whether brace,
396 //   bracket or pianostaff.
397 //----------------------------------------------------------------
398 
brackRegister(int brnumber,int bratype,int staffnr,bool start,bool end)399 void ExportLy::brackRegister(int brnumber, int bratype, int staffnr, bool start, bool end)
400 
401 {
402   QString br = "";
403   switch(bratype)
404     {
405     case BRACKET_NORMAL:
406       if (start) lybracks[staffnr].brakstart=true;
407       if (end) lybracks[staffnr].brakend=true;
408       lybracks[staffnr].brakno=brnumber;
409       break;
410     case BRACKET_BRACE:
411       if (start) lybracks[staffnr].bracestart=true;
412       if (end) lybracks[staffnr].braceend=true;
413       lybracks[staffnr].braceno=brnumber;
414       break;
415     case -1: //piano-staff: lilypond makes rigid distance between
416 	     //staffs to allow cross-staff beaming.
417       lybracks[staffnr].piano=true;
418       if (start) lybracks[staffnr].bracestart=true;
419       if (end) lybracks[staffnr].braceend=true;
420       lybracks[staffnr].braceno=brnumber;
421       break;
422     default:
423       qDebug("bracket subtype %d not understood\n", bratype);
424     }
425 }
426 
427 
428 //-------------------------------------------------------------
429 // findBrackets
430 // run thru parts and staffs to find start and end of braces and brackets
431 //---------------------------------------------------------------
432 
findBrackets()433 void ExportLy::findBrackets()
434 {
435   initBrackets();
436   char groupnumber;
437   groupnumber=1;
438   const QList<Part*>& il = score->parts();  //list of parts
439 
440   for (int partnumber = 0; partnumber < il.size(); ++partnumber)  //run thru list of parts
441     {
442       Part* part = il.at(partnumber);
443       if (part->nstaves() == 2) pianostaff=true;
444       for (int stavno = 0; stavno < part->nstaves(); stavno++) //run thru list of staves in part.
445 	{
446 	  if (pianostaff)
447 	    {
448 	      if (stavno==0)
449 		{
450 		  brackRegister(groupnumber, -1, partnumber+stavno, true, false);
451 		}
452 	      if (stavno==1)
453 		{
454 		  brackRegister(groupnumber, -1, partnumber+stavno, false, true);
455 		  pianostaff=false;
456 		}
457 	    }
458 	  else //not pianostaff
459 	    {
460 	      Staff* st = part->staff(stavno);
461 	      if (st)
462 		{
463 		  for (int braclev= 0; braclev < st->bracketLevels(); braclev++) //run thru bracketlevels of staff
464 		    {
465 		      if (st->bracket(braclev) != NO_BRACKET) //if bracket
466 			{
467 			  groupnumber++;
468 			  if (groupnumber < MAXPARTGROUPS)
469 			    { //brackRegister(bracketnumber, brackettype, staffnr, start, end)
470 			      brackRegister(groupnumber, st->bracket(braclev), partnumber, true, false);
471 			      brackRegister(groupnumber,st->bracket(braclev), partnumber-1+st->bracketSpan(braclev), false, true);
472 			    }
473 			}//end of if bracket
474 		    }//end of bracket-levels of staff
475 		}//end if staff
476 	    } // end of else:not pianostaff
477 	}//end of stafflist
478     }//end of parts-list
479 }//end of findBrackets;
480 
481 
482 
bracktest()483 void ExportLy::bracktest()
484       {
485       for (int i = 0; i < 10; i++) {
486             qDebug("stavnr: %d braceno: %d brackno %d\n", i, lybracks[i].braceno, lybracks[i].brakno);
487             }
488       }
489 
490 
491 //-------------------------------------------------------
492 // instructionJump
493 //--------------------------------------------------------
494 
instructionJump(Jump * jp)495 void ExportLy::instructionJump(Jump* jp)
496 {
497   JumpType jtp = jp->jumpType();
498   QString words = "\n    \\once\\override Score.RehearsalMark #'self-alignment-X = #RIGHT \n      ";
499 
500   if (jtp == JumpType::DC)
501     words += "\\mark \"Da capo\" ";
502   else if (jtp == JumpType::DC_AL_FINE)
503     words += "\\DCalfine ";
504   else if (jtp == JumpType::DC_AL_CODA)
505     words += "\\DCalcoda";
506   else if (jtp == JumpType::DS_AL_CODA)
507     words += "\\DSalcoda";
508   else if (jtp == JumpType::DS_AL_FINE)
509     words += "\\DSalfine";
510   else if (jtp == JumpType::DS)
511     words += "\\mark \\markup{Dal segno \\raise #2 \\halign#-1 \\musicglyph #\"scripts.segno\"}";
512   else
513     qDebug("jump type=%d not implemented\n", jtp);
514   out <<  words << " ";
515 }
516 
517 
518 
519 //---------------------------------------------------------
520 //   instructionMarker -- write marker
521 //---------------------------------------------------------
522 
instructionMarker(Marker * m)523 void ExportLy::instructionMarker(Marker* m)
524 {
525   MarkerType mtp = m->markerType();
526   QString words = "";
527   if (mtp == MarkerType::CODA)
528       words = "\\theCoda ";
529   else if (mtp == MarkerType::CODETTA)
530      	words = "\\codetta";
531   else if (mtp == MarkerType::SEGNO)
532       words = "\\thesegno";
533   else if (mtp == MarkerType::FINE)
534 	words = "\\fine";
535   else if (mtp == MarkerType::TOCODA)
536 	words = "\\gotocoda ";
537   else if (mtp == MarkerType::VARCODA)
538 	words = "\\varcodasign ";
539   else if (mtp == MarkerType::USER)
540 	qDebug("unknown user marker\n");
541   else
542     qDebug("marker type=%d not implemented\n", mtp);
543 
544   out <<  words << " ";
545 
546 }
547 
548 
549 
550 //---------------------------------------------------------------------
551 // primitiveJump -- write jumpsign without macros: to be combined with
552 // rehearsalmark
553 //---------------------------------------------------------------------
554 
primitiveJump(Jump * jp)555 QString ExportLy::primitiveJump(Jump* jp)
556 {
557   JumpType jtp = jp->jumpType();
558   QString words = "";
559 
560   cout << "primitivejump\n";
561 
562   if (jtp == JumpType::DC)
563      	words = "Da capo";
564   else if (jtp == JumpType::DC_AL_FINE)
565       words = "D.C. al fine";
566   else if (jtp == JumpType::DC_AL_CODA)
567 	words = "D.C. al coda";
568   else if (jtp == JumpType::DS_AL_CODA)
569 	words = "D.S. al coda";
570   else if (jtp == JumpType::DS_AL_FINE)
571 	words = "D.S. al fine";
572   else if (jtp == JumpType::DS)
573       words = "Dal segnoX \\musicglyph #\"scripts.segno\"";
574   else
575     qDebug("jump type=%d not implemented\n", jtp);
576   return  words;
577 }
578 
579 //------------------------------------------------------------------
580 //   primitiveMarker -- write marker without macros: to be combined
581 //   with rehearsalmark.
582 //------------------------------------------------------------------
583 
primitiveMarker(Marker * m)584 QString ExportLy::primitiveMarker(Marker* m)
585 {
586   MarkerType mtp = m->markerType();
587   QString words = "";
588   if (mtp == MarkerType::CODA) //the coda
589     //    words = "\\line{\\halign #-0.75\\noBreak \\codaspace \\resumeStaff \\showClefKey \musicglyph #\"scripts.coda\" \\musicglyph #\"scripts.coda\"}";
590     words = "\\line{\\halign #-0.75 \\musicglyph #\"scripts.coda\" \\musicglyph #\"scripts.coda\"}";
591   else if (mtp == MarkerType::CODETTA)
592      	words = "\\line {\\musicglyph #\"scripts.coda\" \\hspace #-1.3 \\musicglyph #\"scripts.coda\"} } \n";
593   else if (mtp == MarkerType::SEGNO)
594       words = "\\musicglyph #\"scripts.segno\"";
595   else if (mtp == MarkerType::FINE)
596 	words =  "{\"Fine\"} \\mark \\markup {\\musicglyph #\"scripts.ufermata\" } \\bar \"\bar \"||\" } \n";
597   else if (mtp == MarkerType::TOCODA)
598 	words = "\\musicglyph #\"scripts.coda\"";
599   else if (mtp == MarkerType::VARCODA)
600     words = "\\musicglyph#\"scripts.varcoda\"";
601   else if (mtp == MarkerType::USER)
602 	qDebug("unknown user marker\n");
603   else
604     qDebug("marker type=%d not implemented\n", mtp);
605   return words;
606 }
607 
608 
609 
610 //---------------------------------------------------------
611 //   symbol
612 //---------------------------------------------------------
613 
writeSymbol(QString name)614 void ExportLy::writeSymbol(QString name)
615 {
616  //  QString name = symbols[sym->sym()].name();
617   //this needs rewriting probably because of some rewriting of sym.cpp/sym.h
618   //  cout << "symbolname: " << name.toLatin1().data() << "\n";
619 
620   if (wholemeasurerest > 0) writeMeasuRestNum();
621 
622   if (name == "clef eight")
623       out << "^\\markup \\tiny\\roman 8 ";
624   else if (name == "pedal ped")
625     out << " \\sustainOn ";
626   else if (name == "pedalasterisk")
627     out << " \\sustainOff ";
628   else if (name == "scripts.trill")
629     out << "\\trill ";
630   else if (name == "scripts.flageolet")
631     out << "\\flageolet ";
632   else if (name == "rcomma")
633     out << "\\mark \\markup {\\musicglyph #\"scripts.rcomma\"} ";
634   else if (name == "lcomma")
635     out << "\\mark \\markup {\\musicglyph #\"scripts.lcomma\"} ";
636   else
637     out << "^\\markup{\\musicglyph #\"" << name << "\"} ";
638   // else if (name == "acc discant")
639   //   out << "^\\markup{\\musicglyph #\"accordion.accDiscant\"} ";
640   // else if (name == "acc dot")
641   //   //we need to place the dot on the correct place within the discant
642   //   //and other base symbols. Is this possible in mscore? The entire
643   //   //example in lily manual "2.2.3 Accordion" must be input as a
644   //   //macro?
645   //   out << "^\\markup{\\musicglyph #\"accordion.accDot\"} ";
646   // else if (name == "acc freebase")
647   //   out << "^\\markup{\\musicglyph #\"accordion.accFreebase\"} ";
648   // else if (name == "acc stdbase")
649   //   out << "^\\markup{\\musicglyph #\"accordion.accStdbase\"} ";
650   // else if (name == "acc bayanbase")
651   //   out << "^\\markup{\\musicglyph #\"accordion.accBayanbase\"} ";
652   // else if (name == "acc old ee")
653   //   out << "^\\markup{\\musicglyph #\"accordion.accOldEE\"} ";
654   // else
655   //   {
656   //   qDebug("ExportLy::symbol(): %s not supported\n", name.toLatin1().data());
657   //   return;
658   //   }
659 }
660 
661 
resetChordData(struct chordData & CD)662 void ExportLy::resetChordData(struct chordData &CD)
663 {
664   CD.chrName="";
665   CD.extName="";
666   CD.alt=0;
667   CD.bsnName="";
668   CD.tickpos=0;
669   CD.bsnAlt=0;
670   CD.ticklen=0;
671 }
672 
673 
cleanupChordList()674 void ExportLy::cleanupChordList()
675 {
676   chordPost * next;
677   chordThis = chordHead;
678   if (chordThis == 0)
679         return;
680   next = chordThis->next;
681 
682   while (next !=NULL)
683     {
684       next->prev = NULL;
685       delete chordThis;
686       chordThis = next;
687       next = next->next;
688     }
689   delete chordThis;
690 }
691 
692 
writeChordLen(int ticks)693 void ExportLy::writeChordLen(int ticks)
694 {
695   int dots = 0;
696   int len = getLen(ticks, &dots);
697 
698   switch (len)
699     {
700     case -5:
701       os << "1*5/4"; // 5/4
702       break;
703     case -4:
704       os << "2*5 "; // 5/2 ??
705       break;
706     case -3:
707       os << "1.*2 ";
708       break;
709     case -2://longa 16/4
710       os << "1*4 ";
711       break;
712     case -1: //brevis 8/4
713       os << "1*2";
714       break;
715     default:
716       os << len;
717       for (int i = 0; i < dots; ++i)
718 	os << ".";
719       break;
720     }
721 }
722 
printChordList()723 void ExportLy::printChordList()
724 {
725   chordThis = chordHead;
726   if (chordThis == 0)   // ws
727       return;
728 
729   struct chordPost * next;
730   next = chordThis->next;
731   int i=0;
732   int dots=0;
733   int lilylen=0;
734 
735   while (next != NULL)
736     {
737       i++;
738 
739       //insert spacer rests before first chord:
740       if ((i==1) and (chordThis->cd.tickpos > 0))
741 	{
742 	  int factor=1;
743 	  // works at least if denominator is 4:
744 	  if (timedenom == 2) factor=2; else factor = 1;
745 	  int measnum = chordThis->cd.tickpos / (z1 * MScore::division * factor);
746 	  qDebug("Measnum chord: \n");
747 	  int surplus = chordThis->cd.tickpos % MScore::division;
748 	  if (measnum == 0) surplus = chordThis->cd.tickpos;
749 	  level++;
750 	  indentF();
751 	  if (surplus > 0)
752 	    {
753 	      lilylen= getLen(surplus, &dots);
754 	      level++;
755 	      indentF();
756 	      os << "s" << lilylen;
757 	      while (dots>0)
758 		{
759 		  os<< ".";
760 		  dots--;
761 		}
762 	      os << " ";
763 	    }
764 	  if (measnum > 0 ) os << "s1*" << measnum<< " \n";
765 	}// end if firstone is not on tick 0 print spacer rest.
766       else
767 	{
768 	  //compute ticklen for the rest of the chords:
769 	  chordThis->cd.ticklen =  next->cd.tickpos - chordThis->cd.tickpos;
770 	  chordThis=next;
771 	  next=next->next;
772 	}
773     }//while not end of list.
774 
775   if (next == NULL)
776      chordThis->cd.ticklen= 480;
777 
778 
779   chordThis = chordHead;
780   next = chordThis;
781   //  i=0;
782 
783   indentF();
784 
785 
786   while (next != NULL)
787     {
788       next=next->next;
789       dots=0;
790       lilylen=0;
791       i++;
792       //      lilylen = getLen(chordThis->cd.ticklen, &dots);
793       os << chordThis->cd.chrName;
794       curTicks=0;
795 
796       writeChordLen(chordThis->cd.ticklen); //<< lilylen;
797 
798       while (dots > 0)
799 	{
800 	  os << ".";
801 	  dots--;
802 	}
803 
804       if (chordThis->cd.extName !="")
805 	os << ":" << chordThis->cd.extName;
806 
807       if (chordThis->cd.bsnName !="")
808 	os << "/" << chordThis->cd.bsnName;
809       if (chordThis->cd.bsnAlt > 0)
810 	os << chordThis->cd.bsnAlt;
811       os << " ";
812       chordThis=next;
813     }//end of while chordthis...
814   os << "}%%end of chordlist \n\n";
815 }//end of printChordList
816 
817 
818 
819 //-----------------------------------------------------------
820 // chord2Name
821 //-----------------------------------------------------------
chord2Name(int ch)822 QString ExportLy::chord2Name(int ch)
823       {
824       const char names[] = "fcgdaeb";
825       return QString(names[(ch + 1) % 7]);
826       }
827 
828 
829 //----------------------------------------------------------
830 // chordInsertList
831 //----------------------------------------------------------
chordInsertList(chordPost * newchord)832 void ExportLy::chordInsertList(chordPost * newchord)
833 {
834 
835   if (chordHead == NULL) //first element: make head of list.
836     {
837       chordcount++;
838       chordHead = newchord;
839       newchord->prev = NULL;
840       newchord->next = NULL;
841     }
842   else //at least one previous existent element
843     {
844       chordcount++;
845       chordThis = chordHead;
846       while ((newchord->cd.tickpos >= chordThis->cd.tickpos) && (chordThis->next != NULL))
847 	{
848 	  chordThis = chordThis->next;
849 	}
850       if ((chordThis->next == NULL) && (chordThis->cd.tickpos <= newchord->cd.tickpos)) //we have reached end of list
851 	{
852 	  //insert new element as tail
853 	  chordThis->next = newchord;
854 	  newchord->prev = chordThis;
855 	}
856       else
857 	//insert somewhere in the middle
858 	{
859 	  newchord->next = chordThis;
860 	  newchord->prev = chordThis->prev;
861 	  if (chordHead != chordThis)
862 	    {
863 	      chordThis = chordThis->prev;
864 	      chordThis->next = newchord;
865 	    }
866 	  else // the middle is immediately after head and before the tail.
867 	    {
868 	      chordThis->prev = newchord;
869 	      chordHead = newchord;
870 	    }
871 	}//middle
872     }//at least one previous
873 }//end of chordInsertList
874 
875 //-----------------------------------------------------------------
876 // storeChord
877 //-----------------------------------------------------------------
storeChord(struct InstructionAnchor chordanchor)878 void ExportLy::storeChord(struct InstructionAnchor chordanchor)
879 {
880   cout << "chords!!!\n";
881   //first create new element
882   chordPost * aux;
883   aux = new chordPost();
884   resetChordData(aux->cd);
885   aux->next = NULL;
886   aux->prev = NULL;
887 
888   //then fill it
889   Harmony* harmelm = (Harmony*) chordanchor.instruct;
890   int  chordroot = harmelm->rootTpc();
891   QString n, app;
892 
893   if (chordroot != INVALID_TPC)
894     {
895       if (nochord == true) nochord = false;
896       aux->cd.chrName = chord2Name(chordroot);
897       n=thisHarmony.chrName;
898 
899       aux->cd.tickpos = harmelm->parent()->type() == Element::SEGMENT
900          ? static_cast<Segment*>(harmelm->parent())->tick() : 0;
901 
902       if (!harmelm->xmlKind().isEmpty())
903 	{
904 	  aux->cd.extName = harmelm->extensionName();
905 	  aux->cd.extName = aux->cd.extName.toLower();
906 	}
907 
908       int alter = tpc2alter(chordroot);
909       if (alter==1) app = "is";
910       else
911 	{
912 	  if (alter == -1)
913 	    {
914 	      if (n == "e") app = "s";
915 	      else app = "es";
916 	    }
917 	}
918       aux->cd.chrName = aux->cd.chrName + app;
919 
920       int  bassnote = harmelm->baseTpc();
921       if (bassnote != INVALID_TPC)
922 	{
923 	  aux->cd.bsnName = chord2Name(bassnote);
924 	  int alter = tpc2alter(bassnote);
925 	  n=aux->cd.bsnName;
926 
927 	  if (alter==1) app = "is";
928 	  else if (alter == -1)
929 	  {
930 	    if (n=="e")  app =  "s"; else app = "es";
931 	  }
932 
933 	  aux->cd.bsnName = n + app;
934 	  aux->cd.bsnAlt=alter;
935 	} //end if bassnote
936       //and at last insert it in list:
937       chordInsertList(aux);
938     }//end if chordroot
939   else
940     storeAnchor(anker);
941 }
942 
943 
944 //---------------------------------------------------------
945 //   tempoText
946 //---------------------------------------------------------
947 
tempoText(TempoText * text)948 void ExportLy::tempoText(TempoText* text)
949       {
950 	QString temptekst = text->text();
951 	double met = text->tempo();
952 	int metronome;
953 	metronome = (int) (met * 60);
954 	out << "\\tempo \""  << text->text() << "\" " <<  timedenom << " = " << metronome << "  ";
955       }
956 
957 
958 
959 //---------------------------------------------------------
960 //   words
961 //---------------------------------------------------------
962 
words(Text * text)963 void ExportLy::words(Text* text)
964      {
965        QString style;
966        int size;
967        findTextProperties(text,style,size);
968        //todo: find exact mscore-position of text and not only anchorpoint, and position accordingly in lily.
969 //TODO     if ((text->subtypeName() != "RehearsalMark"))
970        // if (text->text() != "")
971        out << "^\\markup {" << style<< " \"" << text->text() << "\"} ";
972      //     qDebug("tekst %s\n", tekst.toLatin1().data());
973       }
974 
975 
976 
977 //---------------------------------------------------------
978 //   hairpin
979 //---------------------------------------------------------
980 
hairpin(Hairpin * hp,int tick)981 void ExportLy::hairpin(Hairpin* hp, int tick)
982 { // print hairpin from anchorlist
983   // todo: find exact mscore-position of
984   // hairpin start and end and not only anchorpoint, and position
985   // accordingly in lily.
986 	int art=2;
987 	art=hp->hairpinType();
988 	if (hp->tick() == tick)
989 	  {
990 	    if (art == 0) //diminuendo
991 	      out << "\\< ";
992 	    if (art == 1) //crescendo
993 	      out << "\\> ";
994 	    if (art > 1 ) out << "\\!x ";
995 	  }
996 //TODO-WS       if (hp->tick2() == tick) out << "\\! "; //end of hairpin
997       }
998 
999 //---------------------------------------------------------
1000 //  start ottava
1001 //---------------------------------------------------------
1002 
ottava(Ottava * ot,int tick)1003 void ExportLy::ottava(Ottava* ot, int tick)
1004 {
1005   int st = ot->ottavaType();
1006   if (ot->tick() == tick)
1007     {
1008       switch(st) {
1009       case 0:
1010 	out << "\\ottva ";
1011 	break;
1012       case 1:
1013 	out << "\\ottva \\once\\override TextSpanner #'(bound-details left text) = \"15va\" \n";
1014 	indent();
1015 	break;
1016       case 2:
1017 	out << "\\ottvabassa ";
1018 	break;
1019       case 3:
1020 	out << "\\ottvabassa \\once \\override TextSpanner #'(bound-details left text) = \"15vb\"  \n";
1021 	indent();
1022 	break;
1023       default:
1024 	qDebug("ottava subtype %d not understood\n", st);
1025       }
1026     }
1027   else {
1028      	  out << "\\ottvaend ";
1029         }
1030 }
1031 
1032 
1033 //---------------------------------------------------------
1034 //   pedal
1035 //---------------------------------------------------------
1036 
pedal(Pedal * pd,int tick)1037 void ExportLy::pedal(Pedal* pd, int tick)
1038       {
1039       if (pd->tick() == tick)
1040 	out << "\\sustainOn ";
1041       else
1042 	out << "\\sustainOff ";
1043       }
1044 
1045 
1046 
1047 //---------------------------------------------------------
1048 //   dynamic
1049 //---------------------------------------------------------
dynamic(Dynamic * dyn,int nop)1050 void ExportLy::dynamic(Dynamic* dyn, int nop)
1051 {
1052   QString t = dyn->text();
1053   if (t == "p" || t == "pp" || t == "ppp" || t == "pppp" || t == "ppppp" || t == "pppppp"
1054       || t == "f" ||
1055       t == "ff" || t == "fff" || t == "ffff" || t == "fffff" || t == "ffffff"
1056       || t == "mp" || t == "mf" || t == "sf" || t == "sfp" || t == "sfpp" || t == "fp"
1057       || t == "rf" || t == "rfz" || t == "sfz" || t == "sffz" || t == "fz" || t == "sff")
1058     {
1059 	switch(nop)
1060 	    {
1061 	    case 0:
1062 		out << "\\" << t << " ";
1063 		break;
1064 	    case 1:
1065 		out << "_\\markup\{\\dynamic " << t.toLatin1().data() << " \\halign #-2 ";
1066 		break;
1067 	    case 2:
1068 		out <<  " \\dynamic " << t.toLatin1().data() << " } ";
1069 		break;
1070 	    default:
1071 		out << "\\" << t.toLatin1().data() << " ";
1072 		break;
1073 	    }
1074 
1075     }
1076   else if (t == "m" || t == "z")
1077     {
1078       out << "\\"<< t.toLatin1().data() << " ";
1079     }
1080     else
1081       out << "_\\markup{\""<< t.toLatin1().data() << "\"} ";
1082 }//end dynamic
1083 
1084 
1085 //-----------------------------------------------------------------------------------
1086 // findTextProperties
1087 //-----------------------------------------------------------------------------------
findTextProperties(Text * tekst,QString & tekststyle,int & fontsize)1088 void ExportLy::findTextProperties(Text* tekst, QString &tekststyle, int &fontsize)
1089 {
1090   QFont fontprops=tekst->font();
1091   fontsize= fontprops.pointSizeF();
1092   switch (fontprops.style())
1093     {
1094     case QFont::StyleNormal :
1095       tekststyle = "\\upright ";
1096       break;
1097     case QFont::StyleItalic :
1098     case QFont::StyleOblique:
1099       tekststyle = "\\italic";
1100       break;
1101     default :
1102       tekststyle = "\\upright ";
1103       break;
1104     }
1105   switch (fontprops.weight())
1106     {
1107     case QFont::Light:
1108     case QFont::Normal:
1109       break;
1110     case QFont::DemiBold:
1111     case QFont::Bold:
1112     case QFont::Black:
1113       tekststyle += "\\bold ";
1114       break;
1115     default:
1116       break;
1117     }
1118 }//end findTextProperties
1119 
1120 //---------------------------------------------------------
1121 //   textLine
1122 //---------------------------------------------------------
1123 
textLine(Element * instruction,int tick,bool pre)1124 void ExportLy::textLine(Element* instruction, int tick, bool pre)
1125 {
1126   qDebug("textline\n");
1127   QString rest;
1128   QPointF point;
1129   QString lineEnd = "none";
1130   QString type;
1131   //  int lineoffset;
1132   QString lineType;
1133 //  SLine* sl = (SLine*) instruction;
1134   int fontsize=0;
1135   TextLine* tekstlinje = (TextLine *) instruction;
1136   bool post = false;
1137   if (pre == false) post = true;
1138 
1139   //start of line:
1140   if (tekstlinje->tick() == tick)
1141     {
1142       if (pre)
1143 	{
1144 	  switch (tekstlinje->lineStyle())
1145 	    {
1146 	    case Qt::DashDotLine:
1147 	    case Qt::DashDotDotLine:
1148 	    case Qt::DashLine:
1149 	      out << " \\once\\override TextSpanner  #'style = #'dashed-line \n";
1150 	      indent();
1151 	      break;
1152 	    case Qt::DotLine:
1153 	      out << " \\once\\override TextSpanner  #'style = #'dotted-line \n";
1154 	      indent();
1155 	      break;
1156 	    default:
1157 	      break;
1158 	    }
1159 	  if (tekstlinje->endHook())
1160 	    {
1161 	      double h = tekstlinje->endHookHeight().val();
1162 	      if (h < 0.0)
1163 		{
1164 		  out << "\\once\\override TextSpanner #'(bound-details right text) = \\markup{ \\draw-line #'(0 . 1) }\n";
1165 		  indent();
1166 		}
1167 	      else
1168 		{
1169 		  out << "\\once\\override TextSpanner #'(bound-details right text) = \\markup{ \\draw-line #'(0 . -1) }\n";
1170 		  indent();
1171 		}
1172 	    }
1173 	  if (tekstlinje->beginText())
1174 	    {
1175 	      QString linetext = tekstlinje->beginText()->text();
1176 	      Text* tekst = (Text*) tekstlinje->beginText();
1177 	      QString tekststyle = "";
1178 	      findTextProperties(tekst, tekststyle, fontsize);
1179 	      out << "\\once\\override TextSpanner #'(bound-details left text) = \\markup{";
1180 	      out << tekststyle<< "\"" << linetext <<"\"} \n";
1181 	      indent();
1182 	    }
1183 	  point = tekstlinje->frontSegment()->userOff();
1184 	  if (point.y() > 0.0) //below
1185 	    {
1186 	      out <<"\\textSpannerDown ";
1187 	      textspannerdown=true;
1188 	    }
1189 	  else if (textspannerdown)
1190 	    {
1191 	      out << "\\textSpannerNeutral ";
1192 	      textspannerdown = false;
1193 	    }
1194 	}// end if pre
1195 
1196       else if (post) //after note, start of line.
1197 	{
1198 	  out << "\\startTextSpan ";
1199 	  textspanswitch=true;
1200 	}// end if post: after note, start of textline
1201     }//end of start-of-textline
1202 #if 0 // TODO-WS
1203   else if  (sl->tick2() == tick)  //at end of textline.
1204     {
1205       if (pre)
1206 	{
1207 	  out << "\\stopTextSpan ";
1208 	  textspanswitch=false;
1209 	   // from exportxml.cpp: output of user offset from anchor:
1210 	  // userOff2 is relative to userOff in MuseScore
1211 	  //            point = tekstlinje->lineSegments().last()->userOff2() + tekstlinje->lineSegments().first()->userOff();
1212 	  //            lineoffset = tekstlinje->mxmlOff2();
1213 	}
1214       else if (post)
1215 	{
1216 	  //just relax for the moment.
1217 	}
1218     }// end if tick2()
1219 #endif
1220 }// end of textLine()
1221 
1222 
1223 //---------------------------------------------------------------------
1224 // anchortest
1225 //---------------------------------------------------------------------
anchortest()1226 void ExportLy::anchortest()
1227 {
1228       int i;
1229       for (i=0; i<nextAnchor ; i++)
1230 	{
1231 	  Element * instruction = anchors[i].instruct;
1232 	  ElementType instructiontype = instruction ->type();
1233 //	  Text* text = (Text*) instruction;
1234 	  qDebug("anker nr: %d ", i);
1235 	  switch(instructiontype)
1236 	    {
1237 	    case Element::STAFF_TEXT:
1238 	      qDebug("STAFF_TEXT ");
1239 //TODO	      if (text->subtypeName()== "RehearsalMark") qDebug(" rehearsal STAFF ");
1240 	      qDebug("\n");
1241 	      break;
1242 	    case Element::TEXT:
1243 	      qDebug("TEXT ");
1244 //	      if (text->subtypeName()== "RehearsalMark") qDebug(" rehearsal MEASURE");
1245 	      qDebug("\n");
1246 	      break;
1247 	    case Element::MARKER:
1248 	      qDebug("MARKER\n");
1249 	      break;
1250 	    case Element::JUMP:
1251 	      qDebug("JUMP\n");
1252 	      break;
1253 	    case Element::SYMBOL:
1254 	      qDebug("SYMBOL\n");
1255 	      break;
1256 	    case Element::TEMPO_TEXT:
1257 	      qDebug("TEMPOTEXT MEASURE\n");
1258 	      break;
1259 	    case Element::DYNAMIC:
1260 	      qDebug("Dynamic\n");
1261 	      break;
1262 	    case Element::HARMONY:
1263 	      qDebug("akkordnavn. \n");
1264 	      break;
1265 	    case Element::HAIRPIN:
1266 	      qDebug("hairpin \n");
1267 	      break;
1268 	    case Element::PEDAL:
1269 	      qDebug("pedal\n");
1270 	      break;
1271 	    case Element::TEXTLINE:
1272 	      qDebug("textline\n");
1273 	      break;
1274 	    case Element::OTTAVA:
1275 	      qDebug("ottava\n");
1276 	      break;
1277 	    default: break;
1278 	    }
1279 	}
1280       qDebug("Anchortest finished\n");
1281 }//end anchortest
1282 
1283 
1284 
1285 
1286 
1287 //---------------------------------------------------------------------
1288 // jumptest
1289 //---------------------------------------------------------------------
jumptest()1290 void ExportLy::jumptest()
1291 {
1292   qDebug("at jumptest A lastjump %d\n", lastJumpOrMarker);
1293       int i;
1294       for (i=0; i<lastJumpOrMarker; i++)
1295 	{
1296 	  qDebug("jumptest 1\n");
1297 	  Element * merke = jumpOrMarkerList[i].marker;
1298 	  qDebug("jumptest 2\n");
1299 	  ElementType instructiontype = merke->type();
1300 	  qDebug("jumptest 3\n");
1301 //	  Text* text = (Text*) merke;
1302 	  qDebug("jumptest 4\n");
1303 	  qDebug("marker nr: %d ", i);
1304 	  switch(instructiontype)
1305 	    {
1306 	    case Element::STAFF_TEXT:
1307 	      qDebug("STAFF_TEXT ");
1308 //	      if (text->subtypeName()== "RehearsalMark") qDebug(" rehearsal ");
1309 	      qDebug("\n");
1310 	      break;
1311 	    case Element::TEXT:
1312 	      qDebug("TEXT ");
1313 //	      if (text->subtypeName()== "RehearsalMark") qDebug(" rehearsal ");
1314 	      qDebug("\n");
1315 	      break;
1316 	    case Element::MARKER:
1317 	      qDebug("MARKER\n");
1318 	      break;
1319 	    case Element::JUMP:
1320 	      qDebug("JUMP\n");
1321 	      break;
1322 	    case Element::SYMBOL:
1323 	      qDebug("SYMBOL\n");
1324 	      break;
1325 	    case Element::TEMPO_TEXT:
1326 	      qDebug("TEMPOTEXT MEASURE\n");
1327 	      break;
1328 	    case Element::DYNAMIC:
1329 	      qDebug("Dynamic\n");
1330 	      break;
1331 	    case Element::HARMONY:
1332 	      qDebug("akkordnavn. \n");
1333 	      break;
1334 	    case Element::HAIRPIN:
1335 	      qDebug("hairpin \n");
1336 	      break;
1337 	    case Element::PEDAL:
1338 	      qDebug("pedal\n");
1339 	      break;
1340 	    case Element::TEXTLINE:
1341 	      qDebug("textline\n");
1342 	      break;
1343 	    case Element::OTTAVA:
1344 	      qDebug("ottava\n");
1345 	      break;
1346 	    default:
1347 	      break;
1348 	    }
1349 	}
1350 }//end jumptest
1351 
1352 
1353 
1354 //--------------------------------------------------------
1355 //  initAnchors
1356 //--------------------------------------------------------
initAnchors()1357 void ExportLy::initAnchors()
1358 {
1359   int i;
1360   for (i=0; i<1024; i++)
1361     resetAnchor(anchors[i]);
1362 }
1363 
1364 
1365 
1366 //--------------------------------------------------------
1367 //   resetAnchor
1368 //--------------------------------------------------------
resetAnchor(struct InstructionAnchor & ank)1369 void ExportLy::resetAnchor(struct InstructionAnchor &ank)
1370 {
1371   ank.instruct=0;
1372   ank.anchor=0;
1373   ank.start=false;
1374   ank.tick=0;
1375 }
1376 
1377 //---------------------------------------------------------
1378 //   deleteAnchor
1379 //---------------------------------------------------------
removeAnchor(int ankind)1380 void ExportLy::removeAnchor(int ankind)
1381 {
1382   int i;
1383   resetAnchor(anchors[ankind]);
1384   for (i=ankind; i<=nextAnchor; i++)
1385     anchors[i]=anchors[i+1];
1386   resetAnchor(anchors[nextAnchor]);
1387   nextAnchor=nextAnchor-1;
1388 }
1389 
1390 //---------------------------------------------------------
1391 //   storeAnchor
1392 //---------------------------------------------------------
1393 
storeAnchor(struct InstructionAnchor a)1394 void ExportLy::storeAnchor(struct InstructionAnchor a)
1395       {
1396 	if (nextAnchor < 1024)
1397 	  {
1398 	    anchors[nextAnchor++] = a;
1399 	  }
1400 	else
1401 	  qDebug("InstructionHandler: too many instructions\n");
1402 	resetAnchor(anker);
1403       }
1404 
writeCombinedMarker(int foundJoM,Element * elm)1405 void ExportLy::writeCombinedMarker(int foundJoM, Element* elm)
1406 {
1407   out << "\\mark\\markup\\column \{ \n";
1408   level++;
1409   indent();
1410   if (foundJoM == Element::MARKER)
1411     {
1412       QString primark = primitiveMarker((Marker*)elm);
1413       out << primark << "\n";
1414     }
1415   if (foundJoM == Element::JUMP)
1416     out << primitiveJump((Jump*) elm) << "\n";
1417   indent();
1418   out << "\\box\\bold \"";
1419   if (rehearsalnumbers)
1420     out << (int)privateRehearsalMark; //+n
1421   else
1422     out << privateRehearsalMark << "\" \n";
1423   indent();
1424   level--;
1425   indent();
1426   out << "} \n";
1427   indent();
1428   out << "\\set Score.rehearsalMark = #" << (int)privateRehearsalMark-63 << "\n";
1429   indent();
1430 }
1431 
1432 
1433 
1434 
1435 //-----------------------------------------------------------------
1436 // handlePreInstruction -- handle the instructions attached to one
1437 // specific element and which are to be exported BEFORE the element
1438 // itself.
1439 // -----------------------------------------------------------------
1440 
handlePreInstruction(Element * el)1441 void ExportLy::handlePreInstruction(Element * el)
1442 {
1443   int i = 0;
1444   int foundJoM = 0;
1445   Text* tekst;
1446   for (i = 0; i <= nextAnchor; i++) //run thru anchorlist
1447     {
1448       if  ((anchors[i].anchor != 0) && (anchors[i].anchor == el))
1449 	{
1450 	  Element * instruction = anchors[i].instruct;
1451 	  ElementType instructiontype = instruction->type();
1452 
1453 	  switch(instructiontype)
1454 	    {
1455 	    case Element::STAFF_TEXT:
1456 	    case Element::REHEARSAL_MARK:
1457 	      {
1458 		    tekst = (Text*) instruction;
1459 		    if (wholemeasurerest >=1) writeMeasuRestNum();
1460 		    bool ok = false;
1461 		    // int dec=0;
1462 		    QString c;
1463 		    c=tekst->text();
1464 		    // dec = c.toInt(&ok, 10);
1465 		    if (ok) rehearsalnumbers=true;
1466 		    Element* elm = 0;
1467     		    foundJoM = checkJumpOrMarker(measurenumber, true, elm); //true means at the start of measure.
1468 		      if (foundJoM)
1469 			writeCombinedMarker(foundJoM,elm);
1470 		      else
1471 		        out << "\\mark\\default ";//xxx
1472 		      privateRehearsalMark++;
1473 		      removeAnchor(i); //to use this caused trouble at another place. Maybe remove?
1474 		break;
1475 	      }
1476 	    case Element::OTTAVA:
1477 	      if (wholemeasurerest >=1) writeMeasuRestNum();
1478 	      ottvaswitch=true;
1479 	      ottava((Ottava*) instruction, anchors[i].tick);
1480 	      removeAnchor(i);
1481 	      break;
1482 	    case Element::TEMPO_TEXT:
1483 	      tempoText((TempoText*) instruction);
1484 	      removeAnchor(i);
1485 	      break;
1486 	    case Element::TEXTLINE:
1487 	      textLine(instruction, anchors[i].tick, true);
1488 	      break;
1489 	    default: break;
1490 	    }//end switch
1491 	}//end if anchors
1492     }//end for (i...)
1493 }//End of handlePreInstructiion
1494 
1495 
1496 
1497 //---------------------------------------------------------
1498 //   handleElement -- handle all instructions attached to one specific
1499 //   element and which are to be exported AFTER the element itself.
1500 //---------------------------------------------------------
1501 
handleElement(Element * el)1502 void ExportLy::handleElement(Element* el)
1503 {
1504   int i = 0;
1505   Symbol * sym;
1506   QString name;
1507   for (i = 0; i<=nextAnchor; i++)//run thru filled part of list
1508     {
1509 	if (anchors[i].anchor != 0 and anchors[i].anchor==el) // if anchored to this element
1510 	    {
1511 		Element* instruction = anchors[i].instruct;
1512 		ElementType instructiontype = instruction->type();
1513 
1514 		switch(instructiontype)
1515 		    {
1516 		    case Element::MARKER:
1517 			qDebug("MARKER\n");
1518 			instructionMarker((Marker*) instruction);
1519 			break;
1520 		    case Element::JUMP:
1521 			qDebug("JUMP\n");
1522 			instructionJump((Jump*) instruction);
1523 			break;
1524 		    case Element::SYMBOL:
1525 			{
1526 			    cout << "symbol in anchorlist tick: " << anchors[i].tick << "  \n";
1527 			    sym = (Symbol*) instruction;
1528 			    name = Sym::id2name(sym->sym());
1529 			    writeSymbol(name);
1530 			    break;
1531 			}
1532 		    case Element::TEMPO_TEXT:
1533 			//   qDebug("TEMPOTEXT MEASURE\n");
1534 			//   tempoText((TempoText*) instruction);
1535 			break;
1536 		    case Element::STAFF_TEXT:
1537 		    case Element::TEXT:
1538 			cout << "anchored text \n";
1539 			if (wholemeasurerest)
1540 			    {
1541 				Text* wmtx = (Text*) instruction;
1542 				wholemeasuretext = wmtx->text();
1543 			    }
1544 			else
1545 			    words((Text*) instruction);
1546 			break;
1547 		    case Element::DYNAMIC:
1548 			{
1549 			    int nextorprev=0;
1550 
1551 			    if ((anchors[i+1].anchor != 0) and (anchors[i+1].anchor==el))
1552 				{
1553 
1554 				    Element* nextinstruct = anchors[i+1].instruct;
1555 				    ElementType nextinstrtype = nextinstruct->type();
1556 				    if (nextinstrtype == Element::DYNAMIC)
1557 				    nextorprev = 1;
1558 				}
1559 			    else if ((anchors[i-1].anchor != 0) and (anchors[i-1].anchor==el))
1560 				{
1561 				    Element* previnstruct = anchors[i-1].instruct;
1562 				    ElementType previnstrtype = previnstruct->type();
1563 				    if (previnstrtype == Element::DYNAMIC)
1564 					nextorprev=2;
1565 				}
1566 			    dynamic((Dynamic*) instruction, nextorprev);
1567 			    break;
1568 			}
1569 		    case Element::HAIRPIN:
1570 			hairpin((Hairpin*) instruction, anchors[i].tick);
1571 			break;
1572 		    case Element::HARMONY:
1573 			words((Text*) instruction);
1574 			break;
1575 		    case Element::PEDAL:
1576 			pedal((Pedal*) instruction, anchors[i].tick);
1577 			break;
1578 		    case Element::TEXTLINE:
1579 			textLine(instruction, anchors[i].tick, false);
1580 			break;
1581 		    case Element::OTTAVA:
1582 			break;
1583 		    default:
1584 			qDebug("post-InstructionHandler::handleElement: direction type %s at tick %d not implemented\n",
1585 			       Element::name(instruction->type()), anchors[i].tick);
1586 			break;
1587 		    }
1588 		//	  removeAnchor(i);
1589 	    }
1590     } //foreach position i anchor-array.
1591 }
1592 
1593 
1594 
1595 
1596 //--------------------------------------------------------
1597 //   resetMarkerLM
1598 //--------------------------------------------------------
resetJumpOrMarkerLM(struct jumpOrMarkerLM & mlm)1599 void ExportLy::resetJumpOrMarkerLM(struct jumpOrMarkerLM &mlm)
1600 {
1601   mlm.marker=0;
1602   mlm.measurenum=0;
1603   mlm.start=false;
1604 }
1605 
1606 //--------------------------------------------------------
1607 //  initMarkerLMs
1608 //--------------------------------------------------------
initJumpOrMarkerLMs()1609 void ExportLy::initJumpOrMarkerLMs()
1610 {
1611   int i;
1612   for (i=0; i<100; i++)
1613     resetJumpOrMarkerLM(jumpOrMarkerList[i]);
1614 }
1615 
1616 //---------------------------------------------------------
1617 //   removeMarkerLM -- not used ?!
1618 //---------------------------------------------------------
removeJumpOrMarkerLM(int markerind)1619 void ExportLy::removeJumpOrMarkerLM(int markerind)
1620 {
1621   int i;
1622   resetJumpOrMarkerLM(jumpOrMarkerList[markerind]);
1623   for (i=markerind; i<=nextAnchor; i++)
1624     jumpOrMarkerList[i]=jumpOrMarkerList[i+1];
1625   resetJumpOrMarkerLM(jumpOrMarkerList[lastJumpOrMarker]);
1626   lastJumpOrMarker=lastJumpOrMarker-1;
1627 }
1628 
1629 
1630 //---------------------------------------------------------------------
1631 // preserveJumpOrMark
1632 //---------------------------------------------------------------------
1633 
preserveJumpOrMarker(Element * dir,int mnum,bool start)1634 void ExportLy::preserveJumpOrMarker(Element* dir, int mnum, bool start)
1635 {
1636   jumpswitch=true;
1637   jumpOrMarkerLM mlm;
1638   Marker* ma = (Marker*) dir;
1639   mlm.marker = ma;
1640   mlm.measurenum = mnum;
1641   mlm.start = start;
1642   if (lastJumpOrMarker < 100)
1643     {
1644       lastJumpOrMarker++;
1645       jumpOrMarkerList[lastJumpOrMarker] = mlm;
1646     }
1647   else
1648     qDebug("PreserveMarker: Too many marksorjumps\n");
1649 }
1650 
1651 
1652 
1653 //--------------------------------------------------------------------
1654 // checkJumpOrMarker
1655 //---------------------------------------------------------------------
checkJumpOrMarker(int mnum,bool start,Element * & moj)1656 int ExportLy::checkJumpOrMarker(int mnum, bool start, Element* &moj)
1657 {
1658   cout << "checkjumpormarker\n";
1659 
1660   int tp=0;
1661   int i=0;
1662 
1663   if (start) mnum--; //we place these things at the end of the previous measure
1664   cout << "mnum: " << mnum << "\n";
1665 
1666   while (jumpOrMarkerList[i].measurenum < mnum)
1667     {
1668       ++i;
1669       if (jumpOrMarkerList[i].measurenum ==0 )
1670 	goto endofcheck;
1671     }
1672 
1673   while ((jumpOrMarkerList[i].measurenum == mnum) and (i < 100))
1674     {
1675       cout << "found measure  " << jumpOrMarkerList[i].start << "\n";
1676       if (jumpOrMarkerList[i].start == true)
1677 	{
1678 	  moj = jumpOrMarkerList[i].marker;
1679 	  tp = moj->type();
1680 	  cout << "moj->type: " << tp << "\n";
1681     	}
1682       i++;
1683       cout << i << "\n";
1684       // if (i >= 100)
1685       // 	break;
1686     }
1687  endofcheck:
1688   cout << "checkjumpormarker, type: " << tp << "\n";
1689   return tp;
1690 }
1691 
1692 
1693 //--------------------------------------------------------------------
1694 // printJumpOrMarker
1695 //---------------------------------------------------------------------
printJumpOrMarker(int mnum,bool start)1696 void ExportLy::printJumpOrMarker(int mnum, bool start)
1697 {
1698   cout << "printjumpormarker 1\n";
1699 
1700   int i=0;
1701   while (jumpOrMarkerList[i].measurenum < mnum)
1702     i++;
1703 
1704   cout << "test 2\n";
1705 
1706   while ((jumpOrMarkerList[i].measurenum == mnum) and (i < 100))
1707     {
1708       cout << "test 3\n";
1709 
1710       if (jumpOrMarkerList[i].start == start)
1711 	{
1712 	  cout << "test 4\n";
1713 
1714 	  Element* moj = jumpOrMarkerList[i].marker;
1715 	  int tp = moj->type();
1716 	  if (tp == Element::MARKER)
1717 	    {
1718 	      cout << "test 5\n";
1719 	      Marker* ma = (Marker*) moj;
1720 	      instructionMarker(ma);
1721 	    }
1722 	  else if (tp ==Element::JUMP)
1723 	    {
1724 	      cout << "test 6\n";
1725 	      Jump* jp = (Jump*) moj;
1726 	      instructionJump(jp);
1727     	    }
1728     	  cout << "test 7\n";
1729     	}
1730       i++;
1731       cout << i << "\n";
1732       // if (i >= 100)
1733       // 	break;
1734     }
1735   cout << "test 8\n";
1736 }
1737 
1738 
1739 
1740 //---------------------------------------------------------------------
1741 // findMarkerAtMeasureStart
1742 //---------------------------------------------------------------------
1743 
1744 
findMarkerAtMeasureStart(Measure * m)1745 void ExportLy::findMarkerAtMeasureStart(Measure* m)
1746 {
1747    for (auto ci = m->el()->begin(); ci != m->el()->end(); ++ci)
1748      {
1749        Element* dir = *ci;
1750        int tp = dir->type();
1751        if (tp == Element::MARKER)
1752   	 { //only markers, not jumps, are used at measure start.
1753 	   Marker* ma = (Marker*) dir;
1754 	   MarkerType mtp = ma->markerType();
1755 	   //discard markers which belong at measure end:
1756 	   if (!(mtp == MarkerType::FINE || mtp == MarkerType::TOCODA))
1757 	     {
1758 	       cout << "marker found at measure: " << measurenumber << "\n";
1759 	       //	       instructionMarker(ma);
1760 	       preserveJumpOrMarker(dir, measurenumber, true); //true means start of measure
1761 	     }
1762   	 }
1763      }
1764 }
1765 
1766 //---------------------------------------------------------
1767 //  jumpAtMeasureStop -- write jumps at end of measure
1768 //---------------------------------------------------------
1769 
jumpAtMeasureStop(Measure * m)1770 void ExportLy::jumpAtMeasureStop(Measure* m)
1771       {
1772 	// loop over all measure relative elements in this measure
1773 	// looking for JUMPS and MARKERS
1774 	for (auto ci = m->el()->begin(); ci != m->el()->end(); ++ci)
1775 	  {
1776 	    Element* dir = *ci;
1777 	    int tp = dir->type();
1778 	    bool end; // start;
1779 	    // start=true;
1780 	    end=false;
1781 
1782 	    if (tp == Element::JUMP)
1783 	      {
1784 		// all jumps are handled at measure end
1785 		Jump* jp = (Jump*) dir;
1786 		//writing the jump-mark in part one of the score:
1787 		instructionJump(jp);
1788 		// in mscore jumps and markers are found only in the
1789 		// first staff. If it shall be possible to extract
1790 		// parts from the exported lilypond-score, jumps and
1791 		// markers must be inserted in each and every part. We
1792 		// will hence have to preserve those elements in a list
1793 		// to be used when we write the parts other than the
1794 		// first in our lilypond-score:
1795 	      	preserveJumpOrMarker(dir, measurenumber, end);
1796 	      }
1797 	    else if (tp == Element::MARKER)
1798 	      {
1799 		Marker* ma = (Marker*) dir;
1800 		MarkerType mtp = ma->markerType();
1801 		//only print markers which belong at measure end:
1802 		if (mtp == MarkerType::FINE || mtp == MarkerType::TOCODA)
1803 		  {
1804 		    //print the marker in part one
1805 		    instructionMarker(ma);
1806 		    //preserve the marker for later use in other parts:
1807 		    preserveJumpOrMarker(dir, measurenumber, end);
1808 		  }
1809 	      }
1810 	  }
1811       }
1812 
1813 
1814 
1815 //---------------------------------------------------------
1816 //   findMatchInMeasure -- find chord or rest in measure
1817 //     starting or ending at tick
1818 //---------------------------------------------------------
findMatchInMeasure(int tick,Staff * stf,Measure * m,int strack,int etrack,bool rehearsalmark)1819 bool ExportLy::findMatchInMeasure(int tick, Staff* stf, Measure* m, int strack, int etrack, bool rehearsalmark)
1820 {
1821   int iter=0;
1822   bool  found = false;
1823 
1824   for (int st = strack; st < etrack; ++st)
1825     {
1826       for (Segment* seg = m->first(); seg; seg = seg->next())
1827 	{
1828 	  iter ++;
1829 	  Element* el = seg->element(st);
1830 	  if (!el) continue;
1831 
1832 	  if ((el->isChordRest()) and ((el->staff() == stf) or (rehearsalmark==true)) && ((seg->tick() >= tick)))
1833 	    {
1834 	      if (seg->tick() > tick) tick=prevElTick;
1835 	      anker.anchor=el;
1836 	      found=true;
1837 	      anker.tick=tick;
1838 	      anker.start=true;
1839 	      goto fertig;
1840 	    }
1841 	    prevElTick = seg->tick();
1842 	 }
1843     }
1844  fertig:
1845  return found;
1846 }
1847 
1848 
1849 //---------------------------------------------------------
1850 //   findMatchInPart -- find chord or rest in part
1851 //     starting or ending at tick
1852 //---------------------------------------------------------
1853 
findMatchInPart(int tick,Staff * stav,Score * sc,int starttrack,int endtrack,bool rehearsalmark)1854 bool ExportLy::findMatchInPart(int tick, Staff* stav, Score* sc, int starttrack, int endtrack, bool rehearsalmark)
1855 {
1856 
1857   bool found=false;
1858   for (MeasureBase* mb = sc->measures()->first(); mb; mb = mb->next())
1859     {
1860       if (mb->type() != Element::MEASURE)
1861 	continue;
1862       Measure* m = (Measure*)mb;
1863       found = findMatchInMeasure(tick, stav, m, starttrack, endtrack, rehearsalmark);
1864       if (found) break;
1865      }
1866 return found;
1867 }
1868 
1869 //---------------------------------------------------------
1870 //     buildInstructionList -- associate instruction (measure relative elements)
1871 //     with elements in segments to enable writing at the correct position
1872 //     in the output stream. Called once for every part to handle all part-level elements.
1873 //---------------------------------------------------------
1874 
buildInstructionListPart(int strack,int etrack)1875 void ExportLy::buildInstructionListPart(int strack, int etrack)
1876 {
1877 
1878   // part-level elements stored in the score layout: at the global level
1879   prevElTick=0;
1880 #if 0 // TODO-WS implementation changed
1881   foreach(Element* instruction, *(score->gel()))
1882     {
1883       bool found=false;
1884       bool rehearsalm=false;
1885       switch(instruction->type())
1886 	{
1887 	case Element::JUMP:
1888 //TODO-WS	   qDebug("score JUMP found at tick: %d\n", instruction->tick());
1889             break;
1890 	case Element::MARKER:
1891 /*TODO-WS	    qDebug("score MARKER found at tick: %d\n", instruction->tick()); */ break;
1892 	case Element::HAIRPIN:
1893 	case Element::HARMONY:
1894 	case Element::OTTAVA:
1895 	case Element::PEDAL:
1896 	case Element::DYNAMIC:
1897 	case Element::TEXT:
1898 	case Element::TEXTLINE:
1899 	  {
1900 	    SLine* sl = (SLine*) instruction;
1901 	    Text* tekst = (Text*) instruction;
1902 	    //	    if (tekst->subtypeName() == "System") qDebug("Systemtekst in part\n");
1903 	    //      if (tekst->subtypeName() == "Staff")  qDebug("Stafftest in part\n");
1904 	    if (tekst->subtypeName() == "RehearsalMark")
1905 	      {
1906 		rehearsalm=true;
1907 		qDebug("found rehearsalmark in part\n");
1908 	      }
1909 	    //start of instruction:
1910 	    found=findMatchInPart(sl->tick(), sl->staff(), score, strack, etrack, rehearsalm);
1911 	    if (found)
1912 	      {
1913 		anker.instruct=instruction;
1914 		storeAnchor(anker);
1915 	      }
1916 	    //end of instruction:
1917 //TODO-WS	    found=findMatchInPart(sl->tick2(), sl->staff(), score, strack, etrack, rehearsalm);
1918 	    if (found)
1919 	      {
1920 		anker.instruct=instruction;
1921 		storeAnchor(anker);
1922 	      }
1923 	    break;
1924 	  } //end textline
1925 	default:
1926 	  // all others ignored
1927 	  // qDebug(" instruction type %s not implemented\n", Element::name(instruction->type()));
1928 	  break;
1929 	}
1930     }// end foreach element....
1931 #endif
1932 
1933   // part-level elements stored in measures:
1934   for (MeasureBase* mb = score->measures()->first(); mb; mb = mb->next())
1935     {
1936       if (mb->type() != Element::MEASURE)
1937 	continue;
1938       Measure* m = (Measure*)mb;
1939       buildInstructionList(m, strack, etrack);
1940     }
1941 }//end: buildInstructionList
1942 
1943 
1944 //---------------------------------------------------------
1945 //   buildInstructionList -- associate instruction (measure relative elements)
1946 //     with elements in segments to enable writing at the correct position
1947 //     in the output stream. Called once for every measure to handle either
1948 //     part-level or measure-level elements.
1949 //---------------------------------------------------------
1950 
buildInstructionList(Measure * m,int strack,int etrack)1951 void ExportLy::buildInstructionList(Measure* m, int strack, int etrack)
1952 {
1953 
1954   // loop over all measure relative elements in this measure
1955   for (auto ci = m->el()->begin(); ci != m->el()->end(); ++ci)
1956     {
1957       bool found=false;
1958 //      bool rehearsal=false;
1959 
1960       Element* instruction = *ci;
1961       switch(instruction->type())
1962 	{
1963 	case Element::DYNAMIC:
1964 	case Element::SYMBOL:
1965 	case Element::TEMPO_TEXT:
1966 	case Element::TEXT:
1967 	case Element::HAIRPIN:
1968 	  //case Element::HARMONY:
1969 	case Element::OTTAVA:
1970 	case Element::PEDAL:
1971 	case Element::STAFF_TEXT:
1972 #if 0 // TODO-WS
1973 	  { 	    //	    if (instruction->subtypeName() == "Staff") qDebug("stafftekst i measure\n");
1974 	    //   if (instruction->subtypeName() == "System") qDebug("systemtekst i measure\n");
1975 	    if (instruction->subtypeName() == "RehearsalMark") rehearsal=true;
1976 	    found = findMatchInMeasure(instruction->tick(), instruction->staff(), m, strack, etrack, rehearsal);
1977 	  if (found)
1978 	    {
1979 	      anker.instruct=instruction;
1980 	      storeAnchor(anker);
1981 	    }
1982        }
1983 #endif
1984 	  break;
1985 	case Element::HARMONY:
1986 	  {
1987           Harmony* h = static_cast<Harmony*>(instruction);
1988           int tick = h->parent()->type() == Element::SEGMENT
1989              ? static_cast<Segment*>(h->parent())->tick() : 0;
1990 	    found = findMatchInMeasure(tick, instruction->staff(), m, strack, etrack, false);
1991 	    if ((found) && (staffInd == 0)) //only save chords in first staff.
1992 	      {
1993 		anker.instruct=instruction;
1994 		storeChord(anker);
1995 		resetAnchor(anker);
1996 	      }
1997 	    break;
1998 	  }
1999 	 default:
2000 	   break;
2001 	}
2002     }
2003 }// end buildinstructionlist(measure)
2004 
2005 
buildGlissandoList(int strack,int etrack)2006 void ExportLy::buildGlissandoList(int strack, int etrack)
2007 {
2008   //seems to be overkill to go thru entire score first to find
2009   //glissandos. Alternative would be to back up to the previous chord
2010   //in writeChordMeasure(). But I don't know how to do that. So I steal the
2011   //buildinstructionlist-functions to make a parallel
2012   //buildglissandolist-function. (og)
2013   for (MeasureBase* mb = score->measures()->first(); mb; mb = mb->next())
2014     {
2015       if (mb->type() != Element::MEASURE)
2016 	continue;
2017       Measure* m = (Measure*)mb;
2018       for (int st = strack; st < etrack; ++st)
2019        	{
2020 	  for (Segment* seg = m->first(); seg; seg = seg->next())
2021 	    {
2022 	      Element* el = seg->element(st);//(st);
2023 	      if (!el) continue;
2024 
2025 	      if (el->type() == Element::CHORD)
2026 		{
2027 		 Chord* cd = (Chord*)el;
2028 		  if (cd->glissando())
2029 		    {
2030 		      glisscount++;
2031 		      //this may cause trouble in multistaff-scores (??):
2032 		      Element* prevel = seg->prev()->element(st); //(st);
2033 		      Chord* prevchord = (Chord*)prevel;
2034 		      glisstable[glisscount].chord = prevchord;
2035 		      glisstable[glisscount].type = int(cd->glissando()->glissandoType());
2036 		      glisstable[glisscount].glisstext = cd->glissando()->text();
2037 		      glisstable[glisscount].tick = prevchord->tick();
2038 		    }
2039 		}
2040 	    }
2041 	 }
2042     }
2043 }
2044 
2045 
2046 
2047 //---------------------------------------------------------
2048 //   indent  -- scorebuffer
2049 //---------------------------------------------------------
2050 
indent()2051 void ExportLy::indent()
2052 {
2053   for (int i = 0; i < level; ++i)
2054     out << "    ";
2055 }
2056 
2057 
2058 //---------------------------------------------------------
2059 //   indent  -- outputfile
2060 //---------------------------------------------------------
2061 
indentF()2062 void ExportLy::indentF()
2063 {
2064       for (int i = 0; i < level; ++i)
2065 	    os << "    ";
2066 }
2067 
2068 
2069 //-------------------------------------
2070 // Find tuplets Note
2071 //-------------------------------------
2072 
findTuplets(ChordRest * cr)2073 void ExportLy::findTuplets(ChordRest* cr)
2074 {
2075       Tuplet* t = cr->tuplet();
2076 
2077       if (t) {
2078             if (tupletcount == 0) {
2079                   int actNotes   = t->ratio().numerator();
2080                   int nrmNotes   = t->ratio().denominator();
2081                   int baselength = t->duration().ticks() / nrmNotes;
2082                   int thislength = cr->duration().ticks();
2083 		  tupletcount    = nrmNotes * baselength - thislength;
2084                   out << "\\times " <<  nrmNotes << "/" << actNotes << "{" ;
2085                   }
2086             else if (tupletcount > 1) {
2087                   int thislength = cr->duration().ticks();
2088                   tupletcount    = tupletcount - thislength;
2089                   if (tupletcount == 0)
2090                         tupletcount = -1;
2091                   }
2092             }
2093       }
2094 
2095 //-----------------------------------------------------
2096 //  voltaCheckBar
2097 //
2098 // supplements findVolta and called from there: check barlinetypes in
2099 // addition to endings
2100 //------------------------------------------------------
voltaCheckBar(Measure * meas,int i)2101 int ExportLy::voltaCheckBar(Measure* meas, int i)
2102 {
2103 
2104   int barlinetype = meas->endBarLineType();
2105 
2106   switch(barlinetype)
2107     {
2108     case START_REPEAT:
2109       i++;
2110       voltarray[i].voltart=startrepeat;
2111       voltarray[i].barno=taktnr;
2112       break;
2113     case END_REPEAT:
2114       i++;
2115       voltarray[i].voltart=endrepeat;
2116       voltarray[i].barno=taktnr;
2117       break;
2118     case END_START_REPEAT:
2119       i++;
2120       voltarray[i].voltart=bothrepeat;
2121       voltarray[i].barno=taktnr;
2122       break;
2123     case END_BAR:
2124       i++;
2125       voltarray[i].voltart=endbar;
2126       voltarray[i].barno=taktnr;
2127       break;
2128     case DOUBLE_BAR:
2129       i++;
2130       voltarray[i].voltart=doublebar;
2131       voltarray[i].barno=taktnr;
2132       break;
2133     case BROKEN_BAR:
2134     case DOTTED_BAR:
2135       i++;
2136       voltarray[i].voltart=brokenbar;
2137       voltarray[i].barno=taktnr;
2138       break;
2139     default:
2140       break;
2141     }//switch
2142 
2143   // find startrepeat which does not exist as endbarline: If
2144   // startrepeat is at beginning of line, and endrepeatbar ends this
2145   // first measure of the line, repeatFlag is not set to RepeatStart,
2146   // then this does not help, and I need "findStartRepNoBarline"
2147   if (meas->repeatFlags() == RepeatStart)
2148     {
2149       // we have to exclude startrepeats found as endbarlines in previous measure
2150       if ((voltarray[i].barno != taktnr-1) and (voltarray[i].voltart != startrepeat) and ( voltarray[i].voltart != bothrepeat ))
2151 	{
2152 	  i++;
2153 	  voltarray[i].voltart=startrepeat;
2154 	  voltarray[i].barno=taktnr-1; //set as last element in previous measure.
2155 	}
2156     }
2157 
2158   return i;
2159 }//end voltacheckbarline
2160 
2161 //------------------------------------------------------------------------
2162 // findStartRepNoBarline
2163 // helper routine for findVolta.
2164 //------------------------------------------------------------------------
2165 
findStartRepNoBarline(int & i,Measure * m)2166 void ExportLy::findStartRepNoBarline(int &i, Measure* m)
2167 {
2168  // loop over all measure relative segments in this measure
2169   for (Segment* seg = m->first(); seg; seg = seg->next())
2170     {
2171       if (seg->segmentType() == SegmentType::StartRepeatBarLine)
2172 	{
2173 	  i++; // insert at next slot of voltarray
2174 	  voltarray[i].voltart = startrepeat;
2175 	  voltarray[i].barno = taktnr-1;
2176 	  break;
2177 	}
2178     }
2179 }
2180 
2181 
2182 
2183 //------------------------------------------------------------------
2184 //   findVolta -- find and register volta and repeats in entire piece,
2185 //   register them in voltarray for later use in writeVolta.
2186 //------------------------------------------------------------------
2187 
findVolta()2188 void  ExportLy::findVolta()
2189 {
2190   taktnr=0;
2191   lastind=0;
2192   int i=0;
2193 
2194   for (i=0; i<255; i++)
2195     {
2196       voltarray[i].voltart=none;
2197       voltarray[i].barno=0;
2198     }
2199 
2200   i=0;
2201 
2202   for (MeasureBase * m=score->first(); m; m=m->next())
2203     {// for all measures
2204       if (m->type() != Element::MEASURE )
2205 	continue;
2206 
2207       ++taktnr; //should really not be incremented in case of pickupbars.
2208 
2209       //needed because of problems with repeatflag and because there
2210       //are no readymade functions for finding startbarlines, and
2211       //because startbarlines are not at the global level:
2212       Measure* meas = (Measure*)m;
2213       findStartRepNoBarline(i,meas);
2214 
2215 #if 0 // TODO-WS implementation changed
2216       foreach(Element* el, *(m->score()->gel()))
2217 	//for each element at the global level relevant for this measure
2218 	{
2219 	  if (el->type() == Element::VOLTA)
2220 	    {
2221 	      Volta* v = (Volta*) el;
2222 
2223 	      if (v->tick() == m->tick()) //If we are at the beginning of the measure
2224 		{
2225 		  i++;
2226 		  //  if (v->subtype() == Volta::VOLTA_CLOSED)
2227 		  // 		    {
2228 		  //                 Lilypond has second volta closed for all kinds of thin-tick or tick-thin double bars
2229 		  //                 with or without repeat dots. But not for thin-thin double bar or single barline.
2230 		  //                 The only way I know of to make volta closed for thin-thin double bar
2231 		  //                 and single bar is to put the following lines in the source code, the file
2232 		  //                 volta-bracket.cc, at approx line 133, and recompile Lilypond
2233 		  //                	&& str != "||"
2234 		  //                        && str != "|"
2235 		  //                 But then closing becomes hardcoded and we have no choice.
2236 		  //                 There must be some \override or \set which fixes this stubbornness of the
2237 		  //                 Lilypond developers?? (olagunde@start.no)
2238 		  // 		    }
2239 		  // 		  else if (v->subtype() == Volta::VOLTA_OPEN)
2240 		  // 		    {
2241 		  // 		    }
2242 		  voltarray[i].voltart = startending;
2243 		  voltarray[i].barno=taktnr-1; //register as last element i previous measure
2244 		}
2245 #if 0 // TODO-WS
2246 	      if (v->tick2() == m->tick() + m->ticks()) // if it is at the end of measure
2247 		{
2248 		  i++;
2249 		  voltarray[i].voltart = endending;
2250 		  voltarray[i].barno=taktnr;//last element of this measure
2251 		  // 		  if (v->subtype() == Volta::VOLTA_CLOSED)
2252 		  // 		    {// see comment above.
2253 		  // 		    }
2254 		  // 		  else if (v->subtype() == Volta::VOLTA_OPEN)
2255 		  // 		    {// see comment above.
2256 		  // 		    }
2257 		}
2258 #endif
2259 	    }//if volta
2260 	}// for all global elements
2261 #endif
2262       i=voltaCheckBar((Measure *) m, i);
2263     }//for all measures
2264   lastind=i;
2265 
2266 }// end findvolta
2267 
voltatest()2268 void ExportLy::voltatest()
2269 {
2270   int i=0;
2271   for (i=0; i<lastind; i++)
2272     {
2273       qDebug("iter: %d\n", i);
2274       switch(voltarray[i].voltart)
2275 	{
2276 	case startrepeat:
2277 	  qDebug("startrepeat, bar %d\n", voltarray[i].barno);
2278 	  break;
2279 	case endrepeat:
2280 	  qDebug("endrepeat, bar %d\n", voltarray[i].barno);
2281 	  break;
2282 	case bothrepeat:
2283 	  qDebug("bothrepeat, bar %d\n", voltarray[i].barno);
2284 	  break;
2285 	case endbar:
2286 	  qDebug("endbar, bar %d\n", voltarray[i].barno);
2287 	  break;
2288 	case doublebar:
2289 	  qDebug("doublebar, bar %d\n", voltarray[i].barno);
2290 	  break;
2291 	case startending:
2292 	  qDebug("startending, bar %d\n", voltarray[i].barno);
2293 	  break;
2294 	case endending:
2295 	  qDebug("endending, bar %d\n", voltarray[i].barno);
2296 	  break;
2297 	default:
2298 	  break;
2299 	}
2300 
2301     }
2302 }
2303 
2304 
2305 //---------------------------------------------------------
2306 //   exportLilypond
2307 //---------------------------------------------------------
2308 
saveLilypond(Score * score,const QString & name)2309 bool MuseScore::saveLilypond(Score* score, const QString& name)
2310 {
2311   ExportLy em(score);
2312   return em.write(name);
2313 }
2314 
2315 
2316 //---------------------------------------------------------
2317 //   writeClef
2318 //---------------------------------------------------------
2319 
writeClef(int clef)2320 void ExportLy::writeClef(int clef)
2321 {
2322   out << "\\clef ";
2323   switch(clef) {
2324   case ClefType::G:      out << "treble\n";         break;
2325   case ClefType::F:      out << "bass\n";           break;
2326   case ClefType::G1:     out << "\"treble^8\"\n";   break;
2327   case ClefType::G2:     out << "\"treble^15\"\n";  break;
2328   case ClefType::G3:     out << "\"treble_8\"\n";   break;
2329   case ClefType::F8:     out << "\"bass_8\"\n";     break;
2330   case ClefType::F15:    out << "\"bass_15\"\n";    break;
2331   case ClefType::F_B:    out << "bass\n";           break;
2332   case ClefType::F_C:    out << "bass\n";           break;
2333   case ClefType::C1:     out <<  "soprano\n";       break;
2334   case ClefType::C2:     out <<  "mezzo-soprano\n"; break;
2335   case ClefType::C3:     out <<  "alto\n";          break;
2336   case ClefType::C4:     out <<  "tenor\n";         break;
2337   case ClefType::TAB2:
2338   case ClefType::TAB:    out <<  "tab\n";           break;
2339   case ClefType::PERC:   out <<  "percussion\n";    break;
2340   }
2341 
2342 }
2343 
2344 //---------------------------------------------------------
2345 //   writeTimeSig
2346 //---------------------------------------------------------
2347 
writeTimeSig(TimeSig * sig)2348 void ExportLy::writeTimeSig(TimeSig* sig)
2349 {
2350   int st     = sig->timeSigType();
2351   Fraction f = sig->sig();
2352   timedenom  = f.denominator();
2353   z1         = f.numerator();
2354 
2355   //lilypond writes 4/4 as C by default, so only check for cut.
2356   if (st == TSIG_ALLA_BREVE)
2357     {
2358       z1=2;
2359       timedenom=2;
2360       // 2/2 automatically written as alla breve by lily.
2361     }
2362   indent();
2363   out << "\\time " << z1 << "/" << timedenom << " ";
2364 }
2365 
2366 //---------------------------------------------------------
2367 //   writeKeySig
2368 //---------------------------------------------------------
2369 
writeKeySig(int st)2370 void ExportLy::writeKeySig(int st)
2371 {
2372   st = char(st & 0xff);
2373   out << "\\key ";
2374   switch(st) {
2375   case 7:  out << "cis"; break;
2376   case 6:  out << "fis"; break;
2377   case 5:  out << "b";   break;
2378   case 4:  out << "e";   break;
2379   case 3:  out << "a";   break;
2380   case 2:  out << "d";   break;
2381   case 1:  out << "g";   break;
2382   case 0:  out << "c";   break;
2383   case -7: out << "ces"; break;
2384   case -6: out << "ges"; break;
2385   case -5: out << "des"; break;
2386   case -4: out << "as";  break;
2387   case -3: out << "es";  break;
2388   case -2: out << "bes"; break;
2389   case -1: out << "f";   break;
2390   default:
2391     qDebug("illegal key %d\n", st);
2392     break;
2393   }
2394   out << " \\major \n";
2395 }
2396 
2397 //---------------------------------------------------------
2398 //   tpc2name
2399 //---------------------------------------------------------
2400 
tpc2name(int tpc)2401 QString ExportLy::tpc2name(int tpc)
2402 {
2403   const char names[] = "fcgdaeb";
2404   int acc   = ((tpc+1) / 7) - 2;
2405   QString s(names[(tpc + 1) % 7]);
2406   switch(acc) {
2407   case -2: s += "eses"; break;
2408   case -1: s += "es";  break;
2409   case  1: s += "is";  break;
2410   case  2: s += "isis"; break;
2411   case  0: break;
2412   default: s += "??"; break;
2413   }
2414   return s;
2415 }
2416 
2417 
2418 //---------------------------------------------------------
2419 //   tpc2purename
2420 //---------------------------------------------------------
2421 
tpc2purename(int tpc)2422 QString ExportLy::tpc2purename(int tpc)
2423 {
2424   const char names[] = "fcgdaeb";
2425   QString s(names[(tpc + 1) % 7]);
2426   return s;
2427 }
2428 
2429 
2430 //--------------------------------------------------------
2431 //  Slur functions, stolen from exportxml.cpp. I really
2432 //  don't understand these functions, but they seem to work
2433 //  (olav)
2434 //
2435 //---------------------------------------------------------
2436 //   findSlur -- get index of slur in slur table
2437 //   return -1 if not found
2438 //---------------------------------------------------------
2439 
findSlur(const Slur * s) const2440 int ExportLy::findSlur(const Slur* s) const
2441 {
2442   for (int i = 0; i < 8; ++i)
2443     if (slurre[i] == s) return i;
2444   return -1;
2445 }
2446 
2447 //---------------------------------------------------------
2448 //   doSlurStart. Find start of slur connected to chord.
2449 //---------------------------------------------------------
2450 
doSlurStart(Chord * chord,bool nextisrest)2451 void ExportLy::doSlurStart(Chord* chord, bool nextisrest)
2452 {
2453 #if 0 // TODO-S
2454   int slurcount=0;
2455   for(const Spanner* sp = chord->spannerFor(); sp; sp = sp->next())
2456     {
2457       if (sp->type() != Element::SLUR)
2458             continue;
2459       const Slur* s = static_cast<const Slur*>(sp);
2460 
2461       slurcount++;
2462 
2463       int i = findSlur(s);
2464 
2465       if (i >= 0)
2466 	{
2467 	  slurstack++;
2468 	  slurre[i] = 0;
2469 	  started[i] = false;
2470 	  if (s->slurDirection() == MScore::UP) out << "^";
2471 	  if (s->slurDirection() == MScore::DOWN) out << "_";
2472 	  if (slurcount==2)
2473 	    {
2474 	      phraseslur=slurstack;
2475 	      out <<"\\";
2476 	    }
2477 	  if (nextisrest)
2478 	    {
2479 	      out << "\\laissezVibrer " ;
2480 	    }
2481 	    else
2482 	      out << "(";
2483 
2484 	}
2485       else
2486 	{
2487 	  i = findSlur(0);
2488 	  if (i >= 0)
2489 	    {
2490 	      slurstack++;
2491 	      slurre[i] = s;
2492 	      started[i] = true;
2493 	      if (s->slurDirection() == MScore::UP) out << "^";
2494 	      if (s->slurDirection() == MScore::DOWN) out << "_";
2495 	      if (slurcount==2)
2496 		{
2497 		  phraseslur=slurstack;
2498 		  out <<"\\";
2499 		}
2500 
2501 	      if (nextisrest)
2502 	     {
2503 	       out << "\\laissezVibrer " ;
2504 	     }
2505 	     else
2506 	      out << "(";
2507 	    }
2508 	  else
2509 	    qDebug("no free slur slot");
2510 	}
2511     }
2512 #endif
2513 
2514 }
2515 
2516 
2517 //---------------------------------------------------------
2518 //   doSlurStop
2519 //   From exportxml.cpp:
2520 //-------------------------------------------
doSlurStop(Chord * chord)2521 void ExportLy::doSlurStop(Chord* chord)
2522 {
2523 #if 0 // TODO-S
2524   for(const Spanner* sp = chord->spannerBack(); sp; sp = sp->next())
2525     {
2526     if (sp->type() != Element::SLUR)
2527           continue;
2528     const Slur* s = static_cast<const Slur*>(sp);
2529 
2530       // check if on slur list
2531       int i = findSlur(s);
2532       if (i < 0)
2533 	{
2534 	  // if not, find free slot to store it
2535 	  i = findSlur(0);
2536 	  if (i >= 0)
2537 	    {
2538 	      slurre[i] = s;
2539 	      started[i] = false;
2540 	      if (slurstack == phraseslur)
2541 		{
2542 		  phraseslur=0;
2543 		  out << "\\";
2544 		}
2545 	      slurstack--;
2546 	      out << ")";  //why do we always end here??
2547 	    }
2548 	  else
2549 	    qDebug("no free slur slot");
2550 	}
2551     }
2552 #endif
2553       for (int i = 0; i < 8; ++i) {
2554             if (slurre[i]) {
2555 #if 0 // TODO-S
2556                   if  (slurre[i]->endElement() == chord) {
2557                         if (started[i]) {
2558                               slurre[i] = 0;
2559                               started[i] = false;
2560                               if (phraseslur == slurstack) {
2561                                     out << "\\";
2562      	                              phraseslur = 0;
2563      	                              }
2564                               slurstack--;
2565                               out << ")"; //why do we never end here?!
2566                               }
2567                         }
2568 #endif
2569 	            }
2570             }
2571       }
2572 
2573 //-------------------------
2574 // checkSlur
2575 //-------------------------
checkSlur(Chord * chord,bool nextisrest)2576 void ExportLy::checkSlur(Chord* chord, bool nextisrest)
2577 {
2578   //init array:
2579   for (int i = 0; i < 8; ++i)
2580     {
2581       slurre[i] = 0;
2582       started[i] = false;
2583      }
2584   doSlurStop(chord);
2585   doSlurStart(chord, nextisrest);
2586 }
2587 
2588 
2589 //-----------------------------------
2590 // helper routine for writeScore
2591 // -- called from there
2592 //-----------------------------------
2593 
writeArticulation(ChordRest * c)2594 void ExportLy::writeArticulation(ChordRest* c)
2595 {
2596   foreach(Articulation* a, c->articulations())
2597     {
2598       switch(a->articulationType())
2599 	{
2600 	case Articulation_Fermata:
2601         if (a->up())
2602 	      out << "\\fermata ";
2603         else
2604 	      out << "_\\fermata ";
2605 	  break;
2606 	case Articulation_Thumb:
2607 	  out << "\\thumb ";
2608 	  break;
2609 	case Articulation_Sforzatoaccent:
2610 	  out << "-> ";
2611 	  break;
2612 	case Articulation_Espressivo:
2613 	  out << "\\espressivo ";
2614 	  break;
2615 	case Articulation_Staccato:
2616 	  out << "-. ";
2617 	  break;
2618 	case Articulation_Staccatissimo:
2619         if (a->up())
2620 	      out << "-| ";
2621         else
2622 	      out << "_| ";
2623 	  break;
2624 	case Articulation_Tenuto:
2625 	  out << "-- ";
2626 	  break;
2627 //TODO:	case Articulation_Flageolet:
2628 //	  out << "\\flageolet ";
2629 	case Articulation_Portato:
2630         if (a->up())
2631 	      out << "-_ ";
2632         else
2633 	      out << "__ ";
2634 	  break;
2635 	case Articulation_Marcato:
2636         if (a->up())
2637 	      out << "-^ ";
2638         else
2639 	      out << "_^ ";
2640 	  break;
2641 	case Articulation_Ouvert:
2642 	  out << "\\open ";
2643 	  break;
2644 	case Articulation_Plusstop:
2645 	  out << "-+ ";
2646 	  break;
2647 	case Articulation_Upbow:
2648 	  out << "\\upbow ";
2649 	  break;
2650 	case Articulation_Downbow:
2651 	  out << "\\downbow ";
2652 	  break;
2653 	case Articulation_Reverseturn:
2654 	  out << "\\reverseturn ";
2655 	  break;
2656 	case Articulation_Turn:
2657 	  out << "\\turn ";
2658 	  break;
2659 	case Articulation_Trill:
2660 	  out << "\\trill ";
2661 	  break;
2662 	case Articulation_Prall:
2663 	  out << "\\prall ";
2664 	  break;
2665 	case Articulation_Mordent:
2666 	  out << "\\mordent ";
2667 	  break;
2668 	case Articulation_PrallPrall:
2669 	  out << "\\prallprall ";
2670 	  break;
2671 	case Articulation_PrallMordent:
2672 	  out << "\\prallmordent ";
2673 	  break;
2674 	case Articulation_UpPrall:
2675 	  out << "\\prallup ";
2676 	  break;
2677 	case Articulation_DownPrall:
2678 	  out << "\\pralldown ";
2679 	  break;
2680 	case Articulation_UpMordent:
2681 	  out << "\\upmordent ";
2682 	  break;
2683 	case Articulation_DownMordent:
2684 	  out << "\\downmordent ";
2685 	  break;
2686 	default:
2687 	  qDebug("unsupported note attribute %d\n", int(a->articulationType()));
2688 	  break;
2689 	}// end switch
2690     }// end foreach
2691 }// end writeArticulation();
2692 
2693 
2694 //------------------------------------------
2695 // write Tremolo. stolen from exportxml.cpp
2696 //------------------------------------------
2697 
writeTremolo(Chord * chord)2698 void ExportLy::writeTremolo(Chord * chord)
2699 {
2700   if (chord->tremolo())
2701     {
2702       Tremolo * tr = chord->tremolo();
2703       int st = tr->tremoloType();
2704       switch (st)
2705 	{
2706 	case TREMOLO_R8:
2707 	  out << ":8 ";
2708 	  break;
2709 	case TREMOLO_R16:
2710 	  out << ":16 ";
2711 	  break;
2712 	case TREMOLO_R32:
2713 	  out << ":32 ";
2714 	  break;
2715 	case TREMOLO_R64:
2716 	  out << ":64 ";
2717 	  break;
2718 	default:
2719 	  qDebug("unknown tremolo %d\n", st);
2720 	  break;
2721 	}
2722     }
2723 }
2724 
2725 
2726 //-------------------------------------------------------------------------------------------
2727 //  findFingerAndStringno
2728 //------------------------------------------------------------------------------------------
2729 
findFingerAndStringno(Note * note,int & fingix,int & stringix,QString (& fingarray)[5],QString (& stringarray)[10])2730 void ExportLy::findFingerAndStringno(Note* note, int &fingix, int &stringix, QString (&fingarray)[5], QString (&stringarray)[10])
2731       {
2732       foreach (const Element* e, note->el()) {
2733             if (e->type() == Element::FINGERING) {
2734                   const Text* text = static_cast<const Text*>(e);
2735                   if (text->textStyleType() == TEXT_STYLE_FINGERING) {
2736 	                  fingix++;
2737       	            Text* f = (Text*)e;
2738 	                  fingarray[fingix] = f->text();
2739 	                  }
2740                   else if (text->textStyleType() == TEXT_STYLE_STRING_NUMBER) {
2741                         stringix++;
2742                         Text * s = (Text*)e;
2743                         stringarray[stringix] = s->text();
2744                         }
2745                   }
2746             }
2747       }//end findfingerandstringno
2748 
2749 
writeStringInstruction(int & strgix,QString stringarr[10])2750 void ExportLy::writeStringInstruction(int &strgix, QString stringarr[10])
2751 {
2752   if (strgix > 0)
2753     {  //there should be only one stringinstruction, so this is possibly redundant.
2754       for (int i=0; i < strgix; i++)
2755 	out << "\\" << stringarr[strgix];
2756     }
2757   strgix = 0;
2758 }
2759 
2760 
2761 //---------------------------------------------------------
2762 //  writeFingering
2763 //---------------------------------------------------------
writeFingering(int & fingr,QString fingering[5])2764 void ExportLy::writeFingering (int &fingr,   QString fingering[5])
2765 {
2766   if (fingr > 0)
2767 	{
2768 	  if (fingr == 1) out << "-" << fingering[1] << " ";
2769 	  else if (fingr >1)
2770 	    {
2771 	      out << "^\\markup {\\finger \"";
2772 	      out << fingering[1] << " - " << fingering[2] << "\"} ";
2773 	    }
2774 	}
2775   fingr=0;
2776 }
2777 
2778 //----------------------------------------------------------------
2779 // stemDirection
2780 //----------------------------------------------------------------
2781 
stemDir(Chord * chord)2782 void ExportLy::stemDir(Chord * chord)
2783 {
2784   // For now, we only export stem directions for gracenotes.
2785   if (chord->beam() == 0 || chord->beam()->elements().front() == chord)
2786     {
2787       MScore::Direction d = chord->stemDirection();
2788       if (d != stemDirection)
2789 	{
2790 	  stemDirection = d;
2791 	  if ((d == MScore::UP) and (graceswitch == true))
2792 	    out << "\\stemUp ";
2793 	  else if ((d == MScore::DOWN)  and (graceswitch == true))
2794 	    out << "\\stemDown ";
2795 	  //   else if (d == MScore::AUTO)
2796 	  // 	    {
2797 	  // 	      if (graceswitch == true)
2798 	  // 		{
2799 	  // 		  out << "\\stemNeutral "; // we set this at the end of graces anyway.
2800 	  // 		}
2801 	  // 	    }
2802 	}
2803     }
2804 }//end stemDirection
2805 
2806 //-------------------------------------------------------------
2807 // findGraceNotes
2808 //--------------------------------------------------------------
findGraceNotes(Note * note,bool & chordstart,int streng)2809 void ExportLy::findGraceNotes(Note *note, bool &chordstart, int streng)
2810 {
2811   NoteType gracen;
2812   gracen = note->noteType();
2813   switch(gracen)
2814     {
2815     case NOTE_INVALID:
2816     case NOTE_NORMAL:
2817       if (graceswitch==true)
2818 	{
2819 	  graceswitch=false;
2820 	  gracebeam=false;
2821 	  if (gracecount > 1) out << " ] "; //single graces are not beamed
2822 	  out << " } \\stemNeutral "; //end of grace
2823 	  gracecount=0;
2824 	}
2825       if ((chordstart) or (streng > 0))
2826 	{
2827 	  out << "<";
2828 	  chordstart=false;
2829 	}
2830       break;
2831     case NOTE_ACCIACCATURA:
2832     case NOTE_APPOGGIATURA:
2833     case NOTE_GRACE4:
2834     case NOTE_GRACE16:
2835     case NOTE_GRACE32:
2836       if (graceswitch==false)
2837 	{
2838 	  out << "\\grace{\\stemUp "; //as long as general stemdirecton is unsolved: graces always stemUp.
2839 	  graceswitch=true;
2840 	  gracebeam=false;
2841 	  gracecount=0;
2842 	}
2843       gracecount++;
2844       break;
2845     } //end of switch(gracen)
2846 }//end findGraceNotes
2847 
2848 //---------------------------------------------------------------------------
2849 //   setOctave
2850 //---------------------------------------------------------------------------
setOctave(int & purepitch,int & pitchidx,int (& pitchlist)[12])2851 void ExportLy::setOctave(int &purepitch, int &pitchidx, int (&pitchlist)[12])
2852 {
2853   int oktavdiff=prevpitch - purepitch;
2854   int oktreit=numval(oktavdiff);
2855   while (oktreit > 0)
2856     {
2857       if ((oktavdiff < -6) or ((prevnote=="b") and (oktavdiff < -5)))
2858 	{ //up
2859 	  out << "'";
2860 	  oktavdiff=oktavdiff+12;
2861 	}
2862       else if ((oktavdiff > 6)  or ((prevnote=="f") and (oktavdiff > 5)))
2863 	{//down
2864 	  out << ",";
2865 	  oktavdiff=oktavdiff-12;
2866 	}
2867       oktreit=oktreit-12;
2868     }
2869   prevpitch=purepitch;
2870   pitchlist[pitchidx]=purepitch;
2871   pitchidx++;
2872 }//end setOctave
2873 
2874 
arpeggioTest(Chord * chord)2875 bool ExportLy::arpeggioTest(Chord* chord)
2876 {
2877   bool arp=false;
2878   if (chord->arpeggio())
2879     {
2880       arp=true;
2881       int subtype = int(chord->arpeggio()->arpeggioType());
2882       switch (subtype)
2883 	{
2884 	case 0:
2885 	  out << "\\arpeggioNormal ";
2886 	  break;
2887 	case 1:
2888 	  out << "\\arpeggioArrowUp ";
2889 	  break;
2890 	case 2:
2891 	  out << "\\arpeggioArrowDown ";
2892 	  break;
2893 	default:
2894 	  qDebug("unknown arpeggio subtype %d\n", subtype);
2895 	  break;
2896 	}
2897     }
2898   return arp;
2899 }
2900 
2901 
glissandotest(Chord * chord)2902 bool ExportLy::glissandotest(Chord* chord)
2903 {
2904   bool gliss=false;
2905   int i=0;
2906   for (i=0; i < glisscount; i++)
2907     {
2908       if (glisstable[i].chord == chord)
2909 	{
2910 	  if (glisstable[i].type == 1)
2911 	    {
2912 	      out << "\\once\\override Glissando #'style = #'trill \n";
2913 	      indent();
2914 	    }
2915 	  gliss=true;
2916 	}
2917     }
2918   return gliss;
2919 }
2920 
2921 
2922 //------------------------------------------------------------
2923 // findNoteSymbol
2924 // Find symbols attached to note.
2925 //------------------------------------------------------------
2926 
findNoteSymbol(Note * n,QString & symbolname)2927 bool ExportLy::findNoteSymbol(Note* n, QString& symbolname)
2928       {
2929       symbolname = "";
2930 
2931       foreach(const Element* symbol, n->el()) {
2932             if (symbol->type() == Element::SYMBOL) {
2933                   const Symbol* symb = static_cast<const Symbol*>(symbol);
2934                   symbolname = Sym::id2name(symb->sym());
2935                   return true; // what about more symbols connected to one note? Return array of names?
2936                   }
2937             }
2938       return false;
2939       }//end findNoteSymbol
2940 
2941 //---------------------------------------------------------
2942 //   writeChord
2943 //---------------------------------------------------------
2944 
writeChord(Chord * c,bool nextisrest)2945 void ExportLy::writeChord(Chord* c, bool nextisrest)
2946 {
2947   int  purepitch;
2948   QString purename, chordnote;
2949   int pitchlist[12];
2950   QString fingering[5];
2951   QString stringno[10];
2952   bool tie=false;
2953   bool symb=false;
2954   QList<Note*> nl = c->notes();
2955   bool chordstart=false;
2956   int fing=0;
2957   int streng=0;
2958   bool gliss=false;
2959   QString glisstext;
2960   QString symbolname;
2961 
2962   int j=0;
2963   for (j=0; j<12; j++) pitchlist[j]=0;
2964 
2965   stemDir(c);
2966 
2967   if (nl.size() > 1) chordstart = true;
2968 
2969   int  pitchidx=0;
2970   bool arpeggioswitch=false;
2971   arpeggioswitch=arpeggioTest(c);
2972 
2973   gliss = glissandotest(c);
2974   int iter=0;
2975   for (QList<Note*>::iterator notesinchord = nl.begin();;)
2976     {
2977 	  iter++;
2978       Note* n = *notesinchord;
2979       //if fingering found on _previous_ chordnote, now is the time for writing it:
2980       if (fing>0)  writeFingering(fing,fingering);
2981       if (streng>0) writeStringInstruction(streng,stringno);
2982 
2983       //find diverse elements and attributes connected to the note
2984       findFingerAndStringno(n, fing, streng, fingering, stringno);
2985 
2986       if (iter == 1) findTuplets(n->chord());
2987 
2988       findGraceNotes(n, chordstart, streng);//also writes start of chord symbol "<" if necessary
2989 
2990       symb = findNoteSymbol(n, symbolname);
2991 
2992       if (n->tieFor()) tie=true;
2993 
2994       if (gracecount==2) out << " [ ";
2995 
2996 
2997       out << tpc2name(n->tpc()).toUtf8().data();  //Output of The Notename Itself
2998 
2999       if ((chordstart) and (symb))
3000 	{
3001 	  cout << "symbol in chord\n";
3002 	  writeSymbol(symbolname);
3003 	}
3004 
3005       purepitch = n->pitch();
3006       purename = tpc2name(n->tpc());  //with -es or -is
3007       prevnote=cleannote;             //without -es or -is
3008       cleannote=tpc2purename(n->tpc());//without -es or -is
3009 
3010       if (purename.contains("eses")==1)  purepitch=purepitch+2;
3011       else if (purename.contains("es")==1)  purepitch=purepitch+1;
3012       else if (purename.contains("isis")==1) purepitch=purepitch-2;
3013       else if (purename.contains("is")==1) purepitch=purepitch-1;
3014 
3015       setOctave(purepitch, pitchidx, pitchlist);
3016 
3017       if (notesinchord == nl.begin())
3018 	{
3019 	  chordpitch=prevpitch;
3020 	  chordnote=cleannote;
3021 	}
3022 
3023       ++notesinchord; //number of notes in chord, we progress to next chordnote
3024       if (notesinchord == nl.end())
3025 	break;
3026       out << " ";
3027     } //end of notelist = end of chord
3028 
3029   if ((nl.size() > 1) or (streng > 0))
3030     {
3031       //if fingering found on previous chordnote, now is the time for writing it:
3032       if (fing   > 0) writeFingering(fing, fingering);
3033       if (streng > 0) writeStringInstruction(streng,stringno);
3034       out << ">"; //endofchord sign
3035       cleannote=chordnote;
3036       //if this is a chord, use first note of chord as previous note
3037       //instead of actual previous note.
3038     }
3039 
3040   int ix=0;
3041   prevpitch=pitchlist[0];
3042    while (pitchlist[ix] !=0)
3043      {
3044        if (pitchlist[ix]<prevpitch) prevpitch=pitchlist[ix];
3045        ix++;
3046      }
3047 
3048   writeLen(c->actualTicks());
3049 
3050   if ((symb) and (nl.size() == 1))
3051     writeSymbol(symbolname);
3052 
3053   if (arpeggioswitch)
3054     {
3055       out << "\\arpeggio ";
3056       arpeggioswitch=false;
3057     }
3058 
3059 
3060   //if fingering found on a single note, now is the time for writing it:
3061   if (nl.size() == 1)
3062     writeFingering(fing, fingering);
3063 
3064   writeTremolo(c);
3065 
3066   if (gliss)
3067     {
3068       out << "\\glissando ";
3069       if (glisstable[glisscount].glisstext !="")
3070 	out << "^\\markup{" << glisstable[glisscount].glisstext << "} ";
3071       //todo: make glisstext follow glissline
3072     }
3073 
3074   if (tie)
3075     {
3076       out << "~";
3077       tie=false;
3078     }
3079 
3080   writeArticulation(c);
3081   checkSlur(c, nextisrest);
3082 
3083   out << " ";
3084 
3085 }// end of writechord
3086 
3087 
3088 //---------------------------------------------------------
3089 //   getLen
3090 //---------------------------------------------------------
3091 
getLen(int l,int * dots)3092 int ExportLy::getLen(int l, int* dots)
3093 {
3094   int len  = 4;
3095 
3096   if (l == 16 * MScore::division) //longa, whole measure of 4/2-time
3097     len=-2;
3098   else if (l == 12 * MScore::division) // "6/2" "dotted brevis" used for whole-measure rest in 6/2 time.
3099     len=-3;
3100   else if (l == 10 * MScore::division) // "5/2"- time, used for whole-measure rest.
3101     len=-4;
3102   else if (l == 8 * MScore::division) //brevis
3103     len = -1;
3104   else if (l == 7 * MScore::division) //doubledotted whole
3105     {
3106       len = 1;
3107       *dots = 2;
3108     }
3109   else if (l == 6 * MScore::division) //dotted whole
3110     {
3111       len  = 1;
3112       *dots = 1;
3113     }
3114   else if (l == 5 * MScore::division) // whole measure of 5/4-time
3115       len = -5;
3116   else if (l == 4 * MScore::division) //whole
3117     len = 1;
3118   else if (l == 3 * MScore::division) // dotted half
3119     {
3120       len = 2;
3121       *dots = 1;
3122     }
3123   else if (l == ((MScore::division/2)*7)) // double-dotted half: 7/8 used for \partial bar.
3124     {
3125       len = 2;
3126       *dots=2;
3127     }
3128   else if (l == 2 * MScore::division)
3129     len = 2;
3130   else if (l == MScore::division)         //quarter
3131     len = 4;
3132   else if (l == MScore::division *3 /2)   //dotted quarter
3133     {
3134       len=4;
3135       *dots=1;
3136     }
3137   else if (l == ((MScore::division/4)*7)) // double-dotted quarter
3138     {
3139       len = 4;
3140       *dots=2;
3141     }
3142   else if (l == MScore::division / 2)     //8th
3143     len = 8;
3144   else if (l == MScore::division*3 /4) //dotted 8th
3145     {
3146       len = 8;
3147       *dots=1;
3148     }
3149   else if (l == ((MScore::division/8)*7)) // double-dotted 8th
3150     {
3151       len = 8;
3152       *dots=2;
3153     }
3154   else if (l == MScore::division / 4)
3155     len = 16;
3156   else if (l == MScore::division / 8)
3157     len = 32;
3158   else if (l == MScore::division * 3 /8) //dotted 16th.
3159     {
3160       len = 16;
3161       *dots = 1;
3162     }
3163   else if (l == ((MScore::division/16)*7)) // double-dotted 16th.
3164     {
3165       len = 16;
3166       *dots=2;
3167     }
3168   else if (l == MScore::division / 16)
3169     len = 64;
3170   else if (l == MScore::division /32)
3171     len = 128;
3172   //triplets, lily uses nominal value surrounded by \times 2/3 {  }
3173   //so we set len equal to nominal value
3174   else if (l == ((MScore::division  * 8)/3))
3175      len = 1;
3176   else if (l == MScore::division * 4 /3)
3177      len = 2;
3178   else if (l == (MScore::division * 2)/3)
3179     len = 4;
3180   else if (l == MScore::division /3)
3181     len = 8;
3182   else if (l == MScore::division /(3*2))
3183     len = 16;
3184   else if (l == MScore::division /3*4)
3185     len = 32;
3186   else if (l == MScore::division/3*8)
3187     len = 64;
3188   else if (l == 0)
3189     len = 1;
3190   else qDebug("measure: %d, unsupported len %d (%d,%d)\n", measurenumber, l, l/MScore::division, l % MScore::division);
3191   return len;
3192 }
3193 
3194 //---------------------------------------------------------
3195 //   writeLen
3196 //---------------------------------------------------------
3197 
writeLen(int ticks)3198 void ExportLy::writeLen(int ticks)
3199 {
3200   int dots = 0;
3201   int len = getLen(ticks, &dots);
3202 
3203   if (ticks != curTicks)
3204     {
3205       switch (len)
3206 	{
3207 	case -5:
3208 	  out << "1*5/4";
3209 	  break;
3210 	case -4:
3211 	  out << "2*5 ";
3212 	  break;
3213 	case -3:
3214 	  out << "1.*2 ";
3215 	  break;
3216 	case -2://longa
3217 	  out << "\\longa ";
3218 	    break;
3219 	case -1: //brevis
3220 	  out << "\\breve";
3221 	  break;
3222 	default:
3223 	  out << len;
3224 	  for (int i = 0; i < dots; ++i)
3225 	    out << ".";
3226 	  break;
3227 	}
3228       curTicks = ticks;
3229       if (dots>0)
3230 	curTicks = -1; //first note after dotted: always explicit length
3231     }
3232 }
3233 
3234 //---------------------------------------------------------
3235 //   writeRest
3236 //    type = 0    normal rest
3237 //    type = 1    whole measure rest
3238 //    type = 2    spacer rest
3239 //---------------------------------------------------------
3240 
writeRest(int l,int type)3241 void ExportLy::writeRest(int l, int type)
3242 {
3243   if (type == 1) //whole measure rest
3244     {
3245       out << "R";
3246       curTicks = -1; //whole measure rest always requires explicit length
3247       writeLen(l);
3248       wholemeasurerest=1;
3249      }
3250   else if (type == 2) //invisible rest
3251     {
3252       curTicks = -1;
3253       out << "s";
3254       writeLen(l);
3255     }
3256   else //normal rest
3257     {
3258       out << "r";
3259      writeLen(l);
3260     }
3261   out << " ";
3262 }
3263 
3264 //--------------------------------------------------------------
3265 //   write number of whole measure rests
3266 //-------------------------------------------------------------
writeMeasuRestNum()3267 void ExportLy::writeMeasuRestNum()
3268 {
3269   if (wholemeasurerest >1) out << "*" << wholemeasurerest << " ";
3270   if (wholemeasuretext != "")
3271     {
3272       out << "^\\markup{" << wholemeasuretext << "} \n";
3273       indent();
3274     }
3275   out << " | % \n";
3276   indent();
3277   wholemeasurerest=0;
3278   wholemeasuretext= "";
3279   curTicks = -9;
3280 }
3281 
3282 //--------------------------------------------------------
3283 //   writeVolta
3284 //--------------------------------------------------------
writeVolta(int measurenumber,int lastind)3285 void ExportLy::writeVolta(int measurenumber, int lastind)
3286 {
3287   bool utgang=false;
3288   int i=0;
3289 
3290   if (pickup)
3291     measurenumber--;
3292   while ((voltarray[i].barno < measurenumber) and (i<=lastind))
3293     {
3294       //find the present measure
3295       i++;
3296     }
3297 
3298   if (measurenumber==voltarray[i].barno)
3299     {
3300       while (utgang==false)
3301 	{
3302 	  switch(voltarray[i].voltart)
3303 	    {
3304 	    case startrepeat:
3305 	      if (wholemeasurerest > 0) writeMeasuRestNum();
3306 	      indent();
3307 	      out << "\\repeat volta 2 { %startrep \n";
3308 	      firstalt=false;
3309 	      secondalt=false;
3310 	      repeatactive=true;
3311 	      curTicks=-1;
3312 	      break;
3313 	    case endrepeat:
3314 	      if ((repeatactive==true) and (secondalt==false))
3315 		{
3316 		  if (wholemeasurerest > 0) writeMeasuRestNum();
3317 		  out << "} % end of repeatactive\n";
3318 		  curTicks=-1;
3319 		  // repeatactive=false;
3320 		}
3321 	      indent();
3322 	      break;
3323 	    case bothrepeat:
3324 	      if (firstalt==false)
3325 		{
3326 		  if (wholemeasurerest > 0) writeMeasuRestNum();
3327 		  out << "} % end of repeat (both)\n";
3328 		  indent();
3329 		  out << "\\repeat volta 2 { % bothrep \n";
3330 		  firstalt=false;
3331 		  secondalt=false;
3332 		  repeatactive=true;
3333 		  curTicks=-1;
3334 		}
3335 	      break;
3336 	    case doublebar:
3337 	      if (wholemeasurerest > 0) writeMeasuRestNum();
3338 	      out << "\n";
3339 	      indent();
3340 	      out << "\\bar \"||\"";
3341 	      curTicks=-1;
3342 	      break;
3343 	    case startending:
3344 	      if (firstalt==false)
3345 		{
3346 		  if (wholemeasurerest > 0) writeMeasuRestNum();
3347 		  out << "} % end of repeat except alternate endings\n";
3348 		  indent();
3349 		  out << "\\alternative{ {  ";
3350 		  firstalt=true;
3351 		  curTicks=-1;
3352 		}
3353 	      else
3354 		{
3355 		  if (wholemeasurerest > 0) writeMeasuRestNum();//should not happen?
3356 		  out << "{ ";
3357 		  indent();
3358 		  firstalt=false;
3359 		  secondalt=true;
3360 		  curTicks=-1;
3361 		}
3362 	      break;
3363 	    case endending:
3364 	      if (firstalt)
3365 		{
3366 		  if (wholemeasurerest > 0) writeMeasuRestNum();
3367 		  out << "} %close alt1\n";
3368 		  secondalt=true;
3369 		  repeatactive=true;
3370 		  curTicks=-1;
3371 		}
3372 	      else
3373 		{
3374 		  if (wholemeasurerest > 0) writeMeasuRestNum();
3375 		  out << "} } %close alternatives\n";
3376 		  secondalt=false;
3377 		  firstalt=true;
3378 		  repeatactive=false;
3379 		  curTicks=-1;
3380 		}
3381 	      break;
3382 	    case endbar:
3383 	      if (wholemeasurerest > 0) writeMeasuRestNum();
3384 	      out << "\\bar \"|.\"";
3385 	      curTicks=-1;
3386 	      break;
3387           default:
3388 	    // case none: qDebug("strange voltarraycontents?\n");
3389 	    break;
3390 	    }//end switch
3391 
3392 	  if (voltarray[i+1].barno==measurenumber)
3393 	    {
3394 	      i++;
3395 	    }
3396 	  else utgang=true;
3397 	}// end of while utgang false;
3398     }// if barno=measurenumber
3399 }// end writevolta
3400 
3401 
3402 
3403 //-----------------------------------------------------------------------
3404 //    checkifnextisrest
3405 //-----------------------------------------------------------------------
checkIfNextIsRest(MeasureBase * mb,Segment * s,bool & nextisrest,int track)3406 static void checkIfNextIsRest(MeasureBase* mb, Segment* s, bool &nextisrest, int track)
3407 {
3408   nextisrest = false;
3409   Segment* nextseg = s->next();
3410   Element*  nextelem;
3411   nextelem= nextseg->element(track);
3412 
3413   while (!(nextseg->segmentType() == SegmentType::EndBarLine))//  and !(nextseg->segmentType() == SegmentType::EndBarLine)))
3414     {
3415       //go to next segment, check if it is chord or end of measure.
3416       if (nextseg->isChordRest())	break;
3417       nextseg = nextseg->next();
3418       nextelem = nextseg->element(track); //check if it is on this track
3419     }
3420 
3421   //if it is not on this track, continue until end we find segment
3422   //containing element of this track, or end of measure
3423   while ((nextelem==0) and (!(nextseg->segmentType() == SegmentType::EndBarLine)))
3424     {
3425       nextseg = nextseg->next();
3426       nextelem = nextseg->element(track);
3427     }
3428 
3429   // if next segment contains element of this track, check for end of
3430   // measure and chordorrest.
3431   if ((nextseg->segmentType() != SegmentType::EndBarLine) &&  (nextseg->isChordRest()))
3432     {
3433       // probably superfluous as we have previously checked for
3434       // element on this track (!=0)
3435       if ((!(nextelem == 0 || nextelem->generated())))
3436 	{
3437 	  if (nextelem->type() == Element::REST)
3438 	    {
3439 	      nextisrest=true;
3440 	    }
3441 	}
3442     }
3443   else // if we have reached end of measure
3444     {
3445       // go to next measure:
3446       if (mb->next()) //if it is not the last one of the piece.
3447 	{
3448 	  mb = mb->next();
3449 	  if (mb->type() == Element::MEASURE)
3450 	    {
3451 	      Measure* meas = (Measure*) mb;
3452 	      for(Segment* s = meas->first(); s; s = s->next())
3453 		{
3454 		  if (s->isChordRest())
3455 		    {
3456 		      Element* elem = s->element(track);
3457 		      if (!(elem == 0 ||  elem->generated()))
3458 			{
3459 			  if (elem->type() == Element::REST)
3460 			    {
3461 			      nextisrest=true;
3462 			    }
3463 			  else if (elem->type() == Element::CHORD)
3464 			    {
3465 			      //relax
3466 			    }
3467 			}
3468 		      break; //do not check more segments.
3469 		    }
3470 		}
3471 	    }
3472 	}
3473       else nextisrest=false;
3474     }
3475 }
3476 
3477 
3478 
3479 
newLyricsRecord()3480 void ExportLy::newLyricsRecord()
3481 {
3482   lyricsRecord* lyrrec;
3483   lyrrec = new lyricsRecord();
3484 
3485   for (int i = 0; i < VERSES; i++)
3486     {
3487       lyrrec->lyrdat.tick[i]=0;
3488       lyrrec->lyrdat.verselyrics[i] = "";
3489       lyrrec->lyrdat.segmentnumber[i] = 0;
3490     }
3491   lyrrec->lyrdat.staffname = staffname[staffInd].staffid;
3492   lyrrec->numberofverses=-1;
3493   lyrrec->next = NULL;
3494   lyrrec->prev = NULL;
3495 
3496   if (tailOfLyrics != NULL)
3497     {
3498       lyrrec->prev = tailOfLyrics;
3499       tailOfLyrics->next = lyrrec;
3500 
3501     }
3502 
3503   tailOfLyrics = lyrrec;
3504   thisLyrics = lyrrec;
3505 
3506   if (headOfLyrics == NULL)  headOfLyrics = lyrrec;
3507 }
3508 
3509 //--------------------------------------------------------------------
3510 // findLyrics
3511 //--------------------------------------------------------------------
findLyrics()3512 void ExportLy::findLyrics()
3513 {
3514   int verse = 0;
3515   int track = 0;
3516   int vox = 0;
3517   int prevverse =  0;
3518 
3519   for (int staffno=0; staffno < staffInd; staffno++)
3520     {
3521       newLyricsRecord();//one record for each staff. Contains multiple voices and verses.
3522 
3523       for (MeasureBase* mb = score->first(); mb; mb = mb->next())
3524 	{
3525 	  if (mb->type() != Element::MEASURE)
3526 	    continue;
3527 	  Measure* meas = (Measure*)mb;
3528 
3529         SegmentType st = SegmentType::ChordRest | SegmentType::Grace;
3530 	  for(Segment* seg = meas->first(st); seg; seg = seg->next(st))
3531 	    {
3532         const QList<Lyrics*>* lyrlist = seg->lyricsList(staffno*VOICES);
3533             if (!lyrlist)
3534                   continue;
3535 
3536 	      foreach(const Lyrics* lix, *lyrlist)
3537 		{
3538 		  if (lix)
3539 		    {
3540 		      verse = (lix)->no();
3541 		      if ((verse - prevverse) > 1)
3542 			{
3543 			  thisLyrics->lyrdat.verselyrics[verse-1] += "__ _ ";
3544 			}
3545 		      track = (lix)->track();
3546 		      vox = track - (staffno*VOICES);
3547 
3548 		      thisLyrics->lyrdat.segmentnumber[verse]++;
3549 		      thisLyrics->lyrdat.tick[verse] = (lix)->segment()->tick();
3550 
3551 		      if (verse > thisLyrics->numberofverses)
3552 			{
3553 			  thisLyrics->numberofverses = verse;
3554 			  if (verse > 0)
3555 			    {
3556 			      int segdiff = (thisLyrics->lyrdat.segmentnumber[verse-1] -  thisLyrics->lyrdat.segmentnumber[verse]);
3557 			      if (segdiff > 0)
3558 				{
3559 				  for (int i = 0; i < segdiff; i++)
3560 				    thisLyrics->lyrdat.verselyrics[verse] += " _ ";
3561 				  thisLyrics->lyrdat.segmentnumber[verse] += segdiff;
3562 				}
3563 			    }
3564 			}
3565 
3566 		      QString lyriks = (lix)->text();
3567 
3568           //  escape '"' character
3569           if (lyriks.contains('"'))
3570                  lyriks = "\"" + lyriks.replace("\"","\\\"") + "\"";
3571 
3572 		      lyriks = lyriks.replace(" ", "_"); //bolton: if two words on one note.
3573 		      thisLyrics->lyrdat.verselyrics[verse] += lyriks;
3574 
3575 		      thisLyrics->lyrdat.staffname =  staffname[staffno].staffid;
3576 		      thisLyrics->lyrdat.voicename[verse] = staffname[staffno].voicename[vox];
3577 
3578 		      thisLyrics->lyrdat.tick[verse] = (lix)->segment()->tick();
3579 
3580 		      int syl   = (lix)->syllabic();
3581 		      switch(syl)
3582 			{
3583 			case Lyrics::SINGLE:
3584 			  thisLyrics ->lyrdat.verselyrics[verse] += " ";
3585 			  break;
3586 			case Lyrics::BEGIN:
3587 			  thisLyrics->lyrdat.verselyrics[verse] +=  " -- ";
3588 			  break;
3589 			case Lyrics::END:
3590 			  thisLyrics->lyrdat.verselyrics[verse] += "  ";
3591 			  break;
3592 			case Lyrics::MIDDLE:
3593 			  thisLyrics->lyrdat.verselyrics[verse] += " -- ";
3594 			  break;
3595 			default:
3596 			  qDebug("unknown syllabic %d\n", syl);
3597 			}//switch syllable
3598 		      cout << " lyrics endtick: " << (lix)->endTick() << "\n";
3599 		      if ((lix)->ticks() > 0) //more than one note on this syllable
3600 			{
3601 			  cout << " _ ";
3602 			  thisLyrics->lyrdat.verselyrics[verse] += " _ ";
3603 			}
3604 		    } //if lyrics
3605 		  prevverse = verse;
3606 		} // for each member of lyricslist
3607 		if (verse < thisLyrics->numberofverses)
3608 		  thisLyrics->lyrdat.verselyrics[thisLyrics->numberofverses] += "__ _ ";
3609 	    } // for each segment
3610 	} //for each staff
3611     } //for measurebase first to last
3612 }// end of findlyrics
3613 
3614 //-------------------------------------------------------------
3615 // writeLyrics
3616 //-------------------------------------------------------------
writeLyrics()3617 void ExportLy::writeLyrics()
3618 {
3619 
3620   thisLyrics = headOfLyrics;
3621   tailOfLyrics->next = NULL;//???
3622   int staffi=0;
3623   int stanza=0;
3624 
3625   while (thisLyrics != NULL)
3626     {
3627       staffi=0;
3628       while (staffname[staffi].staffid != "laststaff")
3629 	{
3630 	  for (int j=0; j< staffname[staffi].numberofvoices; j++)
3631 	    {
3632 		  stanza=0;
3633 	      for (int ix = 0; ix < thisLyrics->numberofverses+1; ix++)//thisLyrics->numberofverses; ix++)
3634 		{
3635 		  if ((thisLyrics->lyrdat.staffname == staffname[staffi].staffid)
3636 		      and (thisLyrics->lyrdat.voicename[ix] == staffname[staffi].voicename[j]))
3637 		    {
3638 		      indentF();
3639 		      stanza++;
3640 		      char verseno = (ix + 65);
3641 		      os << "  " << thisLyrics->lyrdat.staffname;
3642 		      os << "verse" << verseno << " = \\lyricmode { \\set stanza = \" " << stanza << ". \" ";
3643 		      os << thisLyrics->lyrdat.verselyrics[ix] << "}\n";
3644 		    }
3645 		}
3646 	    }
3647 	  staffi++;
3648 	}
3649        //if (thisLyrics->next != NULL)
3650       thisLyrics = thisLyrics->next;
3651     }
3652   thisLyrics = headOfLyrics;
3653 }
3654 
3655 
3656 
3657 //--------------------------------------------------------------
3658 // connectLyricsToStaff
3659 //--------------------------------------------------------------
3660 
connectLyricsToStaff()3661 void ExportLy::connectLyricsToStaff()
3662 {
3663   /*      if (lyrics attached to one of the voices in this staff)*/
3664   thisLyrics =headOfLyrics;
3665   while (thisLyrics != NULL)
3666     {
3667       for (int j=0; j< staffname[indx].numberofvoices; j++)
3668 	{
3669 	  for (int ix = 0; ix <= thisLyrics->numberofverses; ix++)//;
3670 	    {
3671 	      if (thisLyrics->lyrdat.staffname == staffname[indx].staffid)
3672 		{
3673 		  if (thisLyrics->lyrdat.voicename[ix] == staffname[indx].voicename[j])
3674 		    {
3675 		      indentF();
3676 		      char verseno = ix + 65;
3677 		      os << " \\context Lyrics = " << staffname[indx].staffid;
3678 		      os << "verse"<< verseno;
3679 		      os <<  "\\lyricsto ";
3680 		      os << thisLyrics->lyrdat.voicename[ix] << "  \\";
3681 		      os << thisLyrics->lyrdat.staffname << "verse" << verseno << "\n";;
3682 		    }
3683 		}
3684 	    }
3685 	}
3686 
3687       //if (thisLyrics->next != NULL)
3688       thisLyrics = thisLyrics->next;
3689     }
3690   os << "\n";
3691 }//end connectlyricstostaff
3692 
3693 //--------------------------------------------------------------------
3694 // cleanupLyrics
3695 //--------------------------------------------------------------------
cleanupLyrics()3696 void ExportLy::cleanupLyrics()
3697 {
3698   thisLyrics=headOfLyrics;
3699   while (thisLyrics !=NULL)
3700     {
3701       headOfLyrics=headOfLyrics->next;
3702       delete thisLyrics;
3703       thisLyrics=headOfLyrics;
3704     }
3705 }
3706 
3707 
3708 
3709 //-----------------------------------------------------------------------
3710 // flatInInstrName
3711 //-----------------------------------------------------------------------
flatInInstrName(QString name)3712 QString ExportLy::flatInInstrName(QString name)
3713 {
3714   //(unecessarily?) big deal for handling the flat-sign in instrumentnames.
3715   int pt = 0;
3716   QChar kar;
3717   int unum;
3718   bool flat=false;
3719   QString newname="";
3720   for (pt = 0; pt < name.size(); pt++)
3721     {
3722       kar=name.at(pt);
3723       unum = kar.unicode();
3724       if (unum < 256)
3725 	{
3726 	  newname.append(kar);
3727 	}
3728       else if (unum == 57613)
3729 	// 57613 is the decimal value of ==hex e10d, the
3730 	// unicode code point for "flat" in mscore's and
3731 	// lilypond's fonts. How do I convert the QChar
3732 	// directly to hex?
3733 	{
3734 	  newname.append("\\smaller \\flat ");
3735 	  flat=true;
3736 	}
3737     }
3738   if (flat)
3739     {
3740       newname.prepend("\\markup{");
3741       newname.append("}");
3742     }
3743   else newname = "";
3744   return newname;
3745 }
3746 
3747 
3748 //---------------------------------------------------------
3749 //   writeVoiceMeasure
3750 //---------------------------------------------------------
3751 
writeVoiceMeasure(MeasureBase * mb,Staff * staff,int staffInd,int voice)3752 void ExportLy::writeVoiceMeasure(MeasureBase* mb, Staff* staff, int staffInd, int voice)
3753 
3754 {
3755   int i=0;
3756   char cvoicenum, cstaffnum;
3757   bool  barempty=true;
3758   bool nextisrest=false;
3759   Measure* m = (Measure*) mb;
3760 
3761   //print barchecksign and barnumber for previous measure:
3762   if ((m->no() > 0) and (wholemeasurerest==0) and (textspanswitch==false))
3763     {
3764       indent();
3765       out << " | % " << m->no() << "\n" ;
3766     }
3767   measurenumber=m->no()+1;
3768 
3769    // if (m->irregular())
3770    //   {
3771    // 	       qDebug("irregular measure, number: %d\n", measurenumber);
3772    //   }
3773 
3774 
3775    if ((measurenumber==1) and (donefirst==false))
3776      // ^^^^if clause: to prevent doing these things for both pickup and first full measure
3777     {
3778       donefirst=true;
3779       level=0;
3780       indent();
3781       cvoicenum=voice+65;
3782       cstaffnum= staffInd+65;
3783       //there must be more elegant ways to do this, but whatever...
3784       staffname[staffInd].voicename[voice] = staffname[staffInd].partshort;
3785       staffname[staffInd].voicename[voice].append("voice");
3786       staffname[staffInd].voicename[voice].append(cstaffnum);
3787       staffname[staffInd].voicename[voice].append(cvoicenum);
3788       staffname[staffInd].voicename[voice].prepend("A");
3789       staffname[staffInd].voicename[voice].remove(QRegExp("[0-9]"));
3790       staffname[staffInd].voicename[voice].remove(QChar('.'));
3791       staffname[staffInd].voicename[voice].remove(QChar(' '));
3792 
3793       out << staffname[staffInd].voicename[voice];
3794       out << " = \\relative c" << relativ;
3795       indent();
3796       out << "{\n";
3797       level++;
3798       indent();
3799       if (voice==0)
3800 	{
3801 	  QString flatpartn="";
3802 	  QString flatshortn="";
3803 
3804 	  cout << "X" << staffname[staffInd].partname.toUtf8().data() << "x\n";
3805 
3806 	  flatpartn = flatInInstrName(staffname[staffInd].partname);
3807 	  flatshortn = flatInInstrName(staffname[staffInd].partshort);
3808 
3809 	  out <<"\\set Staff.instrumentName = ";
3810 
3811 	  cout << "F" << flatpartn.toUtf8().data() << "f\n";
3812 
3813 	  if (flatpartn == "")
3814 	    out<< "#\"" << staffname[staffInd].partname << "\"";
3815 	  else
3816 	    out << flatpartn;
3817 	  out << "\n";
3818 
3819 	  indent();
3820 	  out << "\\set Staff.shortInstrumentName = ";
3821 	  if (flatshortn =="")
3822 	    out << "#\"" << staffname[staffInd].partshort << "\"";
3823 	  else
3824 	    out << flatshortn;
3825 	  out << "\n";
3826 
3827 	  indent();
3828 	  writeClef(staff->clef(0));
3829 	  indent();
3830 	  out << "%staffkeysig\n";
3831 	  indent();
3832 	  //done in first measure anyway: ??
3833 	  writeKeySig(staff->keys()->key(0).accidentalType());
3834 // 	  score->sigmap->timesig(0, z1, timedenom);
3835 // 	  out << "\\time " << z1<< "/" << timedenom << " \n";
3836 	}
3837 
3838       cout << "pianostaff: " << pianostaff << "\n";
3839 
3840       if (pianostaff==false)
3841 	//voice settings does not work very well with pianostaffs. Use
3842 	//\stemUp \stemNeutral \stemDown instead
3843 	{
3844 	  switch(voice)
3845 	    {
3846 	    case 0: break;
3847 	      // we don't want voiceOne-specific behaviour if there is only one
3848 	      // voice, so if there are more voices, we append "\voiceOne" later
3849 	    case 1:
3850 	      out <<"\\voiceTwo" <<"\n\n";
3851 	      break;
3852 	    case 2:
3853 	      out <<"\\voiceThree" <<"\n\n";
3854 	      break;
3855 	    case 3:
3856 	      out <<"\\voiceFour" <<"\n\n";
3857 	      break;
3858 	    }
3859 	}
3860 
3861       //check for implicit startrepeat before first measure: (could
3862       //this be done in findvolta()?)
3863       i=0;
3864       while ((voltarray[i].voltart != startrepeat) and (voltarray[i].voltart != endrepeat)
3865 	     and (voltarray[i].voltart !=bothrepeat) and (i<=lastind))
3866 	{
3867 	  i++;
3868 	}
3869 
3870       if (i<=lastind)
3871 	{
3872 	  if ((voltarray[i].voltart==endrepeat) or (voltarray[i].voltart==bothrepeat))
3873 	    {
3874 	      indent();
3875 	      out << "\\repeat volta 2 { \n";
3876 	      repeatactive=true;
3877 	    }
3878 	}
3879     }// END if start of first measure
3880 
3881    if (wholemeasurerest < 1) indent();
3882    int tick = m->tick();
3883    int measuretick=0;
3884    Element* e;
3885 
3886    for(Segment* s = m->first(); s; s = s->next())
3887      {
3888        // for each segment in measure. Get element:
3889        int track = staffInd * VOICES + voice;
3890        e = s->element(track);
3891 
3892        if (!(e == 0 || e->generated()))
3893 	 {
3894 	   voiceActive[voice] = true;
3895 	   barempty = false;
3896 	 }
3897        else
3898          continue;
3899 
3900        handlePreInstruction(e); // Handle instructions which are to be printed before the element itself
3901        barlen=m->ticks();
3902        //handle element:
3903        switch(e->type())
3904 	 {
3905 	 case Element::CLEF:
3906 	   if (wholemeasurerest >=1) writeMeasuRestNum();
3907 	   writeClef(static_cast<Clef*>(e)->clefType());
3908 	   indent();
3909 	   break;
3910 	 case Element::TIMESIG:
3911 	   {
3912 		 if (wholemeasurerest >=1)
3913 		       writeMeasuRestNum();
3914 		 out << "%bartimesig: \n";
3915 		 writeTimeSig((TimeSig*)e);
3916 		 out << "\n";
3917 
3918 		 int nombarlen=z1*MScore::division;
3919 
3920 		 if (timedenom==8) nombarlen=nombarlen/2;
3921 		 if (timedenom == 2) nombarlen = 2*nombarlen;
3922 
3923 		 if ((barlen<nombarlen) and (measurenumber==1) and (voice == 0))
3924 		       {
3925 			     pickup = true;
3926            partial = true;
3927 			     indent();
3928 			     const SigEvent ev(m->score()->sigmap()->timesig(m->tick()));
3929       	   out << "\\partial " << ev.timesig().denominator() << "*" << ev.timesig().numerator() << "\n";
3930 		       }
3931 		 curTicks=-1; //we always need explicit length after timesig.
3932 		 indent();
3933 		 break;
3934 	   }
3935 	 case Element::KEYSIG:
3936 	     {
3937 		 if (wholemeasurerest >=1) writeMeasuRestNum();
3938 
3939 		 out << "%barkeysig: \n";
3940 		 //this simple line did the job before mid-december
3941 		 // 2009:
3942 
3943 		 //writeKeySig(e->subtype());
3944 
3945 		 //but then, some changes must have been made to
3946 		 // keysig.cpp and .h I then stole (as usual) the code
3947 		 // below from exportxml.cpp. It was, however marked
3948 		 // with a "todo". The check for not end of keylist
3949 		 // prevents some keychanges in the middle of the
3950 		 // piece from being written, so I had to comment it
3951 		 // out. (olav.)
3952 
3953 		 KeySig* ksig= (KeySig*) e;
3954 		 int keytick = ksig->tick();
3955 		 cout << "at tick: " << keytick << "\n";
3956 		 KeyList* kl = score->staff(staffInd)-> keys();
3957 		 KeySigEvent key = kl->key(keytick);
3958 //		 auto ci = kl->find(keytick);
3959 		 //
3960 		 //		 if (ci != kl->end())
3961 		 //     {
3962 			 cout << "barkeysig: " << key.accidentalType() << " measureno: " << measurenumber << "\n";
3963 			 indent();
3964 			 writeKeySig(key.accidentalType());
3965 		 //    }
3966 
3967 		 indent();
3968 		 curTicks=-1; //feels safe to force explicit length after keysig
3969 		 break;
3970 	     }
3971 	 case Element::CHORD:
3972 	     {
3973 		 if (wholemeasurerest >=1) writeMeasuRestNum();
3974 		 int ntick = static_cast<Chord*>(e)->tick() - tick;
3975 		 if (ntick > 0)
3976 		     {
3977 			 writeRest(ntick, 2);//invisible rest: s
3978 			 curTicks=-1;
3979 		     }
3980 		 tick += ntick;
3981 		 measuretick=measuretick+ntick;
3982 		 checkIfNextIsRest(mb, s, nextisrest, track);
3983 		 writeChord((Chord*)e, nextisrest);
3984 		 tick += ((Chord*)e)->actualTicks();
3985 		 measuretick=measuretick+((Chord*)e)->actualTicks();
3986 		 break;
3987 	     }
3988 	 case Element::REST:
3989 	   {
3990 	     bool articul=false;
3991 	     findTuplets((ChordRest *) e);
3992 
3993 	     QList<Articulation*> a;
3994 	     ChordRest * CR = (ChordRest*) e;
3995 
3996 	     a = CR->articulations();
3997 
3998 	     if (!(a.isEmpty()) ) articul = true;
3999 
4000 	     int l = ((Rest*)e)->actualTicks();
4001 	     int mlen=((Rest*)e)->segment()->measure()->ticks();
4002 
4003 	     int nombarl=z1*MScore::division;
4004 
4005 	     if (((l==mlen) || (l==0)) and (mlen ==nombarl))  //l == 0 ??
4006 	       {
4007 		 if (wholemeasurerest > 0)
4008 		   {
4009 		     if (articul)
4010 		       {
4011 			 writeMeasuRestNum();
4012 			 writeRest(l,0);
4013 		         writeArticulation((ChordRest*) e);
4014 		       }
4015 		     else
4016 		     wholemeasurerest++;
4017 		   }
4018 		 else
4019 		   {
4020 		     //wholemeasurerest: on fermata, output of * and start of new count.
4021 		     l = ((Rest*)e)->segment()->measure()->ticks();
4022 		     if (articul)
4023 		       {
4024 			 writeRest(l,0);
4025 			 writeArticulation((ChordRest*) e);
4026 		       }
4027 		     else
4028 		       writeRest(l, 1); //wholemeasure rest: R
4029 		   }
4030 	       }
4031 	     else
4032 	       {
4033 		 if (wholemeasurerest >=1)
4034 		   writeMeasuRestNum();
4035 		 writeRest(l, 0);//ordinary rest: r
4036 		 if (articul) writeArticulation((ChordRest*) e);
4037 	       }
4038 	     tick += l;
4039 	     measuretick=measuretick+l;
4040 	  } //end REST
4041 	  break;
4042 	case Element::MARKER:
4043 	  qDebug("ordinary elements: Marker found\n");
4044 	  break;
4045 	case Element::BREATH:
4046 	  out << "\\breathe ";
4047 	  break;
4048 	default:
4049 	  //qDebug("Export Lilypond: unsupported element <%s>\n", e->name());
4050 	  break;
4051 	} // end switch elementtype
4052 
4053        handleElement(e); //check for instructions anchored to element e.
4054 
4055       if (tupletcount==-1)
4056 	{
4057 	  out << " } ";
4058 	  tupletcount=0;
4059 	}
4060     } //end for all segments
4061 
4062    barlen=m->ticks();
4063    if (barempty == true)
4064    // no stuff in this bar in this voice: fill empty bar with silent rest
4065     {
4066       if ((pickup) and (measurenumber==1) and (voice == 0))
4067 	{
4068 
4069     const SigEvent ev(m->score()->sigmap()->timesig(m->tick()));
4070     out << "\\partial " << ev.timesig().denominator() << "*" << ev.timesig().numerator() << "\n";
4071 	  indent();
4072 	  writeRest(barlen,2);
4073 	  out << "\n";
4074 	}//end if pickup
4075       else //if not pickupbar: full measure silent bar
4076 	{
4077 	  writeRest(barlen, 2);
4078 	  curTicks=-1;
4079 	}
4080     }//end bar empty
4081    else // voice bar not empty
4082      {
4083        //we have to fill with spacer rests before and after nonsilent material
4084        if ((measuretick < barlen) and (measurenumber>0))
4085 	 {
4086 	   //fill rest of measure with silent rest
4087 	   int negative=barlen-measuretick;
4088 	   curTicks=-1;
4089 	   writeRest(negative, 2);
4090 	   curTicks=-1;
4091 	 }
4092      }
4093    int mno;
4094    if (!partial)
4095      mno = measurenumber +1;
4096    else
4097      mno = measurenumber;
4098    writeVolta(mno, lastind);
4099 } //end write VoiceMeasure
4100 
4101 
4102 
4103 //---------------------------------------------------------
4104 //   writeScore
4105 //---------------------------------------------------------
4106 
writeScore()4107 void ExportLy::writeScore()
4108 {
4109   // init of some fundamental variables
4110   firstalt=false;
4111   secondalt=false;
4112   tupletcount=0;
4113   char  cpartnum;
4114   chordpitch=41;
4115   repeatactive=false;
4116   staffInd = 0;
4117   graceswitch=false;
4118   int voice=0;
4119   cleannote="c";
4120   prevnote="c";
4121   gracecount=0;
4122   donefirst=false;
4123   lastJumpOrMarker = 0;
4124   initJumpOrMarkerLMs();
4125   wholemeasuretext = "";
4126   glisscount = 0;
4127   textspanswitch = false;
4128   textspannerdown=false;
4129   headOfLyrics = NULL;
4130   tailOfLyrics = NULL;
4131   privateRehearsalMark='A';
4132 
4133 
4134   foreach(Part* part, score->parts())
4135     {
4136       nextAnchor=0;
4137       initAnchors();
4138       resetAnchor(anker);
4139 
4140       int n = part->staves()->size();
4141       staffname[staffInd].partname  = part->longName().toPlainText();
4142       staffname[staffInd].partshort = part->shortName().toPlainText();
4143       curTicks=-1;
4144       pickup=false;
4145 
4146       if (part->nstaves()==2)
4147 	pianostaff = true;
4148       else
4149 	pianostaff = false;
4150 
4151       int strack = score->staffIdx(part) * VOICES;
4152       int etrack = strack + n* VOICES;
4153 
4154       buildInstructionListPart(strack, etrack);
4155       buildGlissandoList(strack,etrack);
4156 
4157 
4158       //ANCHORTEST: print instructionlist
4159       //      qDebug("anchortest\n");
4160       //   anchortest();
4161       //      qDebug("jumptest\n");
4162       //      jumptest(); segfaults!?!?
4163 
4164       foreach(Staff* staff, *part->staves())
4165 	{
4166 
4167 	  out << "\n";
4168     relativ="";
4169 	  switch(staff->clef(0))
4170 	    {
4171 	    case ClefType::G:
4172 	      relativ="'";
4173 	      staffpitch=12*5;
4174 	      break;
4175 	    case ClefType::TAB:
4176 	    case ClefType::PERC:
4177 	    case ClefType::PERC2:
4178 	    case ClefType::G3:
4179 	    case ClefType::F:
4180 	      relativ="";
4181 	      staffpitch=12*4;
4182 	      break;
4183 	    case ClefType::G1:
4184 	    case ClefType::G2:
4185 	      relativ="''";
4186 	      staffpitch=12*6;
4187 	      break;
4188 	    case ClefType::F_B:
4189 	    case ClefType::F_C:
4190 	    case ClefType::F8:
4191 	      relativ=",";
4192 	      staffpitch=12*3;
4193 	      break;
4194 	    case ClefType::F15:
4195 	      relativ=",,";
4196 	      staffpitch=12*2;
4197 	      break;
4198 	    case ClefType::C1:
4199 	    case ClefType::C2:
4200 	    case ClefType::C3:
4201 	    case ClefType::C4:
4202 	      relativ="'";
4203 	      staffpitch=12*5;
4204 	      break;
4205           default:      //??
4206             break;
4207 	    }
4208 
4209 	  staffrelativ=relativ;
4210 
4211 	  cpartnum = staffInd + 65;
4212 	  staffname[staffInd].staffid = staffname[staffInd].partshort;
4213 	  staffname[staffInd].staffid.append("part");
4214 	  staffname[staffInd].staffid.append(cpartnum);
4215 	  staffname[staffInd].staffid.prepend("A");
4216 	  staffname[staffInd].staffid.remove(QRegExp("[0-9]"));
4217 	  staffname[staffInd].staffid.remove(QChar('.'));
4218 	  staffname[staffInd].staffid.remove(QChar(' '));
4219 
4220 	  findVolta();
4221 	  //qDebug("voltatest\n");
4222 	  //	  voltatest();
4223 
4224 	  for (voice = 0; voice < VOICES; ++voice)  voiceActive[voice] = false;
4225 
4226 	  for (voice = 0; voice < VOICES; ++voice)
4227 	    {
4228 	      prevpitch=staffpitch;
4229 	      relativ=staffrelativ;
4230 	      donefirst=false;
4231 	      partial=0;
4232 
4233 	      //for all measures in this voice:
4234 	      for (MeasureBase* m = score->first(); m; m = m->next())
4235 		{
4236 		  if (m->type() != Element::MEASURE)
4237 		    continue;
4238 
4239 		  if (staffInd == 0)
4240 		    findMarkerAtMeasureStart((Measure*) m );
4241 		  //xxx		  else
4242 		  //xxx		    printJumpOrMarker(measurenumber, true);
4243 
4244 		  writeVoiceMeasure(m, staff, staffInd, voice); //really write the measure contents
4245 
4246 		  if (staffInd == 0)
4247 		    jumpAtMeasureStop( (Measure*) m);
4248 		  //xxx else
4249 		  //xxx printJumpOrMarker(measurenumber, false);
4250 		}
4251 	      level--;
4252 	      indent();
4253 	      out << "\\bar \"|.\" \n"; //thin-thick barline as last.
4254 	      level=0;
4255 	      indent();
4256 	      out << "}% end of last bar in partorvoice\n\n";
4257 	      if (voiceActive[voice])
4258 		{
4259 		  scorout<< voicebuffer;
4260 		}
4261 	      voicebuffer = " \n";
4262 	    } // for voice 0 to VOICES
4263 
4264 	  int voiceno=0;
4265 
4266 	  for (voice = 0; voice < VOICES; ++voice)
4267 	    if (voiceActive[voice]) voiceno++;
4268 
4269 	  if (voiceno == 1)
4270 	    staffname[staffInd].simultaneousvoices=false;
4271 
4272 	  if (voiceno>1) //if more than one voice must be combined into one staff.
4273 	    {
4274 	      level=0;
4275 	      indent();
4276 	      out << staffname[staffInd].staffid << " =  << \n";
4277 	      staffname[staffInd].simultaneousvoices=true;
4278 	      level++;
4279 	      indent();
4280 	      out << "\\mergeDifferentlyHeadedOn\n";
4281 	      indent();
4282               out << "\\mergeDifferentlyDottedOn \n";
4283 	      ++level;
4284 
4285 	      for (voice = 0; voice < voiceno; voice++)
4286 		{
4287 		  if (voiceActive[voice])
4288 		    {
4289 		      //have to go back to explicitly  naming the voices, so that
4290 		      //it will be possible to attach lyrics to them.
4291 		      indent();
4292 		      out << "\\context Voice = " << staffname[staffInd].voicename[voice] ;
4293 		      if ((voice == 0) and (pianostaff ==false))
4294 			out << "{\\voiceOne ";
4295 		      out << "\\" << staffname[staffInd].voicename[voice];
4296 		      if ((voice == 0) and (pianostaff == false))
4297 			out << "}";
4298 		      if (voice < voiceno-1) out << "\\\\ \n";
4299 		      else out <<"\n";
4300 		    }
4301 		}
4302 
4303 	      indent();
4304 	      out << ">> \n\n";
4305 	      level=0;
4306 	      indent();
4307 	      scorout<< voicebuffer;
4308 	      voicebuffer = " \n";
4309 	    }
4310 	  staffname[staffInd].numberofvoices=voiceno;
4311 	  ++staffInd;
4312 	}// end of foreach staff
4313 
4314       staffname[staffInd].staffid="laststaff";
4315       if (n > 1)
4316 	{
4317 	  --level;
4318 	  indent();
4319 	}
4320     }// end for each part
4321 }// end of writeScore
4322 
4323 
4324 //-------------------------------------------------------------------
4325 // write score-block: combining parts and voices, drawing brackets and
4326 // braces, at end of lilypond file
4327 // -------------------------------------------------------------------
writeScoreBlock()4328 void ExportLy::writeScoreBlock()
4329 {
4330   thisLyrics = headOfLyrics;
4331 
4332   if (nochord==false) // output the chords as a separate staff before the score-block
4333     {
4334       os << "theChords = \\chordmode { \n";
4335       printChordList();
4336       cleanupChordList();
4337       level--;
4338     }
4339 
4340   //  bracktest();
4341 
4342   level=0;
4343   os << "\n\\score { \n";
4344   level++;
4345   indentF();
4346   os << "<< \n";
4347 
4348   indx=0;
4349   while (staffname[indx].staffid!="laststaff")
4350     {
4351       if (lybracks[indx].brakstart)
4352 	{
4353 	  ++level;
4354 	  indentF();
4355 	  os << "\\context StaffGroup = " << (char)(lybracks[indx].brakno + 64) << "<< \n";
4356 	}
4357 
4358       if (lybracks[indx].bracestart)
4359 	{
4360 	  ++level;
4361 	  indentF();
4362 	  if (lybracks[indx].piano)
4363 	    {
4364 	      os << "\\context PianoStaff <<\n";
4365 	      indentF();
4366 	      os << "\\set PianoStaff.instrumentName=\"Piano\" \n";
4367 	      pianostaff=true;
4368 	    }
4369 	  else
4370 	    os << "\\context GrandStaff = " << (char)(lybracks[indx].braceno + 64) << "<< \n";
4371 	}
4372 
4373       if ((nochord == false) && (indx==0)) //insert chords as the first staff.
4374 	{
4375 	  indentF();
4376 	  os << "\\new ChordNames { \\theChords } \n";
4377 	}
4378 
4379 
4380       ++level;
4381       indentF();
4382       os << "\\context Staff = " << staffname[indx].staffid << " << \n";
4383       ++level;
4384       indentF();
4385       os << "\\";
4386       if (staffname[indx].simultaneousvoices)
4387 	os << staffname[indx].staffid << "\n";
4388       else
4389 	{
4390 	  // have to reintroduce explicit naming of voices because of "\lyricsto"
4391 	  os << "context Voice = "  << staffname[indx].voicename[0] << " \\";
4392 	  os << staffname[indx].voicename[0] << "\n"; //voices are counted from 0.
4393 	}
4394 
4395       if (lybracks[indx].piano)
4396 	{
4397 	  indentF();
4398 	  os << "\\set Staff.instrumentName = #\"\"\n";
4399 	  indentF();
4400 	  os << "\\set Staff.shortInstrumentName = #\"\"\n";
4401 	}
4402 
4403       --level;
4404       indentF();
4405       os << ">>\n\n"; // end of this staff
4406 
4407       connectLyricsToStaff();
4408 
4409       if (((lybracks[indx].brakstart) and (lybracks[indx].brakend)) or ((lybracks[indx].bracestart) and (lybracks[indx].braceend)))
4410 	{
4411 	  //if bracket or brace starts and ends on same staff: one-staff brace/bracket.
4412 	  indentF();
4413 	  os << "\\override StaffGroup.SystemStartBracket #'collapse-height = #1 \n";
4414 	  indentF();
4415 	  os << "\\override Score.SystemStartBar #'collapse-height = #1 \n";
4416 	}
4417 
4418       if (lybracks[indx].brakend)
4419 	{  --level;
4420 	  indentF();
4421 	  os << ">> %end of StaffGroup" << (char)(lybracks[indx].brakno + 64) << "\n\n";
4422 	}
4423       if (lybracks[indx].braceend)
4424 	{
4425 	  --level;
4426 	  indentF();
4427 	  if (lybracks[indx].piano)
4428 	    os << ">> %end of PianoStaff" << (char)(lybracks[indx].braceno + 64) << "\n";
4429 	  else
4430 	    os << ">> %end of GrandStaff" << (char)(lybracks[indx].braceno + 64) << "\n";
4431 	}
4432 
4433 
4434       --level;
4435       ++indx;
4436 
4437     }//while still more staves
4438 
4439   cleanupLyrics();
4440 
4441   os << "\n";
4442 
4443   os << "\n"
4444   "      \\set Score.skipBars = ##t\n"
4445   "      %%\\set Score.melismaBusyProperties = #'()\n"
4446   "      \\override Score.BarNumber #'break-visibility = #end-of-line-invisible %%every bar is numbered.!!!\n"
4447   "      %% remove previous line to get barnumbers only at beginning of system.\n"
4448   "       #(set-accidental-style 'modern-cautionary)\n";
4449   if (rehearsalnumbers) os <<  "      \\set Score.markFormatter = #format-mark-box-numbers %%boxed rehearsal-numbers \n";
4450   else  os <<  "      \\set Score.markFormatter = #format-mark-box-letters %%boxed rehearsal-marks\n";
4451   if ((timedenom == 2) and (z1 == 2))
4452     {os << "%% "; }
4453   os << "       \\override Score.TimeSignature #'style = #'() %%makes timesigs always numerical\n"
4454   "      %% remove previous line to get cut-time/alla breve or common time \n";
4455 
4456 os <<
4457   "      \\set Score.pedalSustainStyle = #'mixed \n"
4458   "       %% make spanners comprise the note it end on, so that there is no doubt that this note is included.\n"
4459   "       \\override Score.TrillSpanner #'(bound-details right padding) = #-2\n"
4460   "      \\override Score.TextSpanner #'(bound-details right padding) = #-1\n"
4461   "      %% Lilypond's normal textspanners are too weak:  \n"
4462   "      \\override Score.TextSpanner #'dash-period = #1\n"
4463   "      \\override Score.TextSpanner #'dash-fraction = #0.5\n"
4464   "      %% lilypond chordname font, like mscore jazzfont, is both far too big and extremely ugly (olagunde@start.no):\n"
4465   "      \\override Score.ChordName #'font-family = #'roman \n"
4466   "      \\override Score.ChordName #'font-size =#0 \n"
4467   "      %% In my experience the normal thing in printed scores is maj7 and not the triangle. (olagunde):\n"
4468   "      \\set Score.majorSevenSymbol = \\markup {maj7}\n"
4469   "  >>\n\n"
4470   "  %% Boosey and Hawkes, and Peters, have barlines spanning all staff-groups in a score,\n"
4471   "  %% Eulenburg and Philharmonia, like Lilypond, have no barlines between staffgroups.\n"
4472   "  %% If you want the Eulenburg/Lilypond style, comment out the following line:\n"
4473   "  \\layout {\\context {\\Score \\consists Span_bar_engraver}}\n"
4474   "}%% end of score-block \n\n";
4475 
4476   if (((pianostaff) and (indx==2)) or (indx < 2))
4477     os << "#(set-global-staff-size 20)\n";
4478   else if (indx > 2)
4479     os << "#(set-global-staff-size 14)\n";
4480 }// end scoreblock
4481 
4482 
4483 
4484 //-------------------------------------------------------------------------
4485 //    writeLilyMacros
4486 //-------------------------------------------------------------------------
4487 
writeLilyMacros()4488 void ExportLy::writeLilyMacros()
4489 {
4490   if ((jumpswitch) || (ottvaswitch))
4491     {
4492       os<< " %%---------------MSCORE'S LILYPOND MACROS: -------------------------\n\n";
4493     }
4494 
4495   if (ottvaswitch)
4496     {
4497       os << " %%-----------------replacement for the \\ottava command--------------------\n\n";
4498 
4499       //The lilypond \ottava command moves the visual notes one octave
4500       //down, so that they will sound at their correct pitch when we
4501       //take account of the 8va instruction. Mscore adds the
4502       //8va-instruction and leave the notes in place on the staff. In
4503       //order to make the lilypond code exported from mscore reflect
4504       //mscore behavior, it was necessary to construct the macros \okt
4505       //and \oktend as substitutes for \ottava. A more elegant
4506       //solution would be to prevent lilypond's \ottava from temporarily
4507       //resetting the middleCPosition, but I did not understand how to
4508       //do that. (olav)
4509 
4510       os << "ottva =\n  "
4511 	"{  %% for explanation, see mscore source file exportly.cpp \n"
4512 	"   \\once\\override TextSpanner #'(bound-details left text) = \"8va\" \n"
4513 	"   \\once\\override TextSpanner #'(bound-details right text) = \\markup{ \\draw-line #'(0 . -1) }\n"
4514 	"   #(ly:export (make-event-chord (list (make-span-event 'TextSpanEvent START)))) \n"
4515 	"}\n"
4516 	"\n"
4517 
4518 	"ottvaend ={ #(ly:export (make-event-chord (list (make-span-event 'TextSpanEvent STOP)))) \n"
4519 	"   \\textSpannerNeutral} \n"
4520 
4521 	"ottvabassa = \n"
4522 	"{   \n"
4523 	"   \\once \\override TextSpanner #'(bound-details left text) = \"8vb\"  \n"
4524 	"   \\textSpannerDown \n"
4525         "   \\once \\override TextSpanner #'(bound-details right text) = \\markup{ \\draw-line #'(0 . 1) } \n"
4526 	"   #(ly:export (make-event-chord (list (make-span-event 'TextSpanEvent START)))) \n"
4527 	"}\n"
4528 	"\n"
4529 
4530 	"%%------------------end ottava macros ---------------------\n\n";
4531  }// end of if ottva
4532 
4533 
4534   if (jumpswitch)
4535     {
4536       os << "   %%------------------coda---segno---macros--------------------\n"
4537 
4538 	"   %%                 modified from lsr-snippets. Work in progress:       \n"
4539 
4540 	"   %% These macros presupposes a difference between the use of the       \n"
4541 	"   %% Coda-sign telling us to jump to the coda (\\gotocoda), and the   \n"
4542 	"   %% Coda-sign telling us that this is actually the Coda (\\theCoda).  \n"
4543 	"   %% This goes well if you use the mscore text: \"To Coda\" as a mark of \n"
4544 	"   %% of where to jump from, and the codawheel as the mark of where to jump to\n"
4545 	"   %% Otherwise (using codawheel for both) you have to edit the lilypond-file by hand.\n"
4546 
4547 	"   gotocoda     = \\mark \\markup {\\musicglyph #\"scripts.coda\"}               \n"
4548 	"   thecodasign  = \\mark \\markup {\\musicglyph #\"scripts.coda\" \"Coda\"}     \n"
4549 	"   thesegno     = \\mark \\markup {\\musicglyph #\"scripts.segno\"}              \n"
4550 	"   varcodasign  = \\mark \\markup {\\musicglyph #\"scripts.varcoda\"}            \n"
4551 	"   Radjust      =  \\once \\override Score.RehearsalMark #'self-alignment-X = #RIGHT \n"
4552 	"   blankClefKey = {\\once \\override Staff.KeySignature #'break-visibility = #all-invisible \n"
4553 	"		    \\once \\override Staff.Clef #'break-visibility = #all-invisible   \n"
4554 	"                 } \n"
4555 	"   codetta     = {\\mark \\markup \\line {\\musicglyph #\"scripts.coda\" \\hspace #-1.3 \\musicglyph #\"scripts.coda\"} } \n"
4556 	"   fine        = {\\Radjust \\mark \\markup {\"Fine\"} \\mark \\markup {\\musicglyph #\"scripts.ufermata\" } \n"
4557 	"		  \\bar \"||\" } \n"
4558 	"   DCalfine    = {\\Radjust \\mark \\markup {\"D.C. al fine\"} \\bar \"||\" \\blankClefKey \\stopStaff \\cadenzaOn } \n"
4559 	"   DCalcoda    = {\\Radjust \\mark \\markup {\"D.C. al coda\"} \\bar \"||\" \\blankClefKey \\stopStaff \\cadenzaOn }  \n"
4560 	"   DSalfine    = {\\Radjust \\mark \\markup {\"D.S. al fine\"} \\bar \"||\" \\blankClefKey \\stopStaff \\cadenzaOn } \n"
4561 	"   DSalcoda    = {\\Radjust \\mark \\markup {\"D.S. al coda\"} \\bar \"||\" \\blankClefKey \\stopStaff \\cadenzaOn } \n"
4562 	"   showClefKey = {\\once \\override Staff.KeySignature #'break-visibility = #all-visible \n"
4563 	"               \\once \\override Staff.Clef #'break-visibility = #all-visible \n"
4564 	"		 } \n"
4565 	"   resumeStaff = {\\cadenzaOff \\startStaff % Resume bar count and show staff lines again \n"
4566 	"		  \\partial 32 s32 % Add a whee bit of staff before the clef! \n"
4567 	"		  \\bar \"\" \n"
4568 	"		 } \n"
4569 	"   %%   whitespace between D.S./D.C. and the Coda: \n"
4570 	"   codaspace = {\\repeat unfold 2 {s4 s4 s4 s4 \\noBreak \\bar \"\" }}  \n"
4571 	"   theCoda   = {\\noBreak \\codaspace \\resumeStaff \\showClefKey \\thecodasign} \n"
4572 
4573 	" %% -------------------end-of-coda-segno-macros------------------  \n\n ";
4574     }
4575 
4576  if ((jumpswitch) || ottvaswitch)
4577    {
4578      os << "%% --------------END MSCORE LILYPOND-MACROS------------------------\n\n\n\n\n";
4579    }
4580 } //end of writelilymacros
4581 
4582 
4583 
4584 //-------------------------------------------------------------
4585 //   writeLilyHeader
4586 //-------------------------------------------------------------
writeLilyHeader()4587 void ExportLy::writeLilyHeader()
4588 {
4589   os << "%=============================================\n"
4590     "%   created by MuseScore Version: " << VERSION << "\n"
4591     "%          " << QDate::currentDate().toString(Qt::SystemLocaleLongDate);
4592   os << "\n";
4593   os <<"%=============================================\n"
4594     "\n"
4595     "\\version \"2.12.0\"\n\n";     // target lilypond version
4596 
4597   os << "\n\n";
4598 }
4599 
4600   //---------------------------------------------------
4601   //    Page format
4602   //---------------------------------------------------
writePageFormat()4603 void ExportLy::writePageFormat()
4604 {
4605   const PageFormat* pf = score->pageFormat();
4606   os << "#(set-default-paper-size ";
4607       os << "\"" << QString(pf->paperSize()->name).toLower() << "\"";
4608 
4609   if (pf->size().width() > pf->size().height()) os << " 'landscape";
4610 
4611   os << ")\n\n";
4612 
4613   // TODO/O.G.: choose between standard formats and specified paper
4614   // dimensions. We normally don't need both.
4615 
4616   double lw = pf->printableWidth();
4617   os << "\\paper {\n";
4618   os <<  "  line-width    = " << lw * INCH << "\\mm\n";
4619   os <<  "  left-margin   = " << pf->evenLeftMargin() * INCH << "\\mm\n";
4620   os <<  "  top-margin    = " << pf->evenTopMargin() * INCH << "\\mm\n";
4621   os <<  "  bottom-margin = " << pf->evenBottomMargin() * INCH << "\\mm\n";
4622   os <<  "  %%indent = 0 \\mm \n";
4623   os <<  "  %%set to ##t if your score is less than one page: \n";
4624   os <<  "  ragged-last-bottom = ##t \n";
4625   os <<  "  ragged-bottom = ##f  \n";
4626   os <<  "  %% in orchestral scores you probably want the two bold slashes \n";
4627   os <<  "  %% separating the systems: so uncomment the following line: \n";
4628   os <<  "  %% system-separator-markup = \\slashSeparator \n";
4629   os <<  "  }\n\n";
4630 }//end writepageformat
4631 
4632 
4633 
4634 //---------------------------------------------------
4635 //    writeScoreTitles
4636 //---------------------------------------------------
writeScoreTitles()4637 void ExportLy::writeScoreTitles()
4638 {
4639 #if 0 //TODOws
4640 
4641   os << "\\header {\n";
4642 
4643   ++level;
4644   const MeasureBase* m = score->first();
4645   foreach(const Element* e, *m->el()) {
4646     if (e->type() != TEXT)
4647       continue;
4648     QString s = ((Text*)e)->text();
4649     indentF();
4650     switch(e->subtype()) {
4651     case TEXT_TITLE:
4652       os << "title = ";
4653       break;
4654     case TEXT_SUBTITLE:
4655       os << "subtitle = ";
4656       break;
4657     case TEXT_COMPOSER:
4658       os << "composer = ";
4659       break;
4660     case TEXT_POET:
4661       os << "poet = ";
4662       break;
4663     default:
4664       qDebug("text-type %d not supported\n", e->subtype());
4665       os << "subtitle = ";
4666       break;
4667     }
4668     os << "\"" << s << "\"\n";
4669   }
4670 
4671   if (!score->metaTag("Copyright").isEmpty())
4672     {
4673       indentF();
4674       os << "copyright = \"" << score->metaTag("Copyright") << "\"\n";
4675     }
4676 
4677   indentF();
4678   os << "}\n";
4679 #endif
4680 }// end writeScoreTitles
4681 
4682 
4683 
4684 //---------------------------------------------------------
4685 //---------------------------------------------------------
4686 //  WRITE  =  the main function of exportly
4687 //---------------------------------------------------------
4688 //---------------------------------------------------------
4689 
write(const QString & name)4690 bool ExportLy::write(const QString& name)
4691 {
4692   //init of some fundamental variables.
4693   pianostaff=false;
4694   rehearsalnumbers=false;
4695   wholemeasurerest=0;
4696   f.setFileName(name);
4697   if (!f.open(QIODevice::WriteOnly))
4698     return false;
4699   os.setDevice(&f);
4700   os.setCodec("utf8");
4701   out.setCodec("utf8");
4702   out.setString(&voicebuffer);
4703   voicebuffer = "";
4704   scorout.setCodec("utf8");
4705   scorout.setString(&scorebuffer);
4706   scorebuffer = "";
4707   chordHead=NULL;
4708   chordcount = 0;
4709   slurstack=0;
4710   phraseslur=0;
4711   ottvaswitch = false;
4712   jumpswitch = false;
4713   nochord = true;
4714 
4715   writeLilyHeader();
4716 
4717   writeScore();
4718 
4719   findLyrics();
4720 
4721   writeLilyMacros();
4722 
4723   writePageFormat();
4724 
4725   writeScoreTitles();
4726 
4727   findBrackets();
4728 
4729   os << scorebuffer;
4730   scorebuffer = "";
4731 
4732   writeLyrics();
4733 
4734   writeScoreBlock();
4735 
4736   f.close();
4737   return f.error() == QFile::NoError;
4738 }// end of function "write"
4739 
4740 
4741 
4742 
4743 
4744 /*----------------------- NEWS and HISTORY:--------------------  */
4745 
4746 /*
4747 
4748   02.feb 2010. If \voiceOne etc. is used in pianostaff, articulation
4749   signs are either placed on only above or only below staff, and not
4750   in any reasonable connection with the notehead. So \voiceOne etc. is
4751   no longer used in pianostaff.
4752 
4753   27.dec.09 Two (and not more than two) dynamic signs on the same
4754   note.
4755 
4756   26.dec.09 Fixed bug in triplets of chords. Tried to update outdated
4757   code on keychanges.
4758 
4759   23,dec.09 Flat symbol in instrumentnames are now handled. Some
4760   progress on reconciling rehearsalmarks and segno/coda-symbols.
4761 
4762   17. dec.09 Dynamics and text can now be connected to the same note.
4763 
4764    09.dec.09 Fermatas on rests (wholemeasure and others). Fixed bugs
4765   in repeats/doblebars and in wholemeasurerests caused by pickupbar
4766 
4767   20.nov.2009  Tried to repair reported crash on file Cronicas.mscz
4768 
4769   7.nov. 2009: Lyrics. Works reasonably well on demo adeste.
4770 
4771    1.nov. lefthandposition (roman numbers with line: violin, guitar),
4772    trill, pedal and general lines with/out text.
4773 
4774    30.oct. Unterminated slurs: \laissezVibrer. Whole notes as part of
4775    triplets. Flageolets as symbol connected to the note.
4776 
4777    28.oct. Arpeggios and glissandos. Fixed issue of 6.may in the issue
4778    tracker: incorrect export of polyphony.
4779 
4780    25.oct. Implemented fingering and guitar string-number
4781 
4782    24.oct Support for metronome marks.
4783 
4784    22.oct  conditional output of exportly's lilypond macros (\okt and
4785      \segno). bugfix for repeats.
4786 
4787    13.oct fixed grace-note-troubles on demos: golliwogg, and troubles
4788    with wholemeasure rests in the shifting timesignatures in
4789    promenade. Started on lilypond \chordmode
4790 
4791    08.okt.  (olav) Tremolo. Segno and Coda. Correct insertion of s-rests
4792           in demo: adeste.
4793 
4794    01.oct. 2009 (Olav) Improved export of whole measure rests.
4795 
4796    29.sep.2009 (Olav) Rudiments of new 8va. Bugfix for repeats. Some
4797    support for Segno/Coda.
4798 
4799    12.sep.2009 (Olav) Improved export of rehearsalmarks.
4800 
4801    17.aug.2009 (db) add quotes around unparsed markup (since it can
4802    contain special characters), commented out the indent=0, fix spelling
4803    mistake for octave markings ("set-octaviation"), fix type of ottava
4804 
4805    mar. 2009 always explicit end-bar -> no need to declare last bar as
4806    incomplete, but writes two end-bars when last bar is complete. This
4807    doesn't show in print.
4808 
4809    12.feb.2009. - Removed bug: double instrument definitions in pieces
4810    with pickup-measure (prev'ly defined both in measure 0 and measure
4811    1). - Removed bug: nonrecognition of startrepeats. -Improved
4812    recognition of whole-measure rests.
4813 
4814    NEW 5.feb.2009: separated grandstaff (variable distance between staffs) from
4815    pianostaff: constant distance between staffs to prepare for cross-staff
4816    beaming (not implemented). Brackets/braces for single staffs.
4817 
4818    NEW 25.jan.2009: system brackets and braces for simple scores.
4819    Unsolved complications for multistaff instruments (piano, organ,
4820    harp), and for bracketing single staffs.
4821 
4822    NEW 22.jan. 2009
4823    -- fixed a problem with beams on grace-notes, and
4824    some faults produced by the previous revision of exportly.
4825 
4826    NEW 18. jan. 2009
4827    -- Now avoids export of empty voices.
4828 
4829    DELETED HISTORY PRE 2009.
4830 
4831 */
4832 
4833 
4834 /*----------------------TODOS------------------------------------
4835 
4836 
4837       -- Coda/Segno symbols collides with rehearsalmarks, which
4838       accordingly are not printed. Lilypond has automatic
4839       incrementation of rehearsalmarks. It is easy to input values to
4840       the variable in which the mark is stored. But I have not
4841       succeeded in finding an easy way to extract this
4842       value. Lilyponds \mark\default, which write the automatically
4843       incremented rehearsalmark is not reconcilable with segnos and
4844       coda, except thru very complex macros, which will make the
4845       exported lilypond code very ugly and not very perspicuous. If it
4846       was easy to extract the value of the reharsalmark variable from
4847       Lilypond, these macros would not be necessary. Because they
4848       clutter the lilypond-code I do not want to use them. I
4849       can then increment the rehearsalmarks in exportly.cpp, or I can
4850       extract the values of the rehearsalmarks in mscore. As mscore's
4851       manual insertion of rehearsalmarks is less elegant than than
4852       automatic incrementation, I chose to make exportly.cpp increment
4853       the rehearsalmarks. This gives the cleanest lilypond-code.
4854 
4855       -- all kinds of symbols at the notelevel. More symbols on the
4856      measurelevel
4857 
4858       -- odd noteheads and percussion staffs.  See output from noteedit.
4859 
4860       -- breaks and spacers
4861 
4862       -- accordion symbols.
4863 
4864       -- dotted rests in timesignatures which do not subdivide in 3
4865          (like 6/8, 12/8) are plain and simply wrong, and must be made
4866          impossible: translate to two separate rests.
4867 
4868    -- become clear on the difference between system text and staff
4869       text.
4870 
4871    -- octave-trouble in golliwogg.
4872 
4873    -- provide for more than one pianostaff in a score.
4874 
4875    -- Determine whether text goes above or below staff.
4876 
4877    -- correct export of chordsymbols: many faults.
4878 
4879    -- cross-staff beaming in pianostaff cross-voice slurs!?!?!? seems
4880       _very_ complex to implement (example demos:promenade, bar 6)
4881       Will \partcombine do it?
4882 
4883 
4884    -- difficult problem with hairpins: Beginning of hairpin and
4885    -- end of hairpin are anchored to different notes. This is done
4886    -- automatically when you drop an hairpin in the appropriate place
4887    -- in the score. exportly find these anchors and insert \< and \!
4888    -- after these notes. But the start of the hairpin protrudes to the
4889    -- left of the anchor. And often the end of the hairpin is anchored
4890    -- to a note which is too far to the right. The placement of the
4891    -- lily-symbols must take regard for the placement on the canvas
4892    -- and not to the anchorpoints alone. Check the procedure in the
4893    -- main program to see how the anchorpoints and the canvas-position
4894    -- is made and compensate for this when exporting the
4895    -- lily-symbols. -- check \set Score.hairpinToBarline = ##t
4896 
4897    -- close second volta: doesn't seem possible for single and
4898       thin-thin double barlines
4899 
4900    --Collisions in crowded multi-voice staffs
4901      (e.g. cello-suite). check \override RestCollision
4902      #'positioning-done = #'merge-rests-on-positioning. Use
4903      \partcombine instead of ord. polyphony
4904 
4905    -- General tuplets massive failure on demos: prelude_sr.mscz
4906 
4907    -- Many of the demos have voice 2 as the upper one =>
4908       trouble. Exportly.cpp must be made to identify the uppermost
4909       voice as lilypond voice 1, whatever number it has in
4910       mscore. will \partcombine resolve this?
4911 
4912   -- Markups belonging to a multimeasure rest should be
4913      left-adjusted to the left barline, and not centered over the
4914      rest. No good solutions found.
4915 
4916   -- Bug in lilypond. See notation reference 1.2.6 for 2.12.1:
4917      gracenotes. At the end: issues and warnings: "Grace note
4918      synchronization can also lead to surprises. Staff notation, such
4919      as key signatures, bar lines, etc., are also synchronized. Take
4920      care when you mix staves with grace notes and staves without, for
4921      example, ....This can be remedied by inserting grace skips of the
4922      corresponding durations in the other staves." In earlier editions
4923      of the manual, this is rightly described as a bug. I am awaiting
4924      the correction of this in lilypond, which, given the promotion
4925      from bug to "issue", probably will be never, and I will not correct
4926      for it here. (olav)
4927  */
4928 }
4929 
4930