1 //=============================================================================
2 // MusE Score
3 // Linux Music Score Editor
4 //
5 // Copyright (C) 2010 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 #include "drumroll.h"
21 #include "config.h"
22 #include "piano.h"
23 #include "ruler.h"
24 #include "drumview.h"
25 #include "libmscore/staff.h"
26 #include "libmscore/score.h"
27 #include "libmscore/measure.h"
28 #include "libmscore/note.h"
29 #include "awl/pitchlabel.h"
30 #include "awl/pitchedit.h"
31 #include "awl/poslabel.h"
32 #include "musescore.h"
33 #include "libmscore/undo.h"
34 #include "libmscore/part.h"
35 #include "libmscore/instrument.h"
36 #include "seq.h"
37 #include "preferences.h"
38
39 namespace Ms {
40
41 //---------------------------------------------------------
42 // DrumrollEditor
43 //---------------------------------------------------------
44
DrumrollEditor(QWidget * parent)45 DrumrollEditor::DrumrollEditor(QWidget* parent)
46 : QMainWindow(parent)
47 {
48 setObjectName("Drumroll");
49 setWindowTitle(QString("MuseScore"));
50 // setIconSize(QSize(preferences.iconWidth, preferences.iconHeight));
51
52 QWidget* mainWidget = new QWidget;
53 QGridLayout* layout = new QGridLayout;
54 mainWidget->setLayout(layout);
55 layout->setSpacing(0);
56
57 QToolBar* tb = addToolBar("Toolbar 1");
58 if (qApp->layoutDirection() == Qt::LayoutDirection::LeftToRight) {
59 tb->addAction(getAction("undo"));
60 tb->addAction(getAction("redo"));
61 }
62 else {
63 tb->addAction(getAction("redo"));
64 tb->addAction(getAction("undo"));
65 }
66 tb->addSeparator();
67 #ifdef HAS_MIDI
68 tb->addAction(getAction("midi-on"));
69 #endif
70 QAction* a = getAction("follow");
71 a->setCheckable(true);
72 a->setChecked(preferences.getBool(PREF_APP_PLAYBACK_FOLLOWSONG));
73
74 tb->addAction(a);
75
76 tb->addSeparator();
77 tb->addAction(getAction("rewind"));
78 tb->addAction(getAction("play"));
79 tb->addSeparator();
80
81 //-------------
82 tb = addToolBar("Toolbar 2");
83 layout->addWidget(tb, 1, 0, 1, 2);
84
85 for (int i = 0; i < VOICES; ++i) {
86 QToolButton* b = new QToolButton(this);
87 b->setToolButtonStyle(Qt::ToolButtonTextOnly);
88 QPalette p(b->palette());
89 p.setColor(QPalette::Base, MScore::selectColor[i]);
90 b->setPalette(p);
91 QAction* aa = getAction(voiceActions[i]);
92 b->setDefaultAction(aa);
93 tb->addWidget(b);
94 }
95
96 tb->addSeparator();
97 tb->addWidget(new QLabel(tr("Cursor:")));
98 pos = new Awl::PosLabel;
99 tb->addWidget(pos);
100 Awl::PitchLabel* pl = new Awl::PitchLabel();
101 tb->addWidget(pl);
102
103 tb->addSeparator();
104 tb->addWidget(new QLabel(tr("Velocity:")));
105 veloType = new QComboBox;
106 veloType->addItem(tr("Offset"), int(Note::ValueType::OFFSET_VAL));
107 veloType->addItem(tr("User"), int(Note::ValueType::USER_VAL));
108 tb->addWidget(veloType);
109
110 velocity = new QSpinBox;
111 velocity->setRange(-1, 127);
112 velocity->setSpecialValueText("--");
113 velocity->setReadOnly(true);
114 tb->addWidget(velocity);
115
116 tb->addWidget(new QLabel(tr("Pitch:")));
117 pitch = new Awl::PitchEdit;
118 pitch->setReadOnly(true);
119 tb->addWidget(pitch);
120
121 double xmag = .1;
122 gv = new DrumView;
123 gv->scale(xmag, 1.0);
124 layout->addWidget(gv, 3, 1);
125
126 ruler = new Ruler;
127 ruler->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
128 ruler->setFixedHeight(rulerHeight);
129 ruler->setMag(xmag, 1.0);
130
131 layout->addWidget(ruler, 2, 1);
132
133 Piano* piano = new Piano;
134 piano->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding);
135 piano->setFixedWidth(pianoWidth);
136 layout->addWidget(piano, 3, 0);
137
138 setCentralWidget(mainWidget);
139
140 connect(gv->verticalScrollBar(), SIGNAL(valueChanged(int)), piano, SLOT(setYpos(int)));
141 connect(gv->horizontalScrollBar(), SIGNAL(valueChanged(int)), ruler, SLOT(setXpos(int)));
142 connect(gv, SIGNAL(xposChanged(int)), ruler, SLOT(setXpos(int)));
143 connect(gv, SIGNAL(magChanged(double,double)), ruler, SLOT(setMag(double,double)));
144 connect(gv, SIGNAL(magChanged(double,double)), piano, SLOT(setMag(double,double)));
145 connect(gv, SIGNAL(pitchChanged(int)), pl, SLOT(setPitch(int)));
146 connect(gv, SIGNAL(pitchChanged(int)), piano, SLOT(setPitch(int)));
147 connect(piano, SIGNAL(pitchChanged(int)), pl, SLOT(setPitch(int)));
148 connect(gv, SIGNAL(posChanged(const Pos&)), pos, SLOT(setValue(const Pos&)));
149 connect(gv, SIGNAL(posChanged(const Pos&)), ruler, SLOT(setPos(const Pos&)));
150 connect(ruler, SIGNAL(posChanged(const Pos&)), pos, SLOT(setValue(const Pos&)));
151 connect(ruler, SIGNAL(locatorMoved(int)), SLOT(moveLocator(int)));
152 connect(veloType, SIGNAL(activated(int)), SLOT(veloTypeChanged(int)));
153 connect(velocity, SIGNAL(valueChanged(int)), SLOT(velocityChanged(int)));
154 connect(gv->scene(), SIGNAL(selectionChanged()), SLOT(selectionChanged()));
155 connect(piano, SIGNAL(keyPressed(int)), SLOT(keyPressed(int)));
156 connect(piano, SIGNAL(keyReleased(int)), SLOT(keyReleased(int)));
157 resize(800, 400);
158
159 QActionGroup* ag = new QActionGroup(this);
160 a = new QAction(this);
161 a->setData("delete");
162 a->setShortcut(Qt::Key_Delete);
163 ag->addAction(a);
164 addActions(ag->actions());
165 connect(ag, SIGNAL(triggered(QAction*)), SLOT(cmd(QAction*)));
166
167 readSettings();
168 }
169
170 //---------------------------------------------------------
171 // writeSettings
172 //---------------------------------------------------------
173
writeSettings()174 void DrumrollEditor::writeSettings()
175 {
176 MuseScore::saveGeometry(this);
177 }
178
179 //---------------------------------------------------------
180 // readSettings
181 //---------------------------------------------------------
182
readSettings()183 void DrumrollEditor::readSettings()
184 {
185 MuseScore::restoreGeometry(this);
186 }
187
188 //---------------------------------------------------------
189 // setStaff
190 //---------------------------------------------------------
191
setStaff(Staff * st)192 void DrumrollEditor::setStaff(Staff* st)
193 {
194 staff = st;
195 _score = staff->score();
196 setWindowTitle(tr("<%1> Staff: %2").arg(_score->masterScore()->fileInfo()->completeBaseName()).arg(st->idx()));
197 TempoMap* tl = _score->tempomap();
198 TimeSigMap* sl = _score->sigmap();
199 for (int i = 0; i < 3; ++i)
200 locator[i].setContext(tl, sl);
201
202 locator[0].setTick(480 * 5 + 240); // some random test values
203 locator[1].setTick(480 * 3 + 240);
204 locator[2].setTick(480 * 12 + 240);
205
206 gv->setStaff(staff, locator);
207 ruler->setScore(_score, locator);
208 pos->setContext(tl, sl);
209 updateSelection();
210 }
211
212 //---------------------------------------------------------
213 // updateSelection
214 //---------------------------------------------------------
215
updateSelection()216 void DrumrollEditor::updateSelection()
217 {
218 QList<QGraphicsItem*> items = gv->scene()->selectedItems();
219 if (items.size() == 1) {
220 QGraphicsItem* item = items[0];
221 Note* note = static_cast<Note*>(item->data(0).value<void*>());
222 pitch->setEnabled(true);
223 pitch->setValue(note->pitch());
224 veloType->setEnabled(true);
225 velocity->setEnabled(true);
226 updateVelocity(note);
227 }
228 else if (items.size() == 0) {
229 velocity->setValue(0);
230 velocity->setEnabled(false);
231 pitch->setValue(0);
232 pitch->setEnabled(false);
233 veloType->setEnabled(false);
234 veloType->setCurrentIndex(int(Note::ValueType::OFFSET_VAL));
235 }
236 else {
237 velocity->setEnabled(true);
238 velocity->setValue(0);
239 velocity->setReadOnly(false);
240 pitch->setEnabled(true);
241 pitch->setDeltaMode(true);
242 pitch->setValue(0);
243 veloType->setEnabled(true);
244 veloType->setCurrentIndex(int(Note::ValueType::OFFSET_VAL));
245 }
246 }
247
248 //---------------------------------------------------------
249 // selectionChanged
250 //---------------------------------------------------------
251
selectionChanged()252 void DrumrollEditor::selectionChanged()
253 {
254 updateSelection();
255 // _score->blockSignals(true);
256 QList<QGraphicsItem*> items = gv->scene()->selectedItems();
257 if (items.size() == 1) {
258 QGraphicsItem* item = items[0];
259 Note* note = static_cast<Note*>(item->data(0).value<void*>());
260 if (note)
261 _score->select(note, SelectType::SINGLE, 0);
262 }
263 else if (items.size() == 0) {
264 _score->select(0, SelectType::SINGLE, 0);
265 }
266 else {
267 _score->select(0, SelectType::SINGLE, 0);
268 foreach(QGraphicsItem* item, items) {
269 Note* note = static_cast<Note*>(item->data(0).value<void*>());
270 if (note)
271 _score->select(note, SelectType::ADD, 0);
272 }
273 }
274 _score->setUpdateAll();
275 _score->update();
276 // _score->blockSignals(false);
277 }
278
279 //---------------------------------------------------------
280 // changeSelection
281 //---------------------------------------------------------
282
changeSelection(SelState)283 void DrumrollEditor::changeSelection(SelState)
284 {
285 gv->scene()->blockSignals(true);
286 gv->scene()->clearSelection();
287 QList<QGraphicsItem*> il = gv->scene()->items();
288 foreach(QGraphicsItem* item, il) {
289 Note* note = static_cast<Note*>(item->data(0).value<void*>());
290 if (note)
291 item->setSelected(note->selected());
292 }
293 gv->scene()->blockSignals(false);
294 }
295
296 //---------------------------------------------------------
297 // veloTypeChanged
298 //---------------------------------------------------------
299
veloTypeChanged(int val)300 void DrumrollEditor::veloTypeChanged(int val)
301 {
302 QList<QGraphicsItem*> items = gv->scene()->selectedItems();
303 if (items.size() != 1)
304 return;
305 QGraphicsItem* item = items[0];
306 Note* note = (Note*)item->data(0).value<void*>();
307 if ((note == 0) || (Note::ValueType(val) == note->veloType()))
308 return;
309
310 _score->startCmd();
311 _score->undo(new ChangeVelocity(note, Note::ValueType(val), note->veloOffset()));
312 _score->endCmd();
313 updateVelocity(note);
314 }
315
316 //---------------------------------------------------------
317 // updateVelocity
318 //---------------------------------------------------------
319
updateVelocity(Note * note)320 void DrumrollEditor::updateVelocity(Note* note)
321 {
322 Note::ValueType vt = note->veloType();
323 if (vt != Note::ValueType(veloType->currentIndex())) {
324 veloType->setCurrentIndex(int(vt));
325 switch(vt) {
326 case Note::ValueType::USER_VAL:
327 velocity->setReadOnly(false);
328 velocity->setSuffix("");
329 velocity->setRange(0, 127);
330 break;
331 case Note::ValueType::OFFSET_VAL:
332 velocity->setReadOnly(false);
333 velocity->setSuffix("%");
334 velocity->setRange(-200, 200);
335 break;
336 }
337 }
338 velocity->setValue(note->veloOffset());
339 }
340
341 //---------------------------------------------------------
342 // velocityChanged
343 //---------------------------------------------------------
344
velocityChanged(int val)345 void DrumrollEditor::velocityChanged(int val)
346 {
347 QList<QGraphicsItem*> items = gv->scene()->selectedItems();
348 if (items.size() != 1)
349 return;
350 QGraphicsItem* item = items[0];
351 Note* note = (Note*)item->data(0).value<void*>();
352 if (note == 0)
353 return;
354 Note::ValueType vt = note->veloType();
355
356 if (vt == Note::ValueType::OFFSET_VAL)
357 return;
358
359 _score->startCmd();
360 _score->undo(new ChangeVelocity(note, vt, val));
361 _score->endCmd();
362 }
363
364 //---------------------------------------------------------
365 // keyPressed
366 //---------------------------------------------------------
367
keyPressed(int p)368 void DrumrollEditor::keyPressed(int p)
369 {
370 seq->startNote(staff->part()->instrument()->channel(0)->channel(), p, 80, 0, 0.0); //tick?
371 }
372
373 //---------------------------------------------------------
374 // keyReleased
375 //---------------------------------------------------------
376
keyReleased(int)377 void DrumrollEditor::keyReleased(int /*pitch*/)
378 {
379 seq->stopNotes();
380 }
381
382 //---------------------------------------------------------
383 // heartBeat
384 //---------------------------------------------------------
385
heartBeat(Seq * s)386 void DrumrollEditor::heartBeat(Seq* s)
387 {
388 unsigned t = s->getCurTick();
389 if (locator[0].tick() != t) {
390 locator[0].setTick(t);
391 gv->moveLocator(0);
392 ruler->update();
393 if (preferences.getBool(PREF_APP_PLAYBACK_FOLLOWSONG))
394 gv->ensureVisible(t);
395 }
396 }
397
398 //---------------------------------------------------------
399 // moveLocator
400 //---------------------------------------------------------
401
moveLocator(int i)402 void DrumrollEditor::moveLocator(int i)
403 {
404 if (locator[i].valid()) {
405 seq->seek(locator[i].tick());
406 gv->moveLocator(i);
407 }
408 }
409
410 //---------------------------------------------------------
411 // cmd
412 //---------------------------------------------------------
413
cmd(QAction * a)414 void DrumrollEditor::cmd(QAction* a)
415 {
416 score()->startCmd();
417 if (a->data() == "delete") {
418 QList<QGraphicsItem*> items = gv->items();
419 foreach(QGraphicsItem* item, items) {
420 Note* note = static_cast<Note*>(item->data(0).value<void*>());
421 if (note) {
422 score()->deleteItem(note);
423 }
424 }
425 }
426
427 gv->setStaff(staff, locator);
428 }
429 }
430
431