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