1 //=============================================================================
2 //  MuseScore
3 //  Music Composition & Notation
4 //
5 //  Copyright (C) 2019 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 //  as published by the Free Software Foundation and appearing in
10 //  the file LICENCE.GPL
11 //=============================================================================
12 
13 #include "score.h"
14 #include "cursor.h"
15 #include "elements.h"
16 #include "libmscore/instrtemplate.h"
17 #include "libmscore/measure.h"
18 #include "libmscore/score.h"
19 #include "libmscore/segment.h"
20 #include "libmscore/text.h"
21 
22 #include "musescore.h"
23 #include "../qmlpluginengine.h"
24 
25 namespace Ms {
26 namespace PluginAPI {
27 
28 //---------------------------------------------------------
29 //   Score::newCursor
30 //---------------------------------------------------------
31 
newCursor()32 Cursor* Score::newCursor()
33       {
34       return new Cursor(score());
35       }
36 
37 //---------------------------------------------------------
38 //   Score::addText
39 ///   \brief Adds a header text to the score.
40 ///   \param type One of the following values:
41 ///   - "title"
42 ///   - "subtitle"
43 ///   - "composer"
44 ///   - "lyricist"
45 ///   - Any other value corresponds to default text style.
46 ///   \param txt Text to be added.
47 //---------------------------------------------------------
48 
addText(const QString & type,const QString & txt)49 void Score::addText(const QString& type, const QString& txt)
50       {
51       MeasureBase* measure = score()->first();
52       if (!measure || !measure->isVBox()) {
53             score()->insertMeasure(ElementType::VBOX, measure);
54             measure = score()->first();
55             }
56       Tid tid = Tid::DEFAULT;
57       if (type == "title")
58             tid = Tid::TITLE;
59       else if (type == "subtitle")
60             tid = Tid::SUBTITLE;
61       else if (type == "composer")
62             tid = Tid::COMPOSER;
63       else if (type == "lyricist")
64             tid = Tid::POET;
65 
66       Ms::Text* text = new Ms::Text(score(), tid);
67       text->setParent(measure);
68       text->setXmlText(txt);
69       score()->undoAddElement(text);
70       }
71 
72 //---------------------------------------------------------
73 //   defaultInstrTemplate
74 //---------------------------------------------------------
75 
defaultInstrTemplate()76 static const InstrumentTemplate* defaultInstrTemplate()
77       {
78       static InstrumentTemplate defaultInstrument;
79       if (defaultInstrument.channel.empty()) {
80             Channel a;
81             a.setChorus(0);
82             a.setReverb(0);
83             a.setName(Channel::DEFAULT_NAME);
84             a.setBank(0);
85             a.setVolume(90);
86             a.setPan(0);
87             defaultInstrument.channel.append(a);
88             }
89       return &defaultInstrument;
90       }
91 
92 //---------------------------------------------------------
93 //   instrTemplateFromName
94 //---------------------------------------------------------
95 
instrTemplateFromName(const QString & name)96 const InstrumentTemplate* Score::instrTemplateFromName(const QString& name)
97       {
98       const InstrumentTemplate* t = searchTemplate(name);
99       if (!t) {
100             qWarning("<%s> not found", qPrintable(name));
101             t = defaultInstrTemplate();
102             }
103       return t;
104       }
105 
106 //---------------------------------------------------------
107 //   Score::appendPart
108 //---------------------------------------------------------
109 
appendPart(const QString & instrumentId)110 void Score::appendPart(const QString& instrumentId)
111       {
112       const InstrumentTemplate* t = searchTemplate(instrumentId);
113 
114       if (!t) {
115             qWarning("appendPart: <%s> not found", qPrintable(instrumentId));
116             t = defaultInstrTemplate();
117             }
118 
119       score()->appendPart(t);
120       }
121 
122 //---------------------------------------------------------
123 //   Score::appendPartByMusicXmlId
124 //---------------------------------------------------------
125 
appendPartByMusicXmlId(const QString & instrumentMusicXmlId)126 void Score::appendPartByMusicXmlId(const QString& instrumentMusicXmlId)
127       {
128       const InstrumentTemplate* t = searchTemplateForMusicXmlId(instrumentMusicXmlId);
129 
130       if (!t) {
131             qWarning("appendPart: <%s> not found", qPrintable(instrumentMusicXmlId));
132             t = defaultInstrTemplate();
133             }
134 
135       score()->appendPart(t);
136       }
137 
138 //---------------------------------------------------------
139 //   Score::firstSegment
140 //---------------------------------------------------------
141 
firstSegment()142 Segment* Score::firstSegment()
143       {
144       return wrap<Segment>(score()->firstSegment(Ms::SegmentType::All), Ownership::SCORE);
145       }
146 
147 //---------------------------------------------------------
148 //   Score::lastSegment
149 //---------------------------------------------------------
150 
lastSegment()151 Segment* Score::lastSegment()
152       {
153       return wrap<Segment>(score()->lastSegment(), Ownership::SCORE);
154       }
155 
156 //---------------------------------------------------------
157 //   Score::firstMeasure
158 //---------------------------------------------------------
159 
firstMeasure()160 Measure* Score::firstMeasure()
161       {
162       return wrap<Measure>(score()->firstMeasure(), Ownership::SCORE);
163       }
164 
165 //---------------------------------------------------------
166 //   Score::firstMeasureMM
167 //---------------------------------------------------------
168 
firstMeasureMM()169 Measure* Score::firstMeasureMM()
170       {
171       return wrap<Measure>(score()->firstMeasureMM(), Ownership::SCORE);
172       }
173 
174 //---------------------------------------------------------
175 //   Score::lastMeasure
176 //---------------------------------------------------------
177 
lastMeasure()178 Measure* Score::lastMeasure()
179       {
180       return wrap<Measure>(score()->lastMeasure(), Ownership::SCORE);
181       }
182 //---------------------------------------------------------
183 //   Score::firstMeasureMM
184 //---------------------------------------------------------
185 
lastMeasureMM()186 Measure* Score::lastMeasureMM()
187       {
188       return wrap<Measure>(score()->lastMeasureMM(), Ownership::SCORE);
189       }
190 
191 //---------------------------------------------------------
192 //   Score::staves
193 //---------------------------------------------------------
194 
staves()195 QQmlListProperty<Staff> Score::staves()
196       {
197       return wrapContainerProperty<Staff>(this, score()->staves());
198       }
199 
200 //---------------------------------------------------------
201 //   Score::startCmd
202 //---------------------------------------------------------
203 
startCmd()204 void Score::startCmd()
205       {
206       // TODO: should better use qmlEngine(this) (need to set context for wrappers then)
207       const QmlPluginEngine* engine = mscore->getPluginEngine();
208       if (engine->inScoreChangeActionHandler()) {
209             // Plugin-originated changes made while handling onScoreStateChanged
210             // should be grouped together with the action which caused this change
211             // (if it was caused by actual score change).
212             if (!score()->undoStack()->active())
213                   score()->undoStack()->reopen();
214             }
215       else {
216             score()->startCmd();
217             }
218       }
219 }
220 }
221