1 /*
2   MusicXML Library
3   Copyright (C) Grame 2006-2013
4 
5   This Source Code Form is subject to the terms of the Mozilla Public
6   License, v. 2.0. If a copy of the MPL was not distributed with this
7   file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 
9   Grame Research Laboratory, 11, cours de Verdun Gensoul 69002 Lyon - France
10   research@grame.fr
11 */
12 
13 #ifndef __xmlpart2guido__
14 #define __xmlpart2guido__
15 
16 #include <ostream>
17 #include <stack>
18 #include <queue>
19 #include <map>
20 #include <string>
21 
22 #include "clefvisitor.h"
23 #include "exports.h"
24 #include "guido.h"
25 #include "keysignvisitor.h"
26 #include "metronomevisitor.h"
27 #include "notevisitor.h"
28 #include "rational.h"
29 #include "timesignvisitor.h"
30 #include "typedefs.h"
31 #include "visitor.h"
32 #include "xml.h"
33 
34 namespace MusicXML2
35 {
36 
37 /*!
38 \ingroup visitors guido
39 @{
40 */
41 
42 /*!
43 \brief A score visitor to produce a Guido representation.
44 */
45 //______________________________________________________________________________
46 class EXP xmlpart2guido :
47 	public clefvisitor,
48 	public timesignvisitor,
49 	public notevisitor,
50 	public keysignvisitor,
51 	public visitor<S_backup>,
52 	public visitor<S_barline>,
53 	public visitor<S_coda>,
54 	public visitor<S_direction>,
55 	public visitor<S_divisions>,
56 	public visitor<S_ending>,
57 	public visitor<S_forward>,
58 	public visitor<S_measure>,
59 	public visitor<S_octave_shift>,
60 	public visitor<S_part>,
61 	public visitor<S_repeat>,
62 	public visitor<S_segno>,
63 	public visitor<S_sound>,
64     public visitor<S_wedge>,
65 	public visitor<S_rehearsal>,     // for rehearsal Markup
66     public visitor<S_attributes>         // to get clef, division, staves, time and key in order!
67 {
68 	// the guido elements stack
69 	std::stack<Sguidoelement>	fStack;
70 	// structure to store delayed elements ie elements enclosed in direction with offset
71 	typedef struct {
72 		long delay;
73 		Sguidoelement element;
74 	} delayedElement;
75 	vector<delayedElement>	fDelayed;
76 	// fields to controls the guido output generation
77 	bool fGenerateComments, fGenerateBars, fGeneratePositions, fGenerateAutoMeasureNum, fLyricsManualSpacing;
78 //	bool fGenerateStem;
79 
80 	// internal parsing state
81     bool	fInCue, fInGrace, fInhibitNextBar, fPendingBar, fBeamOpened, fMeasureEmpty, fCrescPending,fWavyTrillOpened, fSingleScopeTrill, fNonStandardNoteHead, fDoubleBar, fTremoloInProgress;
82 
83     int fTextTagOpen;
84     int fTupletOpen;    // Number of opened Tuplets
85 
86     std::queue<int> fDirectionEraserStack;        // To skip already visited Directions when looking ahead because of grace notes
87     std::stack< std::pair<int, int> > fBeamStack; // first int: Internal num, 2nd int: XML num
88     std::vector< std::pair<int, int> > fSlurStack; // first int: Internal num, 2nd int: XML num
89 
90     Sguidoelement fLyricOpened;
91 
92     bool isProcessingChord;
93 
94 	S_measure	fCurrentMeasure;
95     S_part      fCurrentPart;
96 
97 	bool	fNotesOnly;				// a flag to generate notes only (used for several voices on the same staff)
98 	bool	fSkipDirection;			// a flag to skip direction elements (for notes only mode or due to different staff)
99 	int		fCurrentStaffIndex;		// the index of the current guido staff
100 	int		fCurrentStaff;			// the staff we're currently generating events for (0 by default)
101 	int		fTargetStaff;			// the musicxml target staff (0 by default)
102 	int		fTargetVoice;			// the musicxml target voice (0 by default)
103 
104 	long	fCurrentDivision;		// the current measure division, expresses the time unit in division of the quarter note
105 	long	fCurrentOffset;			// the current direction offset: represents an element relative displacement in current division unit
106 	rational fCurrentMeasureLength;	// the current measure length (max of the current measure positions)
107 	rational fCurrentMeasurePosition;// the current position in the measure
108 	rational fCurrentVoicePosition;	// the current position within a voice
109 	rational fCurrentTimeSign;		// the current time signature
110 	int		fMeasNum;
111 
112     int		fCurrentBeamNumber;		// number attribute of the current beam
113 	int		fCurrentStemDirection;	// the current stems direction, used for stem direction changes
114 	int		fPendingPops;			// elements to be popped at chord exit (like fermata, articulations...)
115 
start(Sguidoelement & elt)116 	void start (Sguidoelement& elt)		{ fStack.push(elt); }
add(Sguidoelement & elt)117 	void add  (Sguidoelement& elt)		{ if (fStack.size()) fStack.top()->add(elt); }
118 	void addDelayed (Sguidoelement elt, long offset);	// adding elements to the delayed elements
119 	void checkDelayed (long time);						// checks the delayed elements for ready elements
push(Sguidoelement & elt)120 	void push (Sguidoelement& elt)		{ add(elt); fStack.push(elt); }
pop()121 	void pop ()							{ fStack.pop(); }
122 
123 	void moveMeasureTime (int duration, bool moveVoiceToo=false, int x_default = 0);
124 	void reset ();
125 	void stackClean	();
126 
127 	int  checkArticulation ( const notevisitor& note );			// returns the count of articulations pushed on the stack
128     void checkPostArticulation ( const notevisitor& note );      /// Articulations that should be generated in ADD mode after note creation
129 
130     int  checkChordOrnaments ( const notevisitor& note );			// returns the count of articulations pushed on the stack
131 
132     std::vector<Sxmlelement>  getChord ( const S_note& note );    // build a chord vector
133 	std::vector<Sxmlelement>  getChord ( const Sxmlelement& note );	// build a chord vector
134 	void checkStaff		 (int staff );					// check for staff change
135 	void checkStem		 ( const S_stem& stem );
136 	void checkBeamBegin	 ( const std::vector<S_beam>& beams );
137     void checkBeamEnd	 ( const std::vector<S_beam>& beams );
138     void checkTupletBegin( const std::vector<S_tuplet>& tuplets,
139                           const notevisitor& nv,
140                           const S_note& elt);
141     void checkTupletEnd	 ( const std::vector<S_tuplet>& tuplets );
142 	void checkCue		 ( const notevisitor& nv );
143 	void checkGrace		 ( const notevisitor& nv );
144     void checkGraceEnd(const notevisitor& nv);
145 	int  checkFermata	 ( const notevisitor& stem );
146     void checkSlur     ( const std::vector<S_slur>& slurs );
147 	void checkSlurBegin	 ( const std::vector<S_slur>& slurs );
148 	void checkSlurEnd	 ( const std::vector<S_slur>& slurs );
149     bool isSlurClosing(S_slur elt);
150 	void checkTiedBegin	 ( const std::vector<S_tied>& tied );
151 	void checkTiedEnd	 ( const std::vector<S_tied>& tied );
152 	void checkVoiceTime	 ( const rational& currTime, const rational& voiceTime);
153     int  checkRestFormat	 ( const notevisitor& nv );
154     int checkNoteFormatDx	 ( const notevisitor& nv , rational posInMeasure);
155     void checkWavyTrillBegin	 ( const notevisitor& nv );
156     void checkWavyTrillEnd	 ( const notevisitor& nv );
157     void checkTextEnd();
158 	void newNote		 ( const notevisitor& nv, rational posInMeasure, const S_note& elt);
159 
160     int checkTremolo(const notevisitor& note, const S_note& elt);
161 
162 	std::string			noteName		( const notevisitor& nv );
163 	guidonoteduration	noteDuration	( const notevisitor& nv);
164 
165 	std::vector<S_beam>::const_iterator findValue ( const std::vector<S_beam>& beams, const std::string& val ) const;
166 	std::vector<S_slur>::const_iterator findTypeValue ( const std::vector<S_slur>& slurs, const std::string& val ) const;
167 	std::vector<S_tied>::const_iterator findTypeValue ( const std::vector<S_tied>& tied, const std::string& val ) const;
168     std::vector< std::pair<int, int> >::const_iterator findSlur ( const int xmlnum ) const;
169 
170     /// Lyrics handling by AC
171     void checkLyricBegin	 ( const std::vector<S_lyric>& lyrics );
172     void checkLyricEnd	 ( const std::vector<S_lyric>& lyrics );
173     std::vector<S_lyric>::const_iterator findValue ( const std::vector<S_lyric>& lyrics,
174                                                     const std::string& val ) const;
175     std::string lyricParams;
176 
177 
178 	static std::string alter2accident ( float alter );
179 
180 	protected:
181 		enum { kStemUndefined, kStemUp, kStemDown, kStemNone };
182 		enum { kLeaveChord=-1, kNoChord, kEnterChord } chordState;
183 
184 		virtual void visitStart( S_backup& elt);
185 		virtual void visitStart( S_barline& elt);
186 		virtual void visitStart( S_coda& elt);
187 		virtual void visitStart( S_direction& elt);
188 		virtual void visitStart( S_divisions& elt);
189 		virtual void visitStart( S_forward& elt);
190 		virtual void visitStart( S_measure& elt);
191 		virtual void visitStart( S_note& elt);
192 		virtual void visitStart( S_octave_shift& elt);
193 		virtual void visitStart( S_part& elt);
194 		virtual void visitStart( S_segno& elt);
195         virtual void visitStart( S_wedge& elt);
196 		virtual void visitStart( S_rehearsal& elt);
197         virtual void visitStart( S_attributes& elt);
198 
199 		virtual void visitEnd  ( S_direction& elt);
200 		virtual void visitEnd  ( S_ending& elt);
201 		virtual void visitEnd  ( S_key& elt);
202 		virtual void visitEnd  ( S_measure& elt);
203 		virtual void visitEnd  ( S_note& elt);
204 		virtual void visitEnd  ( S_repeat& elt);
205 		virtual void visitEnd  ( S_sound& elt);
206 		virtual void visitEnd  ( S_time& elt);
207 
208     std::string parseMetronome ( metronomevisitor &mv );
209 
210     bool findNextNote(const S_note& elt, ctree<xmlelement>::iterator &nextnote);
211     float getNoteDistanceFromStaffTop(const notevisitor& nv);
212 
213     rational durationInCue;
214 
215     std::map<int, float> fStaffDistance;
216 
217     bool fIgnoreWedgeWithOffset;
218 
219     // Internal Parsing facilities
220     float xPosFromTimePos(float default_x, float relative_x);           /// Infer X-Position from TimePosition
221 
222     public:
223 				 xmlpart2guido(bool generateComments, bool generateStem, bool generateBar=true);
~xmlpart2guido()224 		virtual ~xmlpart2guido() {}
225 
current()226 		Sguidoelement& current ()					{ return fStack.top(); }
227 		void	initialize (Sguidoelement seq, int staff, int guidostaff, int voice, bool notesonly, rational defaultTimeSign);
generatePositions(bool state)228 		void	generatePositions (bool state)		{ fGeneratePositions = state; }
getTimeSign()229 		const rational& getTimeSign () const		{ return fCurrentTimeSign; }
230         bool fHasLyrics;
hasLyrics()231         bool hasLyrics() const {return fHasLyrics;}
232     std::multimap<int,  std::pair< int, std::pair< rational, string > > > staffClefMap;
233 
234     std::string getClef(int staffIndex, rational pos, int measureNum);
235 
236     /// Containing default-x positions on a fCurrentVoicePosition (rational) of measure(int)
237     std::map< int, std::map< rational, std::vector<int> > > timePositions;
238 
239     void addPosYforNoteHead(const notevisitor& nv, Sxmlelement elt, Sguidoelement& tag, float offset);
240 
241 };
242 
243 
244 } // namespace MusicXML2
245 
246 
247 #endif
248