Line data Source code
1 : /*
2 : * SPDX-License-Identifier: GPL-3.0-only
3 : * MuseScore-Studio-CLA-applies
4 : *
5 : * MuseScore Studio
6 : * Music Composition & Notation
7 : *
8 : * Copyright (C) 2021 MuseScore Limited and others
9 : *
10 : * This program is free software: you can redistribute it and/or modify
11 : * it under the terms of the GNU General Public License version 3 as
12 : * published by the Free Software Foundation.
13 : *
14 : * This program is distributed in the hope that it will be useful,
15 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 : * GNU General Public License for more details.
18 : *
19 : * You should have received a copy of the GNU General Public License
20 : * along with this program. If not, see <https://www.gnu.org/licenses/>.
21 : */
22 :
23 : #include "playevent.h"
24 :
25 : #include "engraving/dom/note.h"
26 : #include "engraving/dom/score.h"
27 :
28 : #include "engraving/editing/editnote.h"
29 :
30 : // api
31 : #include "elements.h"
32 :
33 : #include "log.h"
34 :
35 : using namespace mu::engraving::apiv1;
36 :
37 : //---------------------------------------------------------
38 : // PlayEvent::setPitch
39 : //---------------------------------------------------------
40 :
41 0 : void PlayEvent::setPitch(int v)
42 : {
43 0 : if (!ne || ne->pitch() == v) {
44 0 : return; // Value hasn't changed so no need to do more.
45 : }
46 0 : if (!parentNote) {
47 : // We can't check against a parent note we don't have so
48 : // we check against the absolute range. When this NoteEvent
49 : // is added to an actual note the range should be checked
50 : // again.
51 0 : if (pitchIsValid(abs(v))) {
52 0 : ne->setPitch(v); // Set new ontTime value
53 : } else {
54 0 : LOGW("PluginAPI::PlayEvent::setPitch: Invalid relative pitch value when added to parent note pitch.");
55 0 : return;
56 : }
57 : } else {
58 0 : mu::engraving::Score* score = parentNote->note()->score();
59 0 : if (!score) {
60 0 : LOGW("PluginAPI::PlayEvent::setOntime: A score is required.");
61 0 : return;
62 : }
63 0 : int parentPitch = parentNote->note()->pitch();
64 : // A NoteEvent's pitch is actually summed with the parent pitch. This
65 : // check ensures that it doesn't result with an illegal pitch.
66 0 : if (!pitchIsValid(v + parentPitch)) {
67 0 : LOGW("PluginAPI::PlayEvent::setPitch: Invalid relative pitch value when added to parent note pitch.");
68 0 : return;
69 : }
70 0 : mu::engraving::NoteEvent e = *ne; // Make copy of NoteEvent value
71 0 : e.setPitch(v); // Set new ontTime value
72 0 : score->undo(new ChangeNoteEvent(parentNote->note(), ne, e));
73 : }
74 : }
75 :
76 : //---------------------------------------------------------
77 : // PlayEvent::setOntime
78 : //---------------------------------------------------------
79 :
80 0 : void PlayEvent::setOntime(int v)
81 : {
82 0 : if (!ne || ne->ontime() == v) {
83 0 : return; // Value hasn't changed so no need to do more.
84 : }
85 : // Note that onTime can be negative so a note can play earlier.
86 : // See: https://musescore.org/en/node/74651
87 0 : if (v < -2 * mu::engraving::NoteEvent::NOTE_LENGTH || v > 2 * mu::engraving::NoteEvent::NOTE_LENGTH) {
88 0 : LOGW("PluginAPI::PlayEvent::setOntime: Invalid value.");
89 0 : return;
90 : }
91 0 : if (!parentNote) {
92 : // Unowned floating value in QML context.
93 0 : ne->setOntime(v); // Set new ontTime value
94 : } else {
95 0 : mu::engraving::Score* score = parentNote->note()->score();
96 0 : if (!score) {
97 0 : LOGW("PluginAPI::PlayEvent::setOntime: A score is required.");
98 0 : return;
99 : }
100 0 : mu::engraving::NoteEvent e = *ne; // Make copy of NoteEvent value
101 0 : e.setOntime(v); // Set new ontTime value
102 0 : score->undo(new ChangeNoteEvent(parentNote->note(), ne, e));
103 : }
104 : }
105 :
106 : //---------------------------------------------------------
107 : // PlayEvent::setLen
108 : //---------------------------------------------------------
109 :
110 0 : void PlayEvent::setLen(int v)
111 : {
112 0 : if (!ne || ne->len() == v) {
113 0 : return; // Value hasn't changed so no need to do more.
114 : }
115 0 : if (v <= 0 || v > 2 * mu::engraving::NoteEvent::NOTE_LENGTH) {
116 0 : LOGW("PluginAPI::PlayEvent::setLen: Invalid value.");
117 0 : return;
118 : }
119 0 : if (!parentNote) {
120 0 : ne->setLen(v); // Set new length value
121 : } else {
122 0 : mu::engraving::Score* score = parentNote->note()->score();
123 0 : if (!score) {
124 0 : LOGW("PluginAPI::PlayEvent::setLen: A score is required.");
125 0 : return;
126 : }
127 0 : mu::engraving::NoteEvent e = *ne; // Make copy of NoteEvent value
128 0 : e.setLen(v); // Set new length value
129 0 : score->undo(new ChangeNoteEvent(parentNote->note(), ne, e));
130 : }
131 : }
132 :
133 : //---------------------------------------------------------
134 : // QmlPlayEventsListAccess::clear
135 : //---------------------------------------------------------
136 :
137 0 : void QmlPlayEventsListAccess::clear(QQmlListProperty<PlayEvent>* l)
138 : {
139 0 : NoteEventList* plist = static_cast<NoteEventList*>(l->data);
140 0 : Note* papinote = static_cast<Note*>(l->object);
141 :
142 : // Get a copy of the current list contents.
143 0 : NoteEventList nel = *plist;
144 :
145 : // Modify the list copy.
146 0 : nel.clear();
147 :
148 : // Set up the undo operation for the change.
149 0 : mu::engraving::Score* score = papinote->note()->score();
150 0 : score->undo(new ChangeNoteEventList(papinote->note(), nel));
151 0 : }
152 :
153 : //---------------------------------------------------------
154 : // QmlPlayEventsListAccess::append
155 : //---------------------------------------------------------
156 :
157 0 : void QmlPlayEventsListAccess::append(QQmlListProperty<PlayEvent>* l, PlayEvent* v)
158 : {
159 0 : NoteEventList* plist = static_cast<NoteEventList*>(l->data);
160 0 : Note* papinote = static_cast<Note*>(l->object);
161 :
162 : // Get a copy of the current list contents.
163 0 : NoteEventList nel = *plist;
164 :
165 : // Modify the list copy.
166 0 : nel.push_back(v->getNoteEvent());
167 :
168 : // Set up the undo operation for the change.
169 0 : mu::engraving::Score* score = papinote->note()->score();
170 0 : score->undo(new ChangeNoteEventList(papinote->note(), nel));
171 0 : }
|