139
168
if(npartoffset > 0)
141
// Create new part...
142
// if there are several events that are moved outside the part, it will be recreated for each
143
// so the part _in_ the event will not be valid, ask the authority.
144
// Part* newPart = part->clone();
145
//Part* newPart = Canvas::part()->clone();
147
// newPart->setLenTick(newPart->lenTick() + npartoffset);
148
//audio->msgChangePart(part, newPart,false);
150
// modified = SC_PART_MODIFIED;
154
// Fixes posted "select and drag past end of part - crashing" bug
155
// for(iPart ip = editor->parts()->begin(); ip != editor->parts()->end(); ++ip)
157
// if(ip->second == part)
159
// editor->parts()->erase(ip);
164
// editor->parts()->add(newPart);
165
// audio->msgChangePart(part, newPart,false);
167
// if(parts2change.find(part) == parts2change.end())
168
// parts2change.insert(std::pair<Part*, Part*> (part, newPart));
169
iPartToChange ip2c = parts2change.find(part);
170
MusECore::iPartToChange ip2c = parts2change.find(part);
170
171
if(ip2c == parts2change.end())
172
PartToChange p2c = {0, npartoffset};
173
parts2change.insert(std::pair<Part*, PartToChange> (part, p2c));
173
MusECore::PartToChange p2c = {0, npartoffset};
174
parts2change.insert(std::pair<MusECore::Part*, MusECore::PartToChange> (part, p2c));
176
177
ip2c->second.xdiff = npartoffset;
179
//part = newPart; // reassign
180
//item->setPart(part);
181
//item->setEvent(newEvent);
183
//curPartId = curPart->sn();
188
for(iPartToChange ip2c = parts2change.begin(); ip2c != parts2change.end(); ++ip2c)
190
Part* opart = ip2c->first;
191
int diff = ip2c->second.xdiff;
193
Part* newPart = opart->clone();
195
newPart->setLenTick(newPart->lenTick() + diff);
197
modified = SC_PART_MODIFIED;
201
// Fixes posted "select and drag past end of part - crashing" bug
202
for(iPart ip = editor->parts()->begin(); ip != editor->parts()->end(); ++ip)
204
if(ip->second == opart)
206
editor->parts()->erase(ip);
211
editor->parts()->add(newPart);
212
// Indicate no undo, and do port controller values but not clone parts.
213
//audio->msgChangePart(opart, newPart, false);
214
audio->msgChangePart(opart, newPart, false, true, false);
216
ip2c->second.npart = newPart;
220
iPartToChange icp = parts2change.find(curPart);
221
if(icp != parts2change.end())
223
curPart = icp->second.npart;
224
curPartId = curPart->sn();
227
std::vector< CItem* > doneList;
228
typedef std::vector< CItem* >::iterator iDoneList;
230
for(iCItem ici = items.begin(); ici != items.end(); ++ici)
181
bool forbidden=false;
182
for(MusECore::iPartToChange ip2c = parts2change.begin(); ip2c != parts2change.end(); ++ip2c)
232
CItem* ci = ici->second;
234
// If this item's part is in the parts2change list, change the item's part to the new part.
235
Part* pt = ci->part();
236
iPartToChange ip2c = parts2change.find(pt);
237
if(ip2c != parts2change.end())
238
ci->setPart(ip2c->second.npart);
240
int x = ci->pos().x();
241
int y = ci->pos().y();
243
int ny = pitch2y(y2pitch(y) + dp);
244
QPoint newpos = raster(QPoint(nx, ny));
245
selectItem(ci, true);
248
for(idl = doneList.begin(); idl != doneList.end(); ++idl)
249
// This compares EventBase pointers to see if they're the same...
250
if((*idl)->event() == ci->event())
253
// Do not process if the event has already been processed (meaning it's an event in a clone part)...
254
//if(moveItem(ci, newpos, dtype))
255
if(idl != doneList.end())
256
// Just move the canvas item.
184
MusECore::Part* opart = ip2c->first;
185
if (opart->hasHiddenEvents())
260
// Currently moveItem always returns true.
261
if(moveItem(ci, newpos, dtype))
263
// Add the canvas item to the list of done items.
264
doneList.push_back(ci);
265
// Move the canvas item.
270
if(moving.size() == 1) {
271
itemReleased(curItem, newpos);
273
if(dtype == MOVE_COPY || dtype == MOVE_CLONE)
274
selectItem(ci, false);
195
std::vector< CItem* > doneList;
196
typedef std::vector< CItem* >::iterator iDoneList;
198
for(iCItem ici = items.begin(); ici != items.end(); ++ici)
200
CItem* ci = ici->second;
202
int x = ci->pos().x();
203
int y = ci->pos().y();
205
int ny = pitch2y(y2pitch(y) + dp);
206
QPoint newpos = raster(QPoint(nx, ny));
207
selectItem(ci, true);
210
for(idl = doneList.begin(); idl != doneList.end(); ++idl)
211
// This compares EventBase pointers to see if they're the same...
212
if((*idl)->event() == ci->event())
215
// Do not process if the event has already been processed (meaning it's an event in a clone part)...
216
if (idl == doneList.end())
218
operations.push_back(moveItem(ci, newpos, dtype));
219
doneList.push_back(ci);
223
if(moving.size() == 1)
224
itemReleased(curItem, newpos);
226
if(dtype == MOVE_COPY || dtype == MOVE_CLONE)
227
selectItem(ci, false);
230
for(MusECore::iPartToChange ip2c = parts2change.begin(); ip2c != parts2change.end(); ++ip2c)
232
MusECore::Part* opart = ip2c->first;
233
int diff = ip2c->second.xdiff;
235
schedule_resize_all_same_len_clone_parts(opart, opart->lenTick() + diff, operations);
242
return MusECore::Undo(); //return empty list
281
246
//---------------------------------------------------------
283
248
//---------------------------------------------------------
286
//bool DrumCanvas::moveItem(CItem* item, const QPoint& pos, DragType dtype, int* pflags)
287
bool DrumCanvas::moveItem(CItem* item, const QPoint& pos, DragType dtype)
250
MusECore::UndoOp DrumCanvas::moveItem(CItem* item, const QPoint& pos, DragType dtype)
289
252
DEvent* nevent = (DEvent*) item;
292
//MidiPart* part = (MidiPart*)Canvas::part(); // part can be dynamically recreated, ask the authority
293
MidiPart* part = (MidiPart*)nevent->part();
254
MusECore::MidiPart* part = (MusECore::MidiPart*)nevent->part();
295
Event event = nevent->event();
256
MusECore::Event event = nevent->event();
302
263
int npitch = y2pitch(pos.y());
303
Event newEvent = event.clone();
264
MusECore::Event newEvent = event.clone();
305
266
newEvent.setPitch(npitch);
306
267
newEvent.setTick(ntick);
313
int diff = newEvent.endTick()-part->lenTick();
314
if (diff > 0) // too short part? extend it
316
// if there are several events that are moved outside the part, it will be recreated for each
317
// so the part _in_ the event will not be valid, ask the authority.
318
//Part* newPart = part->clone();
319
MidiPart* newPart = (MidiPart*)Canvas::part()->clone();
320
newPart->setLenTick(newPart->lenTick()+diff);
321
audio->msgChangePart(Canvas::part(), newPart,false);
323
modified = SC_PART_MODIFIED;
324
part = newPart; // reassign
325
for(iPart i = editor->parts()->begin(); i != editor->parts()->end(); ++i)
327
if(i->second == Canvas::part())
329
editor->parts()->erase(i);
333
editor->parts()->add(part);
335
item->setEvent(newEvent);
337
curPartId = curPart->sn();
342
// msgAddEvent and msgChangeEvent (below) will set these, but set them here first?
343
//item->setPart(part);
344
item->setEvent(newEvent);
347
if(((int)newEvent.endTick() - (int)part->lenTick()) > 0)
348
printf("DrumCanvas::moveItem Error! New event end:%d exceeds length:%d of part:%s\n", newEvent.endTick(), part->lenTick(), part->name().toLatin1().constData());
350
if (dtype == MOVE_COPY || dtype == MOVE_CLONE) {
351
// Indicate no undo, and do not do port controller values and clone parts.
352
//audio->msgAddEvent(newEvent, part, false);
353
audio->msgAddEvent(newEvent, part, false, false, false);
356
// Indicate no undo, and do not do port controller values and clone parts.
357
//audio->msgChangeEvent(event, newEvent, part, false);
358
audio->msgChangeEvent(event, newEvent, part, false, false, false);
363
// *pflags = modified;
269
// Added by T356, removed by flo93: with operation groups, it happens that the
270
// part is too short right now, even if it's queued for being extended
271
//if(((int)newEvent.endTick() - (int)part->lenTick()) > 0)
272
// printf("DrumCanvas::moveItem Error! New event end:%d exceeds length:%d of part:%s\n", newEvent.endTick(), part->lenTick(), part->name().toLatin1().constData());
274
if (dtype == MOVE_COPY || dtype == MOVE_CLONE)
275
return MusECore::UndoOp(MusECore::UndoOp::AddEvent, newEvent, part, false, false);
277
return MusECore::UndoOp(MusECore::UndoOp::ModifyEvent, newEvent, event, part, false, false);
368
280
//---------------------------------------------------------
459
368
// Added by T356.
460
Part* part = nevent->part();
462
int modified=SC_EVENT_MODIFIED;
369
MusECore::Part* part = nevent->part();
370
MusECore::Undo operations;
463
371
int diff = event.endTick()-part->lenTick();
464
if (diff > 0) {// too short part? extend it
465
Part* newPart = part->clone();
466
newPart->setLenTick(newPart->lenTick()+diff);
467
// Indicate no undo, and do port controller values but not clone parts.
468
//audio->msgChangePart(part, newPart,false);
469
audio->msgChangePart(part, newPart, false, true, false);
470
modified=modified|SC_PART_MODIFIED;
471
part = newPart; // reassign
473
// Indicate no undo, and do not do port controller values and clone parts.
474
//audio->msgAddEvent(event, part,false);
475
audio->msgAddEvent(event, part, false, false, false);
476
song->endUndo(modified);
373
if (! ((diff > 0) && part->hasHiddenEvents()) ) //operation is allowed
375
operations.push_back(MusECore::UndoOp(MusECore::UndoOp::AddEvent,event, part, false, false));
377
if (diff > 0)// part must be extended?
379
schedule_resize_all_same_len_clone_parts(part, event.endTick(), operations);
380
printf("newItem: extending\n");
383
//else forbid action by not applying it
384
MusEGlobal::song->applyOperationGroup(operations);
385
songChanged(SC_EVENT_INSERTED); //this forces an update of the itemlist, which is neccessary
386
//to remove "forbidden" events from the list again
480
389
//---------------------------------------------------------
807
674
int spos = pos[0] - editor->rasterStep(pos[0]);
811
song->setPos(0, p, true, true, true); //CDW
677
MusECore::Pos p(spos,true);
678
MusEGlobal::song->setPos(0, p, true, true, true); //CDW
814
681
case CMD_RIGHT_NOSNAP:
816
Pos p(pos[0] + editor->rasterStep(pos[0]), true);
817
//if (p > part->tick())
819
song->setPos(0, p, true, true, true); //CDW
822
case CMD_MODIFY_VELOCITY:
825
w.setRange(0); //TODO: Make this work! Probably put _to & _toInit in ecanvas instead
828
int range = w.range(); // all, selected, looped, sel+loop
829
int rate = w.rateVal();
830
int offset = w.offsetVal();
833
for (iCItem k = items.begin(); k != items.end(); ++k) {
834
DEvent* devent = (DEvent*)(k->second);
835
Event event = devent->event();
836
if (event.type() != Note)
838
unsigned tick = event.tick();
839
bool selected = k->second->isSelected();
840
bool inLoop = (tick >= song->lpos()) && (tick < song->rpos());
843
|| (range == 1 && selected)
844
|| (range == 2 && inLoop)
845
|| (range == 3 && selected && inLoop)) {
846
int velo = event.velo();
848
//velo = rate ? (velo * 100) / rate : 64;
849
velo = (velo * rate) / 100;
856
if (event.velo() != velo) {
857
Event newEvent = event.clone();
858
newEvent.setVelo(velo);
859
// Indicate no undo, and do not do port controller values and clone parts.
860
//audio->msgChangeEvent(event, newEvent, devent->part(), false);
861
audio->msgChangeEvent(event, newEvent, devent->part(), false, false, false);
865
song->endUndo(SC_EVENT_MODIFIED);
683
MusECore::Pos p(pos[0] + editor->rasterStep(pos[0]), true);
684
MusEGlobal::song->setPos(0, p, true, true, true); //CDW
874
//---------------------------------------------------------
876
//---------------------------------------------------------
878
Q3TextDrag* DrumCanvas::getTextDrag(QWidget* parent)
880
//---------------------------------------------------
881
// generate event list from selected events
882
//---------------------------------------------------
885
unsigned startTick = MAXINT;
886
for (iCItem i = items.begin(); i != items.end(); ++i) {
887
if (!i->second->isSelected())
889
DEvent* ne = (DEvent*)(i->second);
890
Event e = ne->event();
891
if (startTick == MAXINT)
892
startTick = e.tick();
896
//---------------------------------------------------
897
// write events as XML into tmp file
898
//---------------------------------------------------
900
FILE* tmp = tmpfile();
902
fprintf(stderr, "EventCanvas::copy() fopen failed: %s\n",
909
for (ciEvent e = el.begin(); e != el.end(); ++e)
910
e->second.write(level, xml, -startTick);
912
//---------------------------------------------------
913
// read tmp file into QTextDrag Object
914
//---------------------------------------------------
918
if (fstat(fileno(tmp), &f_stat) == -1) {
919
fprintf(stderr, "EventCanvas::copy() fstat failes:<%s>\n",
924
int n = f_stat.st_size;
925
char* fbuf = (char*)mmap(0, n+1, PROT_READ|PROT_WRITE,
926
MAP_PRIVATE, fileno(tmp), 0);
928
Q3TextDrag* drag = new Q3TextDrag(QString(fbuf), parent);
929
drag->setSubtype("eventlist");
936
//---------------------------------------------------------
939
//---------------------------------------------------------
941
void DrumCanvas::copy()
943
QMimeData* md = getTextDrag();
946
QApplication::clipboard()->setMimeData(md, QClipboard::Clipboard);
950
//---------------------------------------------------------
952
//---------------------------------------------------------
954
int DrumCanvas::pasteAt(const QString& pt, int pos)
956
QByteArray ba = pt.toLatin1();
957
const char* p = ba.constData();
961
int modified = SC_EVENT_INSERTED;
965
Xml::Token token = xml.parse();
966
QString tag = xml.s1();
970
song->endUndo(modified);
973
if (tag == "event") {
978
int tick = e.tick() + pos - curPart->tick();
980
printf("DrumCanvas::pasteAt ERROR: trying to add event before current part!\n");
981
song->endUndo(SC_EVENT_INSERTED);
986
int diff = e.endTick() - curPart->lenTick();
987
if (diff > 0) {// too short part? extend it
988
Part* newPart = curPart->clone();
989
newPart->setLenTick(newPart->lenTick()+diff);
990
// Indicate no undo, and do port controller values but not clone parts.
991
audio->msgChangePart(curPart, newPart, false, true, false);
993
modified=modified|SC_PART_MODIFIED;
994
curPart = newPart; // reassign
997
// Indicate no undo, and do not do port controller values and clone parts.
998
audio->msgAddEvent(e, curPart, false, false, false);
1001
xml.unknown("DCanvas::pasteAt");
1011
//---------------------------------------------------------
1014
//---------------------------------------------------------
1016
void DrumCanvas::paste()
1018
QString stype("x-muse-eventlist");
1020
//QString s = QApplication::clipboard()->text(stype, QClipboard::Selection);
1021
QString s = QApplication::clipboard()->text(stype, QClipboard::Clipboard); // TODO CHECK Tim.
1023
pasteAt(s, song->cpos());
1026
693
//---------------------------------------------------------
1148
781
void DrumCanvas::mapChanged(int spitch, int dpitch)
1150
//TODO: Circumvent undo behaviour, since this isn't really a true change of the events,
1151
// but merely a change in pitch because the pitch relates to the order of the dlist.
1152
// Right now the sequencer spits out internalError: undoOp without startUndo() if start/stopundo is there, which is misleading
1153
// If start/stopundo is there, undo misbehaves since it doesn't undo but messes things up
1154
// Other solution: implement a specific undo-event for this (SC_DRUMMAP_MODIFIED or something) which undoes movement of
1157
std::vector< std::pair<Part*, Event*> > delete_events;
1158
std::vector< std::pair<Part*, Event> > add_events;
1160
typedef std::vector< std::pair<Part*, Event*> >::iterator idel_ev;
1161
typedef std::vector< std::pair<Part*, Event> >::iterator iadd_ev;
1164
class delete_events : public std::vector< Part*, Event* >
1167
idel_ev find(Part* p, Event* e)
1172
class add_events : public std::vector< Part*, Event >
1175
iadd_ev find(Part* p, Event& e)
1182
MidiTrackList* tracks = song->midis();
1183
for (ciMidiTrack t = tracks->begin(); t != tracks->end(); t++) {
1184
MidiTrack* curTrack = *t;
1185
if (curTrack->type() != Track::DRUM)
783
MusECore::Undo operations;
784
std::vector< std::pair<MusECore::Part*, MusECore::Event*> > delete_events;
785
std::vector< std::pair<MusECore::Part*, MusECore::Event> > add_events;
787
typedef std::vector< std::pair<MusECore::Part*, MusECore::Event*> >::iterator idel_ev;
788
typedef std::vector< std::pair<MusECore::Part*, MusECore::Event> >::iterator iadd_ev;
790
MusECore::MidiTrackList* tracks = MusEGlobal::song->midis();
791
for (MusECore::ciMidiTrack t = tracks->begin(); t != tracks->end(); t++) {
792
MusECore::MidiTrack* curTrack = *t;
793
if (curTrack->type() != MusECore::Track::DRUM)
1188
MidiPort* mp = &midiPorts[curTrack->outPort()];
1189
PartList* parts= curTrack->parts();
1190
for (iPart part = parts->begin(); part != parts->end(); ++part) {
1191
EventList* events = part->second->events();
1192
Part* thePart = part->second;
1193
for (iEvent i = events->begin(); i != events->end(); ++i) {
1194
Event event = i->second;
1195
if(event.type() != Controller && event.type() != Note)
796
MusECore::MidiPort* mp = &MusEGlobal::midiPorts[curTrack->outPort()];
797
MusECore::PartList* parts= curTrack->parts();
798
for (MusECore::iPart part = parts->begin(); part != parts->end(); ++part) {
799
MusECore::EventList* events = part->second->events();
800
MusECore::Part* thePart = part->second;
801
for (MusECore::iEvent i = events->begin(); i != events->end(); ++i) {
802
MusECore::Event event = i->second;
803
if(event.type() != MusECore::Controller && event.type() != MusECore::Note)
1197
805
int pitch = event.pitch();
1198
806
bool drc = false;
1199
807
// Is it a drum controller event, according to the track port's instrument?
1200
if(event.type() == Controller && mp->drumController(event.dataA()))
808
if(event.type() == MusECore::Controller && mp->drumController(event.dataA()))
1203
811
pitch = event.dataA() & 0x7f;
1206
814
if (pitch == spitch) {
1207
Event* spitch_event = &(i->second);
1208
delete_events.push_back(std::pair<Part*, Event*>(thePart, spitch_event));
1209
Event newEvent = spitch_event->clone();
815
MusECore::Event* spitch_event = &(i->second);
816
delete_events.push_back(std::pair<MusECore::Part*, MusECore::Event*>(thePart, spitch_event));
817
MusECore::Event newEvent = spitch_event->clone();
1211
819
newEvent.setA((newEvent.dataA() & ~0xff) | dpitch);
1213
821
newEvent.setPitch(dpitch);
1214
add_events.push_back(std::pair<Part*, Event>(thePart, newEvent));
822
add_events.push_back(std::pair<MusECore::Part*, MusECore::Event>(thePart, newEvent));
1216
824
else if (pitch == dpitch) {
1217
Event* dpitch_event = &(i->second);
1218
delete_events.push_back(std::pair<Part*, Event*>(thePart, dpitch_event));
1219
Event newEvent = dpitch_event->clone();
825
MusECore::Event* dpitch_event = &(i->second);
826
delete_events.push_back(std::pair<MusECore::Part*, MusECore::Event*>(thePart, dpitch_event));
827
MusECore::Event newEvent = dpitch_event->clone();
1221
829
newEvent.setA((newEvent.dataA() & ~0xff) | spitch);
1223
831
newEvent.setPitch(spitch);
1224
add_events.push_back(std::pair<Part*, Event>(thePart, newEvent));
832
add_events.push_back(std::pair<MusECore::Part*, MusECore::Event>(thePart, newEvent));
1231
838
for (idel_ev i = delete_events.begin(); i != delete_events.end(); i++) {
1232
//std::pair<Part*, Event*> pair = *i;
1233
//Part* thePart = pair.first;
1234
//Event* theEvent = pair.second;
1235
Part* thePart = (*i).first;
1236
Event* theEvent = (*i).second;
1237
// Indicate no undo, and do port controller values but not clone parts.
1238
//audio->msgDeleteEvent(*theEvent, thePart, false);
1239
audio->msgDeleteEvent(*theEvent, thePart, false, true, false);
839
MusECore::Part* thePart = (*i).first;
840
MusECore::Event* theEvent = (*i).second;
841
operations.push_back(MusECore::UndoOp(MusECore::UndoOp::DeleteEvent, *theEvent, thePart, true, false));
1242
DrumMap dm = drumMap[spitch];
1243
drumMap[spitch] = drumMap[dpitch];
1244
drumMap[dpitch] = dm;
1245
drumInmap[int(drumMap[spitch].enote)] = spitch;
1246
drumOutmap[int(drumMap[int(spitch)].anote)] = spitch;
1247
drumInmap[int(drumMap[int(dpitch)].enote)] = dpitch;
1248
drumOutmap[int(drumMap[int(dpitch)].anote)] = dpitch;
844
MusECore::DrumMap dm = MusEGlobal::drumMap[spitch];
845
MusEGlobal::drumMap[spitch] = MusEGlobal::drumMap[dpitch];
846
MusEGlobal::drumMap[dpitch] = dm;
847
MusEGlobal::drumInmap[int(MusEGlobal::drumMap[spitch].enote)] = spitch;
848
MusEGlobal::drumOutmap[int(MusEGlobal::drumMap[int(spitch)].anote)] = spitch;
849
MusEGlobal::drumInmap[int(MusEGlobal::drumMap[int(dpitch)].enote)] = dpitch;
850
MusEGlobal::drumOutmap[int(MusEGlobal::drumMap[int(dpitch)].anote)] = dpitch;
1250
852
for (iadd_ev i = add_events.begin(); i != add_events.end(); i++) {
1251
//std::pair<Part*, Event> pair = *i;
1252
//Part* thePart = pair.first;
1253
//Event& theEvent = pair.second;
1254
Part* thePart = (*i).first;
1255
Event& theEvent = (*i).second;
1256
// Indicate no undo, and do port controller values but not clone parts.
1257
//audio->msgAddEvent(theEvent, thePart, false);
1258
audio->msgAddEvent(theEvent, thePart, false, true, false);
853
MusECore::Part* thePart = (*i).first;
854
MusECore::Event& theEvent = (*i).second;
855
operations.push_back(MusECore::UndoOp(MusECore::UndoOp::AddEvent, theEvent, thePart, true, false));
1261
song->endUndo(SC_EVENT_MODIFIED);
1262
song->update(SC_DRUMMAP);
858
MusEGlobal::song->applyOperationGroup(operations, false); // do not indicate undo
859
MusEGlobal::song->update(SC_DRUMMAP); //this update is neccessary, as it's not handled by applyOperationGroup()
1265
862
//---------------------------------------------------------