summaryrefslogtreecommitdiff
path: root/muse2/muse/midiedit/dcanvas.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'muse2/muse/midiedit/dcanvas.cpp')
-rw-r--r--muse2/muse/midiedit/dcanvas.cpp608
1 files changed, 540 insertions, 68 deletions
diff --git a/muse2/muse/midiedit/dcanvas.cpp b/muse2/muse/midiedit/dcanvas.cpp
index 7b5949a4..4c033946 100644
--- a/muse2/muse/midiedit/dcanvas.cpp
+++ b/muse2/muse/midiedit/dcanvas.cpp
@@ -22,6 +22,7 @@
#include <QPainter>
#include <QApplication>
+#include <QMessageBox>
#include <QClipboard>
#include <QDrag>
#include <QDragLeaveEvent>
@@ -34,12 +35,12 @@
#include <stdio.h>
#include <values.h>
#include <errno.h>
-#include <set>
//#include <sys/stat.h>
//#include <sys/mman.h>
#include "dcanvas.h"
#include "midieditor.h"
+#include "drumedit.h"
#include "drummap.h"
#include "event.h"
#include "mpevent.h"
@@ -50,20 +51,23 @@
#include "shortcuts.h"
#include "icons.h"
#include "functions.h"
+#include "helper.h"
#define CARET 10
#define CARET2 5
+using MusEGlobal::debugMsg;
+using MusEGlobal::heavyDebugMsg;
+
namespace MusEGui {
//---------------------------------------------------------
// DEvent
//---------------------------------------------------------
-DEvent::DEvent(MusECore::Event e, MusECore::Part* p)
+DEvent::DEvent(MusECore::Event e, MusECore::Part* p, int instr)
: CItem(e, p)
{
- int instr = e.pitch();
int y = instr * TH + TH/2;
int tick = e.tick() + p->tick();
setPos(QPoint(tick, y));
@@ -81,7 +85,14 @@ CItem* DrumCanvas::addItem(MusECore::Part* part, MusECore::Event& event)
return NULL;
}
- DEvent* ev = new DEvent(event, part);
+ int instr=pitch_and_track_to_instrument(event.pitch(), part->track());
+ if (instr<0)
+ {
+ if (heavyDebugMsg) printf("trying to add event which is hidden or not in any part known to me\n");
+ return NULL;
+ }
+
+ DEvent* ev = new DEvent(event, part, instr);
items.add(ev);
int diff = event.endTick()-part->lenTick();
@@ -105,6 +116,37 @@ DrumCanvas::DrumCanvas(MidiEditor* pr, QWidget* parent, int sx,
int sy, const char* name)
: EventCanvas(pr, parent, sx, sy, name)
{
+ drumEditor=dynamic_cast<DrumEdit*>(pr);
+
+ _setCurPartIfOnlyOneEventIsSelected=false;
+
+ old_style_drummap_mode = drumEditor->old_style_drummap_mode();
+
+ if (old_style_drummap_mode)
+ {
+ if (debugMsg) printf("DrumCanvas in old style drummap mode\n");
+ ourDrumMap = MusEGlobal::drumMap;
+ must_delete_our_drum_map=false;
+
+ instrument_number_mapping_t temp;
+ for (MusECore::ciPart it=drumEditor->parts()->begin(); it!=drumEditor->parts()->end(); it++)
+ temp.tracks.insert(it->second->track());
+
+ for (int i=0;i<DRUM_MAPSIZE;i++)
+ {
+ temp.pitch=i;
+ instrument_map.append(temp);
+ }
+ }
+ else
+ {
+ if (debugMsg) printf("DrumCanvas in new style drummap mode\n");
+ ourDrumMap=NULL;
+ rebuildOurDrumMap();
+ }
+
+
+
setVirt(false);
cursorPos= QPoint(0,0);
_stepSize=1;
@@ -118,6 +160,11 @@ DrumCanvas::DrumCanvas(MidiEditor* pr, QWidget* parent, int sx,
DrumCanvas::~DrumCanvas()
{
//items.clearDelete();
+
+ if (must_delete_our_drum_map && ourDrumMap!=NULL)
+ delete [] ourDrumMap;
+
+ delete steprec;
}
//---------------------------------------------------------
@@ -197,7 +244,7 @@ MusECore::Undo DrumCanvas::moveCanvasItems(CItemList& items, int dp, int dx, Dra
for(iCItem ici = items.begin(); ici != items.end(); ++ici)
{
- CItem* ci = ici->second;
+ CItem* ci = ici->second;
int x = ci->pos().x();
int y = ci->pos().y();
@@ -215,11 +262,15 @@ MusECore::Undo DrumCanvas::moveCanvasItems(CItemList& items, int dp, int dx, Dra
// Do not process if the event has already been processed (meaning it's an event in a clone part)...
if (idl == doneList.end())
{
- operations.push_back(moveItem(ci, newpos, dtype));
+ if (moveItem(operations, ci, newpos, dtype) == false) //error?
+ {
+ QMessageBox::warning(this, tr("Moving items failed"), tr("The selection couldn't be moved, because at least one note would be moved into a track which is different from both the original track and the current part's track.\nChanging the current part with ALT+LEFT/RIGHT may help."));
+ return MusECore::Undo(); //return empty list
+ }
doneList.push_back(ci);
}
ci->move(newpos);
-
+
if(moving.size() == 1)
itemReleased(curItem, newpos);
@@ -247,23 +298,44 @@ MusECore::Undo DrumCanvas::moveCanvasItems(CItemList& items, int dp, int dx, Dra
// moveItem
//---------------------------------------------------------
-MusECore::UndoOp DrumCanvas::moveItem(CItem* item, const QPoint& pos, DragType dtype)
+bool DrumCanvas::moveItem(MusECore::Undo& operations, CItem* item, const QPoint& pos, DragType dtype)
{
DEvent* nevent = (DEvent*) item;
- MusECore::MidiPart* part = (MusECore::MidiPart*)nevent->part();
+ MusECore::MidiPart* part = (MusECore::MidiPart*)nevent->part();
+ MusECore::MidiPart* dest_part = part;
+ int nheight = y2pitch(pos.y());
+ if (nheight<0) nheight=0;
+ if (nheight>=getOurDrumMapSize()) nheight=getOurDrumMapSize()-1;
+
+ if (!instrument_map[nheight].tracks.contains(dest_part->track()))
+ {
+ if (debugMsg)
+ printf("trying to move an event into a different track. checking if curPart is set correctly...\n");
+
+ if (!instrument_map[nheight].tracks.contains(curPart->track()))
+ {
+ 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");
+ return false;
+ }
+ else
+ dest_part=(MusECore::MidiPart*)curPart;
+ }
+
MusECore::Event event = nevent->event();
int x = pos.x();
if (x < 0)
x = 0;
- int ntick = editor->rasterVal(x) - part->tick();
+ int ntick = editor->rasterVal(x) - dest_part->tick();
if (ntick < 0)
ntick = 0;
- int npitch = y2pitch(pos.y());
MusECore::Event newEvent = event.clone();
- newEvent.setPitch(npitch);
+
+ int ev_pitch = instrument_map[nheight].pitch;
+
+ newEvent.setPitch(ev_pitch);
newEvent.setTick(ntick);
// Added by T356, removed by flo93: with operation groups, it happens that the
@@ -272,10 +344,19 @@ MusECore::UndoOp DrumCanvas::moveItem(CItem* item, const QPoint& pos, DragType d
// printf("DrumCanvas::moveItem Error! New event end:%d exceeds length:%d of part:%s\n", newEvent.endTick(), part->lenTick(), part->name().toLatin1().constData());
if (dtype == MOVE_COPY || dtype == MOVE_CLONE)
- return MusECore::UndoOp(MusECore::UndoOp::AddEvent, newEvent, part, false, false);
+ operations.push_back(MusECore::UndoOp(MusECore::UndoOp::AddEvent, newEvent, dest_part, false, false));
else
- return MusECore::UndoOp(MusECore::UndoOp::ModifyEvent, newEvent, event, part, false, false);
+ {
+ if (dest_part == part)
+ operations.push_back(MusECore::UndoOp(MusECore::UndoOp::ModifyEvent, newEvent, event, part, false, false));
+ else
+ {
+ operations.push_back(MusECore::UndoOp(MusECore::UndoOp::DeleteEvent, event, part, false, false));
+ operations.push_back(MusECore::UndoOp(MusECore::UndoOp::AddEvent, newEvent, dest_part, false, false));
+ }
}
+ return true;
+}
//---------------------------------------------------------
// newItem
@@ -284,13 +365,16 @@ MusECore::UndoOp DrumCanvas::moveItem(CItem* item, const QPoint& pos, DragType d
CItem* DrumCanvas::newItem(const QPoint& p, int state)
{
int instr = y2pitch(p.y()); //MusEGlobal::drumInmap[y2pitch(p.y())];
- int velo = MusEGlobal::drumMap[instr].lv4;
+ if ((instr<0) || (instr>=getOurDrumMapSize()))
+ return NULL;
+
+ int velo = ourDrumMap[instr].lv4;
if (state == Qt::ShiftModifier)
- velo = MusEGlobal::drumMap[instr].lv3;
+ velo = ourDrumMap[instr].lv3;
else if (state == Qt::ControlModifier)
- velo = MusEGlobal::drumMap[instr].lv2;
+ velo = ourDrumMap[instr].lv2;
else if (state == (Qt::ControlModifier | Qt::ShiftModifier))
- velo = MusEGlobal::drumMap[instr].lv1;
+ velo = ourDrumMap[instr].lv1;
int tick = editor->rasterVal(p.x());
return newItem(tick, instr, velo);
}
@@ -301,13 +385,36 @@ CItem* DrumCanvas::newItem(const QPoint& p, int state)
CItem* DrumCanvas::newItem(int tick, int instrument, int velocity)
{
+ if ((instrument<0) || (instrument>=getOurDrumMapSize()))
+ return NULL;
+
+ if (!old_style_drummap_mode && !instrument_map[instrument].tracks.contains(curPart->track()))
+ {
+ if (debugMsg)
+ printf("tried to create a new Item which cannot be inside the current track. looking for destination part...\n");
+
+ QSet<MusECore::Part*> parts = parts_at_tick(tick, instrument_map[instrument].tracks);
+
+ if (parts.count() != 1)
+ {
+ QMessageBox::warning(this, tr("Creating event failed"), tr("Couldn't create the event, because the currently selected part isn't the same track, and the selected instrument could be either on no or on multiple parts, which is ambiguous.\nSelect the destination part, then try again."));
+ return NULL;
+ }
+ else
+ {
+ setCurrentPart(*parts.begin());
+ }
+ }
+ // else or if we found an alternative part (which has now been set as curPart)
+
tick -= curPart->tick();
MusECore::Event e(MusECore::Note);
e.setTick(tick);
- e.setPitch(instrument);
+ e.setPitch(instrument_map[instrument].pitch);
e.setVelo(velocity);
- e.setLenTick(MusEGlobal::drumMap[instrument].len);
- return new DEvent(e, curPart);
+ e.setLenTick(ourDrumMap[instrument].len);
+
+ return new DEvent(e, curPart, instrument);
}
//---------------------------------------------------------
@@ -330,7 +437,9 @@ void DrumCanvas::newItem(CItem* item, bool noSnap) {
}
void DrumCanvas::newItem(CItem* item, bool noSnap, bool replace)
- {
+{
+ if (item)
+ {
DEvent* nevent = (DEvent*) item;
MusECore::Event event = nevent->event();
int x = item->x();
@@ -338,7 +447,7 @@ void DrumCanvas::newItem(CItem* item, bool noSnap, bool replace)
x = editor->rasterVal(x);
event.setTick(x - nevent->part()->tick());
int npitch = event.pitch();
- event.setPitch(npitch);
+ //event.setPitch(npitch); // commented out by flo: has no effect
//
// check for existing event
@@ -374,7 +483,7 @@ void DrumCanvas::newItem(CItem* item, bool noSnap, bool replace)
{
operations.push_back(MusECore::UndoOp(MusECore::UndoOp::AddEvent,event, part, false, false));
- if (diff > 0)// part must be extended?
+ if (diff > 0) // part must be extended?
{
schedule_resize_all_same_len_clone_parts(part, event.endTick(), operations);
printf("newItem: extending\n");
@@ -384,7 +493,10 @@ void DrumCanvas::newItem(CItem* item, bool noSnap, bool replace)
MusEGlobal::song->applyOperationGroup(operations);
songChanged(SC_EVENT_INSERTED); //this forces an update of the itemlist, which is neccessary
//to remove "forbidden" events from the list again
- }
+ }
+ else
+ printf("THIS SHOULD NEVER HAPPEN: DrumCanvas::newItem called with NULL item!\n");
+}
//---------------------------------------------------------
// deleteItem
@@ -439,7 +551,7 @@ void DrumCanvas::drawItem(QPainter&p, const CItem*item, const QRect& rect)
else
{
int velo = e->event().velo();
- MusECore::DrumMap* dm = &MusEGlobal::drumMap[y2pitch(y)]; //Get the drum item
+ MusECore::DrumMap* dm = &ourDrumMap[y2pitch(y)]; //Get the drum item
QColor color;
if (velo < dm->lv1)
color.setRgb(240, 240, 255);
@@ -530,8 +642,10 @@ void DrumCanvas::drawTopItem(QPainter& p, const QRect&)
int DrumCanvas::y2pitch(int y) const
{
int pitch = y/TH;
- if (pitch >= DRUM_MAPSIZE)
- pitch = DRUM_MAPSIZE-1;
+ if (pitch >= instrument_map.size())
+ pitch = instrument_map.size()-1;
+ else if (pitch<0)
+ pitch = 0;
return pitch;
}
@@ -640,7 +754,8 @@ void DrumCanvas::cmd(int cmd)
DEvent* devent = (DEvent*)(k->second);
MusECore::Event event = devent->event();
MusECore::Event newEvent = event.clone();
- newEvent.setLenTick(MusEGlobal::drumMap[event.pitch()].len);
+ // newEvent.setLenTick(drumMap[event.pitch()].len);
+ newEvent.setLenTick(ourDrumMap[y2pitch(devent->y())].len);
// Indicate no undo, and do not do port controller values and clone parts.
MusEGlobal::audio->msgChangeEvent(event, newEvent, devent->part(), false, false, false);
}
@@ -744,19 +859,37 @@ void DrumCanvas::dragLeaveEvent(QDragLeaveEvent*)
void DrumCanvas::keyPressed(int index, int velocity)
{
+ using MusECore::MidiTrack;
+
+ if ((index<0) || (index>=getOurDrumMapSize()))
+ return;
+
// called from DList - play event
- int port = MusEGlobal::drumMap[index].port;
- int channel = MusEGlobal::drumMap[index].channel;
- int pitch = MusEGlobal::drumMap[index].anote;
+ int port = old_style_drummap_mode ? ourDrumMap[index].port : dynamic_cast<MidiTrack*>(*instrument_map[index].tracks.begin())->outPort();
+ int channel = old_style_drummap_mode ? ourDrumMap[index].channel : dynamic_cast<MidiTrack*>(*instrument_map[index].tracks.begin())->outChannel();
+ int pitch = old_style_drummap_mode ? ourDrumMap[index].anote : instrument_map[index].pitch;
// play note:
MusECore::MidiPlayEvent e(0, port, channel, 0x90, pitch, velocity);
MusEGlobal::audio->msgPlayMidiEvent(&e);
-
- if (_steprec && pos[0] >= start_tick /* && pos[0] < end_tick [removed by flo93: this is handled in steprec->record] */ && curPart)
- steprec->record(curPart,index,MusEGlobal::drumMap[index].len,editor->raster(),velocity,MusEGlobal::globalKeyState&Qt::ControlModifier,MusEGlobal::globalKeyState&Qt::ShiftModifier);
-
- }
+
+
+ if (_steprec) /* && pos[0] >= start_tick && pos[0] < end_tick [removed by flo93: this is handled in steprec->record] */
+ {
+ if ( curPart && instrument_map[index].tracks.contains(curPart->track()) )
+ 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 */);
+ else
+ {
+ QSet<MusECore::Part*> parts = parts_at_tick(pos[0], instrument_map[index].tracks);
+
+ if (parts.count() != 1)
+ 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."));
+ else
+ 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 */);
+
+ }
+ }
+}
//---------------------------------------------------------
// keyReleased
@@ -764,10 +897,15 @@ void DrumCanvas::keyPressed(int index, int velocity)
void DrumCanvas::keyReleased(int index, bool)
{
+ using MusECore::MidiTrack;
+
+ if ((index<0) || (index>=getOurDrumMapSize()))
+ return;
+
// called from DList - silence playing event
- int port = MusEGlobal::drumMap[index].port;
- int channel = MusEGlobal::drumMap[index].channel;
- int pitch = MusEGlobal::drumMap[index].anote;
+ int port = old_style_drummap_mode ? ourDrumMap[index].port : dynamic_cast<MidiTrack*>(*instrument_map[index].tracks.begin())->outPort();
+ int channel = old_style_drummap_mode ? ourDrumMap[index].channel : dynamic_cast<MidiTrack*>(*instrument_map[index].tracks.begin())->outChannel();
+ int pitch = old_style_drummap_mode ? ourDrumMap[index].anote : instrument_map[index].pitch;
// release note:
MusECore::MidiPlayEvent e(0, port, channel, 0x90, pitch, 0);
@@ -779,7 +917,12 @@ void DrumCanvas::keyReleased(int index, bool)
//---------------------------------------------------------
void DrumCanvas::mapChanged(int spitch, int dpitch)
- {
+{
+ // spitch may be the same as dpitch! and something in here must be executed
+ // even if they're same (i assume it's song->update(SC_DRUMMAP)) (flo93)
+
+ if (old_style_drummap_mode)
+ {
MusECore::Undo operations;
std::vector< std::pair<MusECore::Part*, MusECore::Event*> > delete_events;
std::vector< std::pair<MusECore::Part*, MusECore::Event> > add_events;
@@ -857,7 +1000,83 @@ void DrumCanvas::mapChanged(int spitch, int dpitch)
MusEGlobal::song->applyOperationGroup(operations, false); // do not indicate undo
MusEGlobal::song->update(SC_DRUMMAP); //this update is neccessary, as it's not handled by applyOperationGroup()
+ }
+ else // if (!old_style_drummap_mode)
+ {
+ if (dpitch!=spitch)
+ {
+ using MusEGlobal::global_drum_ordering_t;
+ using MusEGlobal::global_drum_ordering;
+
+ MusECore::DrumMap dm_temp = ourDrumMap[spitch];
+ instrument_number_mapping_t im_temp = instrument_map[spitch];
+
+ global_drum_ordering_t order_temp;
+ for (global_drum_ordering_t::iterator it=global_drum_ordering.begin(); it!=global_drum_ordering.end();)
+ {
+ if (im_temp.pitch==it->second && im_temp.tracks.contains(it->first))
+ {
+ order_temp.push_back(*it);
+ it=global_drum_ordering.erase(it);
+ }
+ else
+ it++;
+ }
+
+ // the instrument represented by instrument_map[dpitch] is always the instrument
+ // which will be immediately AFTER our dragged instrument. or it's invalid
+ if (dpitch < getOurDrumMapSize())
+ {
+ for (global_drum_ordering_t::iterator it=global_drum_ordering.begin(); it!=global_drum_ordering.end(); it++)
+ if (instrument_map[dpitch].pitch==it->second && instrument_map[dpitch].tracks.contains(it->first))
+ {
+ while (!order_temp.empty())
+ it=global_drum_ordering.insert(it, order_temp.takeLast());
+
+ break;
+ }
+ }
+ else
+ {
+ global_drum_ordering_t::iterator it=global_drum_ordering.end();
+ while (!order_temp.empty())
+ it=global_drum_ordering.insert(it, order_temp.takeLast());
+ }
+
+
+
+
+
+ if (dpitch > spitch)
+ {
+ for (int i=spitch; i<dpitch-1; i++)
+ {
+ ourDrumMap[i]=ourDrumMap[i+1];
+ instrument_map[i]=instrument_map[i+1];
+ }
+
+ ourDrumMap[dpitch-1] = dm_temp;
+ instrument_map[dpitch-1] = im_temp;
+ }
+ else if (spitch > dpitch)
+ {
+ for (int i=spitch; i>dpitch; i--)
+ {
+ ourDrumMap[i]=ourDrumMap[i-1];
+ instrument_map[i]=instrument_map[i-1];
+ }
+
+ ourDrumMap[dpitch] = dm_temp;
+ instrument_map[dpitch] = im_temp;
+ }
}
+
+
+ MusEGlobal::song->update(SC_DRUMMAP); // this causes a complete rebuild of ourDrumMap
+ // which also handles the changed order in all
+ // other drum editors
+ }
+}
//---------------------------------------------------------
// resizeEvent
@@ -909,6 +1128,7 @@ void DrumCanvas::modifySelected(NoteInfo::ValType type, int delta)
printf("DrumCanvas::modifySelected - NoteInfo::VAL_VELOFF not implemented\n");
break;
case NoteInfo::VAL_PITCH:
+ if (old_style_drummap_mode)
{
int pitch = event.pitch() - delta; // Reversing order since the drumlist is displayed in increasing order
if (pitch > 127)
@@ -917,6 +1137,8 @@ void DrumCanvas::modifySelected(NoteInfo::ValType type, int delta)
pitch = 0;
newEvent.setPitch(pitch);
}
+ else
+ printf("DrumCanvas::modifySelected - MusEWidget::NoteInfo::VAL_PITCH not implemented for new style drum editors\n");
break;
}
MusEGlobal::song->changeEvent(event, newEvent, part);
@@ -933,6 +1155,7 @@ void DrumCanvas::modifySelected(NoteInfo::ValType type, int delta)
void DrumCanvas::curPartChanged()
{
+ EventCanvas::curPartChanged();
editor->setWindowTitle(getCaption());
}
@@ -994,8 +1217,8 @@ void DrumCanvas::keyPress(QKeyEvent* event)
return;
}
else if (key == shortcuts[SHRT_ADDNOTE_1].key) {
- newItem(newItem(cursorPos.x(), cursorPos.y(), MusEGlobal::drumMap[cursorPos.y()].lv1),false,true);
- keyPressed(cursorPos.y(), MusEGlobal::drumMap[cursorPos.y()].lv1);
+ newItem(newItem(cursorPos.x(), cursorPos.y(), ourDrumMap[cursorPos.y()].lv1),false,true);
+ keyPressed(cursorPos.y(), ourDrumMap[cursorPos.y()].lv1);
keyReleased(cursorPos.y(), false);
cursorPos.setX(getNextStep(cursorPos.x(),1, _stepSize));
selectCursorEvent(getEventAtCursorPos());
@@ -1004,8 +1227,8 @@ void DrumCanvas::keyPress(QKeyEvent* event)
return;
}
else if (key == shortcuts[SHRT_ADDNOTE_2].key) {
- newItem(newItem(cursorPos.x(), cursorPos.y(), MusEGlobal::drumMap[cursorPos.y()].lv2),false,true);
- keyPressed(cursorPos.y(), MusEGlobal::drumMap[cursorPos.y()].lv2);
+ newItem(newItem(cursorPos.x(), cursorPos.y(), ourDrumMap[cursorPos.y()].lv2),false,true);
+ keyPressed(cursorPos.y(), ourDrumMap[cursorPos.y()].lv2);
keyReleased(cursorPos.y(), false);
cursorPos.setX(getNextStep(cursorPos.x(),1, _stepSize));
selectCursorEvent(getEventAtCursorPos());
@@ -1014,8 +1237,8 @@ void DrumCanvas::keyPress(QKeyEvent* event)
return;
}
else if (key == shortcuts[SHRT_ADDNOTE_3].key) {
- newItem(newItem(cursorPos.x(), cursorPos.y(), MusEGlobal::drumMap[cursorPos.y()].lv3),false,true);
- keyPressed(cursorPos.y(), MusEGlobal::drumMap[cursorPos.y()].lv3);
+ newItem(newItem(cursorPos.x(), cursorPos.y(), ourDrumMap[cursorPos.y()].lv3),false,true);
+ keyPressed(cursorPos.y(), ourDrumMap[cursorPos.y()].lv3);
keyReleased(cursorPos.y(), false);
cursorPos.setX(getNextStep(cursorPos.x(),1, _stepSize));
selectCursorEvent(getEventAtCursorPos());
@@ -1024,8 +1247,8 @@ void DrumCanvas::keyPress(QKeyEvent* event)
return;
}
else if (key == shortcuts[SHRT_ADDNOTE_4].key) {
- newItem(newItem(cursorPos.x(), cursorPos.y(), MusEGlobal::drumMap[cursorPos.y()].lv4),false,true);
- keyPressed(cursorPos.y(), MusEGlobal::drumMap[cursorPos.y()].lv4);
+ newItem(newItem(cursorPos.x(), cursorPos.y(), ourDrumMap[cursorPos.y()].lv4),false,true);
+ keyPressed(cursorPos.y(), ourDrumMap[cursorPos.y()].lv4);
keyReleased(cursorPos.y(), false);
cursorPos.setX(getNextStep(cursorPos.x(),1, _stepSize));
selectCursorEvent(getEventAtCursorPos());
@@ -1073,17 +1296,19 @@ MusECore::Event *DrumCanvas::getEventAtCursorPos()
{
if (_tool != CursorTool)
return 0;
- MusECore::EventList* el = curPart->events();
- MusECore::iEvent lower = el->lower_bound(cursorPos.x()-curPart->tick());
- MusECore::iEvent upper = el->upper_bound(cursorPos.x()-curPart->tick());
- for (MusECore::iEvent i = lower; i != upper; ++i) {
- MusECore::Event &ev = i->second;
- if(!ev.isNote())
- continue;
- if (ev.pitch() == cursorPos.y()) {
- return &ev;
+ if (instrument_map[cursorPos.y()].tracks.contains(curPart->track()))
+ {
+ MusECore::EventList* el = curPart->events();
+ MusECore::iEvent lower = el->lower_bound(cursorPos.x()-curPart->tick());
+ MusECore::iEvent upper = el->upper_bound(cursorPos.x()-curPart->tick());
+ int curPitch = instrument_map[cursorPos.y()].pitch;
+ for (MusECore::iEvent i = lower; i != upper; ++i) {
+ MusECore::Event &ev = i->second;
+ if (ev.isNote() && ev.pitch() == curPitch)
+ return &ev;
}
}
+ // else or if the for loop didn't find anything
return 0;
}
//---------------------------------------------------------
@@ -1107,9 +1332,13 @@ void DrumCanvas::selectCursorEvent(MusECore::Event *ev)
void DrumCanvas::moveAwayUnused()
{
- using std::set;
+ if (!old_style_drummap_mode)
+ {
+ printf("THIS SHOULD NEVER HAPPEN: DrumCanvas::moveAwayUnused() cannot be used in new style mode\n");
+ return;
+ }
- set<int> used;
+ QSet<int> used;
for (iCItem it=items.begin(); it!=items.end(); it++)
{
const MusECore::Event& ev=it->second->event();
@@ -1119,7 +1348,7 @@ void DrumCanvas::moveAwayUnused()
}
int count=0;
- for (set<int>::iterator it=used.begin(); it!=used.end();)
+ for (QSet<int>::iterator it=used.begin(); it!=used.end();)
{
while ((*it != count) && (used.find(count)!=used.end())) count++;
@@ -1137,15 +1366,258 @@ void DrumCanvas::moveAwayUnused()
// midiNote
//---------------------------------------------------------
void DrumCanvas::midiNote(int pitch, int velo)
- {
- if (MusEGlobal::debugMsg) printf("DrumCanvas::midiNote: pitch=%i, velo=%i\n", pitch, velo);
+{
+ using MusECore::Track;
+ using MusECore::Part;
+
+ if (debugMsg) printf("DrumCanvas::midiNote: pitch=%i, velo=%i\n", pitch, velo);
- if (_midiin && _steprec && curPart
- && !MusEGlobal::audio->isPlaying() && velo && pos[0] >= start_tick
- /* && pos[0] < end_tick [removed by flo93: this is handled in steprec->record] */
- && !(MusEGlobal::globalKeyState & Qt::AltModifier)) {
- steprec->record(curPart,MusEGlobal::drumInmap[pitch],MusEGlobal::drumMap[(int)MusEGlobal::drumInmap[pitch]].len,editor->raster(),velo,MusEGlobal::globalKeyState&Qt::ControlModifier,MusEGlobal::globalKeyState&Qt::ShiftModifier);
+ 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()] */ )
+ {
+ if (pitch == MusEGlobal::rcSteprecNote) // skip the fancy code below, simply record a rest
+ {
+ if (curPart)
+ steprec->record(curPart,0xdead,0xbeef,editor->raster(),velo,MusEGlobal::globalKeyState&Qt::ControlModifier,MusEGlobal::globalKeyState&Qt::ShiftModifier, pitch);
}
+ else
+ {
+ QSet<Track*> possible_dest_tracks;
+ Part* rec_part=NULL;
+ int rec_index=-1;
+
+ int ourDrumMapSize=getOurDrumMapSize();
+ int i;
+ for (i=0;i<ourDrumMapSize;i++)
+ {
+ if ( instrument_map[i].tracks.contains(curPart->track()) && ourDrumMap[i].enote==pitch)
+ {
+ rec_part=curPart;
+ rec_index=i;
+ break;
+ }
+ else if (ourDrumMap[i].enote==pitch)
+ possible_dest_tracks.unite(instrument_map[i].tracks);
+ }
+
+ if (rec_part == NULL) // if recording to curPart isn't possible
+ {
+ QSet<Part*> possible_dest_parts = parts_at_tick(pos[0], possible_dest_tracks);
+
+ if (possible_dest_parts.count() != 1)
+ 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."));
+ else
+ {
+ rec_part = *possible_dest_parts.begin();
+ Track* dest_track=rec_part->track();
+
+ for (i=0;i<ourDrumMapSize;i++)
+ if ( instrument_map[i].tracks.contains(dest_track) && ourDrumMap[i].enote==pitch)
+ {
+ rec_index=i;
+ break;
+ }
+
+ if (rec_index==-1)
+ {
+ 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");
+ QMessageBox::critical(this, tr("Internal error"), tr("Wtf, some nasty internal error which is actually impossible occurred. Check console output. Nothing recorded."));
+ rec_part=NULL;
+ }
+ }
+ }
+
+ if (rec_part != NULL)
+ 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);
+ }
+ }
+}
+
+
+int DrumCanvas::pitch_and_track_to_instrument(int pitch, MusECore::Track* track)
+{
+ for (int i=0; i<instrument_map.size(); i++)
+ if (instrument_map[i].tracks.contains(track) && instrument_map[i].pitch==pitch)
+ return i;
+
+ if (heavyDebugMsg) printf("DrumCanvas::pitch_and_track_to_instrument() called with invalid arguments.\n");
+ return -1;
+}
+
+void DrumCanvas::propagate_drummap_change(int instr, bool update_druminmap)
+{
+ const QSet<MusECore::Track*>& tracks=instrument_map[instr].tracks;
+ int index=instrument_map[instr].pitch;
+
+ for (QSet<MusECore::Track*>::const_iterator it = tracks.begin(); it != tracks.end(); it++)
+ {
+ dynamic_cast<MusECore::MidiTrack*>(*it)->drummap()[index] = ourDrumMap[instr];
+ if (update_druminmap)
+ dynamic_cast<MusECore::MidiTrack*>(*it)->update_drum_in_map();
+ }
+}
+
+
+void DrumCanvas::rebuildOurDrumMap()
+{
+ using MusECore::drummaps_almost_equal;
+ using MusECore::Track;
+ using MusECore::MidiTrack;
+ using MusECore::TrackList;
+ using MusECore::ciTrack;
+ using MusECore::ciPart;
+ using MusECore::DrumMap;
+ using MusEGlobal::global_drum_ordering_t;
+ using MusEGlobal::global_drum_ordering;
+
+
+ if (!old_style_drummap_mode)
+ {
+ bool need_update = false;
+
+ TrackList* tl=MusEGlobal::song->tracks();
+ QList< QSet<Track*> > track_groups;
+ QVector<instrument_number_mapping_t> old_instrument_map = instrument_map;
+
+ instrument_map.clear();
+
+ for (ciTrack track = tl->begin(); track!=tl->end(); track++)
+ {
+ ciPart p_it;
+ for (p_it=drumEditor->parts()->begin(); p_it!=drumEditor->parts()->end(); p_it++)
+ if (p_it->second->track() == *track)
+ break;
+
+ if (p_it!=drumEditor->parts()->end()) // if *track is represented by some part in this editor
+ {
+ bool inserted=false;
+
+ switch (drumEditor->group_mode())
+ {
+ case DrumEdit::GROUP_SAME_CHANNEL:
+ for (QList< QSet<Track*> >::iterator group=track_groups.begin(); group!=track_groups.end(); group++)
+ if ( ((MidiTrack*)*group->begin())->outChannel() == ((MidiTrack*)*track)->outChannel() &&
+ ((MidiTrack*)*group->begin())->outPort() == ((MidiTrack*)*track)->outPort() &&
+ (drummaps_almost_equal(((MidiTrack*)*group->begin())->drummap(), ((MidiTrack*)*track)->drummap())) )
+ {
+ group->insert(*track);
+ inserted=true;
+ break;
+ }
+ break;
+
+ case DrumEdit::GROUP_MAX:
+ for (QList< QSet<Track*> >::iterator group=track_groups.begin(); group!=track_groups.end(); group++)
+ if (drummaps_almost_equal(((MidiTrack*)*group->begin())->drummap(), ((MidiTrack*)*track)->drummap()))
+ {
+ group->insert(*track);
+ inserted=true;
+ break;
+ }
+ break;
+
+ case DrumEdit::DONT_GROUP:
+ inserted=false;
+ break;
+
+ default:
+ printf("THIS SHOULD NEVER HAPPEN: group_mode() is invalid!\n");
+ inserted=false;
+ }
+
+ if (!inserted)
+ {
+ QSet<Track*> temp;
+ temp.insert(*track);
+ track_groups.push_back(temp);
+ }
}
+ }
+
+ // from now, we assume that every track_group's entry only groups tracks with identical
+ // drum maps, but not necessarily identical hide-lists together.
+ QList< std::pair<MidiTrack*,int> > ignore_order_entries;
+ for (global_drum_ordering_t::iterator order_it=global_drum_ordering.begin(); order_it!=global_drum_ordering.end(); order_it++)
+ {
+ // if this entry should be ignored, ignore it.
+ if (ignore_order_entries.contains(*order_it))
+ continue;
+
+ // look if we have order_it->first (the MidiTrack*) in any of our track groups
+ QList< QSet<Track*> >::iterator group;
+ for (group=track_groups.begin(); group!=track_groups.end(); group++)
+ if (group->contains(order_it->first))
+ break;
+
+ if (group!=track_groups.end()) // we have
+ {
+ int pitch=order_it->second;
+
+ bool mute=true;
+ bool hidden=true;
+
+ if (drumEditor->ignore_hide()) hidden=false;
+
+ for (QSet<Track*>::iterator track=group->begin(); track!=group->end() && (mute || hidden); track++)
+ {
+ if (dynamic_cast<MidiTrack*>(*track)->drummap()[pitch].mute == false)
+ mute=false;
+
+ if (dynamic_cast<MidiTrack*>(*track)->drummap_hidden()[pitch] == false)
+ hidden=false;
+ }
+
+ if (!hidden)
+ {
+ for (QSet<Track*>::iterator track=group->begin(); track!=group->end(); track++)
+ {
+ DrumMap* dm = &dynamic_cast<MidiTrack*>(*track)->drummap()[pitch];
+ if (dm->mute != mute)
+ {
+ dm->mute=mute;
+ need_update = true;
+ }
+ }
+
+ if (dynamic_cast<MidiTrack*>(*group->begin())->drummap()[pitch].anote != pitch)
+ printf("THIS SHOULD NEVER HAPPEN: track's_drummap[pitch].anote (%i)!= pitch (%i) !!!\n",dynamic_cast<MidiTrack*>(*group->begin())->drummap()[pitch].anote,pitch);
+
+ instrument_map.append(instrument_number_mapping_t(*group, pitch));
+ }
+
+ for (QSet<Track*>::iterator track=group->begin(); track!=group->end(); track++)
+ ignore_order_entries.append(std::pair<MidiTrack*,int>(dynamic_cast<MidiTrack*>(*track), pitch));
+ }
+ // else ignore it
+ }
+
+
+ // maybe delete and then populate ourDrumMap
+
+ if (must_delete_our_drum_map && ourDrumMap!=NULL)
+ delete [] ourDrumMap;
+
+ int size = instrument_map.size();
+ ourDrumMap=new DrumMap[size];
+ must_delete_our_drum_map=true;
+
+ for (int i=0;i<size;i++)
+ ourDrumMap[i] = dynamic_cast<MidiTrack*>(*instrument_map[i].tracks.begin())->drummap()[instrument_map[i].pitch];
+
+ if (instrument_map!=old_instrument_map)
+ {
+ if (debugMsg) printf("rebuilt drummap and instrument map, size is now %i\n",size);
+
+ songChanged(SC_EVENT_INSERTED); // force an update of the itemlist
+ emit ourDrumMapChanged(true);
+ }
+ else
+ emit ourDrumMapChanged(false);
+
+ if (need_update)
+ MusEGlobal::song->update(SC_DRUMMAP, true); // i know, this causes a recursion, which possibly
+ // isn't the most elegant solution here. but it will
+ // never be an infinite recursion
+ }
+}
} // namespace MusEGui