247
298
//---------------------------------------------------------
249
MusECore::UndoOp DrumCanvas::moveItem(CItem* item, const QPoint& pos, DragType dtype)
300
bool DrumCanvas::moveItem(MusECore::Undo& operations, CItem* item, const QPoint& pos, DragType dtype)
251
302
DEvent* nevent = (DEvent*) item;
253
MusECore::MidiPart* part = (MusECore::MidiPart*)nevent->part();
304
MusECore::MidiPart* part = (MusECore::MidiPart*)nevent->part();
305
MusECore::MidiPart* dest_part = part;
307
int nheight = y2pitch(pos.y());
308
if (nheight<0) nheight=0;
309
if (nheight>=getOurDrumMapSize()) nheight=getOurDrumMapSize()-1;
311
if (!instrument_map[nheight].tracks.contains(dest_part->track()))
314
printf("trying to move an event into a different track. checking if curPart is set correctly...\n");
316
if (!instrument_map[nheight].tracks.contains(curPart->track()))
318
printf ("ERROR: tried to move an event into a track which is different from both the initial part's and the curPart's track! ignoring this one...\n");
322
dest_part=(MusECore::MidiPart*)curPart;
255
325
MusECore::Event event = nevent->event();
259
int ntick = editor->rasterVal(x) - part->tick();
329
int ntick = editor->rasterVal(x) - dest_part->tick();
262
int npitch = y2pitch(pos.y());
263
332
MusECore::Event newEvent = event.clone();
265
newEvent.setPitch(npitch);
335
int ev_pitch = instrument_map[nheight].pitch;
337
newEvent.setPitch(ev_pitch);
266
338
newEvent.setTick(ntick);
268
340
// don't check, whether the new event is within the part
744
859
//---------------------------------------------------------
746
861
void DrumCanvas::keyPressed(int index, int velocity)
863
using MusECore::MidiTrack;
865
if ((index<0) || (index>=getOurDrumMapSize()))
748
868
// called from DList - play event
749
int port = MusEGlobal::drumMap[index].port;
750
int channel = MusEGlobal::drumMap[index].channel;
751
int pitch = MusEGlobal::drumMap[index].anote;
869
int port = old_style_drummap_mode ? ourDrumMap[index].port : dynamic_cast<MidiTrack*>(*instrument_map[index].tracks.begin())->outPort();
870
int channel = old_style_drummap_mode ? ourDrumMap[index].channel : dynamic_cast<MidiTrack*>(*instrument_map[index].tracks.begin())->outChannel();
871
int pitch = old_style_drummap_mode ? ourDrumMap[index].anote : instrument_map[index].pitch;
754
MusECore::MidiPlayEvent e(0, port, channel, 0x90, pitch, velocity);
755
MusEGlobal::audio->msgPlayMidiEvent(&e);
757
if (_steprec && curPart && pos[0] >= start_tick) // && pos[0] < end_tick [removed by flo93: this is handled in steprec->record]
758
steprec->record(curPart,index,MusEGlobal::drumMap[index].len,editor->raster(),velocity,MusEGlobal::globalKeyState&Qt::ControlModifier,MusEGlobal::globalKeyState&Qt::ShiftModifier);
876
MusECore::MidiPlayEvent e(0, port, channel, 0x90, pitch, velocity);
877
MusEGlobal::audio->msgPlayMidiEvent(&e);
880
if (_steprec) /* && pos[0] >= start_tick && pos[0] < end_tick [removed by flo93: this is handled in steprec->record] */
882
if ( curPart && instrument_map[index].tracks.contains(curPart->track()) )
883
steprec->record(curPart,instrument_map[index].pitch,ourDrumMap[index].len,editor->raster(),velocity,MusEGlobal::globalKeyState&Qt::ControlModifier,MusEGlobal::globalKeyState&Qt::ShiftModifier, -1 /* invalid pitch as "really played" -> the "insert rest" feature is never triggered */);
886
QSet<MusECore::Part*> parts = parts_at_tick(pos[0], instrument_map[index].tracks);
888
if (parts.count() != 1)
889
QMessageBox::warning(this, tr("Recording event failed"), tr("Couldn't record the event, because the currently selected part isn't the same track, and the instrument to be recorded could be either on no or on multiple parts, which is ambiguous.\nSelect the destination part, then try again."));
891
steprec->record(*parts.begin(), instrument_map[index].pitch,ourDrumMap[index].len,editor->raster(),velocity,MusEGlobal::globalKeyState&Qt::ControlModifier,MusEGlobal::globalKeyState&Qt::ShiftModifier, -1 /* invalid pitch as "really played" -> the "insert rest" feature is never triggered */);
762
897
//---------------------------------------------------------
859
1007
MusEGlobal::song->applyOperationGroup(operations, false); // do not indicate undo
860
1008
MusEGlobal::song->update(SC_DRUMMAP); //this update is neccessary, as it's not handled by applyOperationGroup()
1010
else // if (!old_style_drummap_mode)
1014
using MusEGlobal::global_drum_ordering_t;
1015
using MusEGlobal::global_drum_ordering;
1017
for (QSet<MusECore::Track*>::iterator it=instrument_map[spitch].tracks.begin();
1018
it!=instrument_map[spitch].tracks.end(); it++)
1020
if (dynamic_cast<MusECore::MidiTrack*>(*it))
1021
dynamic_cast<MusECore::MidiTrack*>(*it)->set_drummap_ordering_tied_to_patch(false);
1023
for (QSet<MusECore::Track*>::iterator it=instrument_map[dpitch].tracks.begin();
1024
it!=instrument_map[dpitch].tracks.end(); it++)
1026
if (dynamic_cast<MusECore::MidiTrack*>(*it))
1027
dynamic_cast<MusECore::MidiTrack*>(*it)->set_drummap_ordering_tied_to_patch(false);
1030
MusECore::DrumMap dm_temp = ourDrumMap[spitch];
1031
instrument_number_mapping_t im_temp = instrument_map[spitch];
1033
global_drum_ordering_t order_temp;
1034
for (global_drum_ordering_t::iterator it=global_drum_ordering.begin(); it!=global_drum_ordering.end();)
1036
if (im_temp.pitch==it->second && im_temp.tracks.contains(it->first))
1038
order_temp.push_back(*it);
1039
it=global_drum_ordering.erase(it);
1045
// the instrument represented by instrument_map[dpitch] is always the instrument
1046
// which will be immediately AFTER our dragged instrument. or it's invalid
1047
if (dpitch < getOurDrumMapSize())
1049
for (global_drum_ordering_t::iterator it=global_drum_ordering.begin(); it!=global_drum_ordering.end(); it++)
1050
if (instrument_map[dpitch].pitch==it->second && instrument_map[dpitch].tracks.contains(it->first))
1052
while (!order_temp.empty())
1053
it=global_drum_ordering.insert(it, order_temp.takeLast());
1060
global_drum_ordering_t::iterator it=global_drum_ordering.end();
1061
while (!order_temp.empty())
1062
it=global_drum_ordering.insert(it, order_temp.takeLast());
1069
if (dpitch > spitch)
1071
for (int i=spitch; i<dpitch-1; i++)
1073
ourDrumMap[i]=ourDrumMap[i+1];
1074
instrument_map[i]=instrument_map[i+1];
1077
ourDrumMap[dpitch-1] = dm_temp;
1078
instrument_map[dpitch-1] = im_temp;
1080
else if (spitch > dpitch)
1082
for (int i=spitch; i>dpitch; i--)
1084
ourDrumMap[i]=ourDrumMap[i-1];
1085
instrument_map[i]=instrument_map[i-1];
1088
ourDrumMap[dpitch] = dm_temp;
1089
instrument_map[dpitch] = im_temp;
1094
MusEGlobal::song->update(SC_DRUMMAP); // this causes a complete rebuild of ourDrumMap
1095
// which also handles the changed order in all
1096
// other drum editors
863
1100
//---------------------------------------------------------
1177
1424
//---------------------------------------------------------
1178
1425
void DrumCanvas::midiNote(int pitch, int velo)
1427
using MusECore::Track;
1428
using MusECore::Part;
1430
if (debugMsg) printf("DrumCanvas::midiNote: pitch=%i, velo=%i\n", pitch, velo);
1432
if (_midiin && _steprec && !MusEGlobal::audio->isPlaying() && velo && !(MusEGlobal::globalKeyState & Qt::AltModifier) /* && pos[0] >= start_tick && pos[0] < end_tick [removed by flo93: this is handled in steprec->record()] */ )
1180
if (MusEGlobal::debugMsg) printf("DrumCanvas::midiNote: pitch=%i, velo=%i\n", pitch, velo);
1182
if (_midiin && _steprec && curPart
1183
&& !MusEGlobal::audio->isPlaying() && velo && pos[0] >= start_tick
1184
/* && pos[0] < end_tick [removed by flo93: this is handled in steprec->record] */
1185
&& !(MusEGlobal::globalKeyState & Qt::AltModifier)) {
1186
steprec->record(curPart,MusEGlobal::drumInmap[pitch],MusEGlobal::drumMap[(int)MusEGlobal::drumInmap[pitch]].len,editor->raster(),velo,MusEGlobal::globalKeyState&Qt::ControlModifier,MusEGlobal::globalKeyState&Qt::ShiftModifier);
1434
if (pitch == MusEGlobal::rcSteprecNote) // skip the fancy code below, simply record a rest
1437
steprec->record(curPart,0xdead,0xbeef,editor->raster(),velo,MusEGlobal::globalKeyState&Qt::ControlModifier,MusEGlobal::globalKeyState&Qt::ShiftModifier, pitch);
1441
QSet<Track*> possible_dest_tracks;
1442
Part* rec_part=NULL;
1445
int ourDrumMapSize=getOurDrumMapSize();
1447
for (i=0;i<ourDrumMapSize;i++)
1449
if ( instrument_map[i].tracks.contains(curPart->track()) && ourDrumMap[i].enote==pitch)
1455
else if (ourDrumMap[i].enote==pitch)
1456
possible_dest_tracks.unite(instrument_map[i].tracks);
1459
if (rec_part == NULL) // if recording to curPart isn't possible
1461
QSet<Part*> possible_dest_parts = parts_at_tick(pos[0], possible_dest_tracks);
1463
if (possible_dest_parts.count() != 1)
1464
QMessageBox::warning(this, tr("Recording event failed"), tr("Couldn't record the event, because the currently selected part isn't the same track, and the instrument to be recorded could be either on no or on multiple parts, which is ambiguous.\nSelect the destination part, then try again."));
1467
rec_part = *possible_dest_parts.begin();
1468
Track* dest_track=rec_part->track();
1470
for (i=0;i<ourDrumMapSize;i++)
1471
if ( instrument_map[i].tracks.contains(dest_track) && ourDrumMap[i].enote==pitch)
1479
printf("ERROR: THIS SHOULD NEVER HAPPEN: i found a destination part for step recording, but now i can't find the instrument any more in DrumCanvas::midiNote()?!\n");
1480
QMessageBox::critical(this, tr("Internal error"), tr("Wtf, some nasty internal error which is actually impossible occurred. Check console output. Nothing recorded."));
1486
if (rec_part != NULL)
1487
steprec->record(rec_part,instrument_map[rec_index].pitch,ourDrumMap[rec_index].len,editor->raster(),velo,MusEGlobal::globalKeyState&Qt::ControlModifier,MusEGlobal::globalKeyState&Qt::ShiftModifier, pitch);
1493
int DrumCanvas::pitch_and_track_to_instrument(int pitch, MusECore::Track* track)
1495
for (int i=0; i<instrument_map.size(); i++)
1496
if (instrument_map[i].tracks.contains(track) && instrument_map[i].pitch==pitch)
1499
if (heavyDebugMsg) printf("DrumCanvas::pitch_and_track_to_instrument() called with invalid arguments.\n");
1503
void DrumCanvas::propagate_drummap_change(int instr, bool update_druminmap)
1505
const QSet<MusECore::Track*>& tracks=instrument_map[instr].tracks;
1506
int index=instrument_map[instr].pitch;
1508
for (QSet<MusECore::Track*>::const_iterator it = tracks.begin(); it != tracks.end(); it++)
1510
MusECore::MidiTrack* mt=dynamic_cast<MusECore::MidiTrack*>(*it);
1511
// if we're not only changing "mute" state...
1512
if (!mt->drummap()[index].almost_equals(ourDrumMap[instr]))
1513
mt->set_drummap_tied_to_patch(false);
1514
mt->drummap()[index] = ourDrumMap[instr];
1515
if (update_druminmap)
1516
mt->update_drum_in_map();
1521
void DrumCanvas::rebuildOurDrumMap()
1523
using MusECore::drummaps_almost_equal;
1524
using MusECore::Track;
1525
using MusECore::MidiTrack;
1526
using MusECore::TrackList;
1527
using MusECore::ciTrack;
1528
using MusECore::ciPart;
1529
using MusECore::DrumMap;
1530
using MusEGlobal::global_drum_ordering_t;
1531
using MusEGlobal::global_drum_ordering;
1534
if (!old_style_drummap_mode)
1536
bool need_update = false;
1538
TrackList* tl=MusEGlobal::song->tracks();
1539
QList< QSet<Track*> > track_groups;
1540
QVector<instrument_number_mapping_t> old_instrument_map = instrument_map;
1542
instrument_map.clear();
1544
for (ciTrack track = tl->begin(); track!=tl->end(); track++)
1547
for (p_it=drumEditor->parts()->begin(); p_it!=drumEditor->parts()->end(); p_it++)
1548
if (p_it->second->track() == *track)
1551
if (p_it!=drumEditor->parts()->end()) // if *track is represented by some part in this editor
1553
bool inserted=false;
1555
switch (drumEditor->group_mode())
1557
case DrumEdit::GROUP_SAME_CHANNEL:
1558
for (QList< QSet<Track*> >::iterator group=track_groups.begin(); group!=track_groups.end(); group++)
1559
if ( ((MidiTrack*)*group->begin())->outChannel() == ((MidiTrack*)*track)->outChannel() &&
1560
((MidiTrack*)*group->begin())->outPort() == ((MidiTrack*)*track)->outPort() &&
1561
(drummaps_almost_equal(((MidiTrack*)*group->begin())->drummap(), ((MidiTrack*)*track)->drummap())) )
1563
group->insert(*track);
1569
case DrumEdit::GROUP_MAX:
1570
for (QList< QSet<Track*> >::iterator group=track_groups.begin(); group!=track_groups.end(); group++)
1571
if (drummaps_almost_equal(((MidiTrack*)*group->begin())->drummap(), ((MidiTrack*)*track)->drummap()))
1573
group->insert(*track);
1579
case DrumEdit::DONT_GROUP:
1584
printf("THIS SHOULD NEVER HAPPEN: group_mode() is invalid!\n");
1591
temp.insert(*track);
1592
track_groups.push_back(temp);
1597
// from now, we assume that every track_group's entry only groups tracks with identical
1598
// drum maps, but not necessarily identical hide-lists together.
1599
QList< std::pair<MidiTrack*,int> > ignore_order_entries;
1600
for (global_drum_ordering_t::iterator order_it=global_drum_ordering.begin(); order_it!=global_drum_ordering.end(); order_it++)
1602
// if this entry should be ignored, ignore it.
1603
if (ignore_order_entries.contains(*order_it))
1606
// look if we have order_it->first (the MidiTrack*) in any of our track groups
1607
QList< QSet<Track*> >::iterator group;
1608
for (group=track_groups.begin(); group!=track_groups.end(); group++)
1609
if (group->contains(order_it->first))
1612
if (group!=track_groups.end()) // we have
1614
int pitch=order_it->second;
1619
if (drumEditor->ignore_hide()) hidden=false;
1621
for (QSet<Track*>::iterator track=group->begin(); track!=group->end() && (mute || hidden); track++)
1623
if (dynamic_cast<MidiTrack*>(*track)->drummap()[pitch].mute == false)
1626
if (dynamic_cast<MidiTrack*>(*track)->drummap_hidden()[pitch] == false)
1632
for (QSet<Track*>::iterator track=group->begin(); track!=group->end(); track++)
1634
DrumMap* dm = &dynamic_cast<MidiTrack*>(*track)->drummap()[pitch];
1635
if (dm->mute != mute)
1642
if (dynamic_cast<MidiTrack*>(*group->begin())->drummap()[pitch].anote != pitch)
1643
printf("THIS SHOULD NEVER HAPPEN: track's_drummap[pitch].anote (%i)!= pitch (%i) !!!\n",dynamic_cast<MidiTrack*>(*group->begin())->drummap()[pitch].anote,pitch);
1645
instrument_map.append(instrument_number_mapping_t(*group, pitch));
1648
for (QSet<Track*>::iterator track=group->begin(); track!=group->end(); track++)
1649
ignore_order_entries.append(std::pair<MidiTrack*,int>(dynamic_cast<MidiTrack*>(*track), pitch));
1655
// maybe delete and then populate ourDrumMap
1657
if (must_delete_our_drum_map && ourDrumMap!=NULL)
1658
delete [] ourDrumMap;
1660
int size = instrument_map.size();
1661
ourDrumMap=new DrumMap[size];
1662
must_delete_our_drum_map=true;
1664
for (int i=0;i<size;i++)
1665
ourDrumMap[i] = dynamic_cast<MidiTrack*>(*instrument_map[i].tracks.begin())->drummap()[instrument_map[i].pitch];
1667
if (instrument_map!=old_instrument_map)
1669
if (debugMsg) printf("rebuilt drummap and instrument map, size is now %i\n",size);
1671
songChanged(SC_EVENT_INSERTED); // force an update of the itemlist
1672
emit ourDrumMapChanged(true);
1675
emit ourDrumMapChanged(false);
1678
MusEGlobal::song->update(SC_DRUMMAP, true); // i know, this causes a recursion, which possibly
1679
// isn't the most elegant solution here. but it will
1680
// never be an infinite recursion
1190
1684
} // namespace MusEGui