~ubuntu-branches/ubuntu/raring/muse/raring-proposed

« back to all changes in this revision

Viewing changes to muse/midiedit/dcanvas.cpp

  • Committer: Package Import Robot
  • Author(s): Alessio Treglia
  • Date: 2012-11-22 01:16:59 UTC
  • mto: This revision was merged to the branch mainline in revision 23.
  • Revision ID: package-import@ubuntu.com-20121122011659-a2fwbf33ceqe1s0t
Tags: upstream-2.1~rc1
ImportĀ upstreamĀ versionĀ 2.1~rc1

Show diffs side-by-side

added added

removed removed

Lines of Context:
22
22
 
23
23
#include <QPainter>
24
24
#include <QApplication>
 
25
#include <QMessageBox>
25
26
#include <QClipboard>
26
27
#include <QDrag>
27
28
#include <QDragLeaveEvent>
36
37
#include <stdio.h>
37
38
#include <limits.h>
38
39
#include <errno.h>
39
 
#include <set>
40
40
 
41
41
#include "dcanvas.h"
42
42
#include "midieditor.h"
 
43
#include "drumedit.h"
43
44
#include "drummap.h"
44
45
#include "event.h"
45
46
#include "mpevent.h"
50
51
#include "shortcuts.h"
51
52
#include "icons.h"
52
53
#include "functions.h"
 
54
#include "helper.h"
53
55
 
54
56
#define CARET   10
55
57
#define CARET2   5
56
58
 
 
59
using MusEGlobal::debugMsg;
 
60
using MusEGlobal::heavyDebugMsg;
 
61
 
57
62
namespace MusEGui {
58
63
 
59
64
//---------------------------------------------------------
60
65
//   DEvent
61
66
//---------------------------------------------------------
62
67
 
63
 
DEvent::DEvent(MusECore::Event e, MusECore::Part* p)
 
68
DEvent::DEvent(MusECore::Event e, MusECore::Part* p, int instr)
64
69
  : CItem(e, p)
65
70
      {
66
 
      int instr = e.pitch();
67
71
      int y  = instr * TH + TH/2;
68
72
      int tick = e.tick() + p->tick();
69
73
      setPos(QPoint(tick, y));
81
85
            return NULL;
82
86
      }
83
87
      
84
 
      DEvent* ev = new DEvent(event, part);
 
88
      int instr=pitch_and_track_to_instrument(event.pitch(), part->track());
 
89
      if (instr<0)
 
90
      {
 
91
        if (heavyDebugMsg) printf("trying to add event which is hidden or not in any part known to me\n");
 
92
        return NULL;
 
93
      }
 
94
      
 
95
      DEvent* ev = new DEvent(event, part, instr);
85
96
      items.add(ev);
86
97
      
87
98
      int diff = event.endTick()-part->lenTick();
105
116
   int sy, const char* name)
106
117
   : EventCanvas(pr, parent, sx, sy, name)
107
118
      {
 
119
      drumEditor=static_cast<DrumEdit*>(pr);
 
120
      
 
121
      _setCurPartIfOnlyOneEventIsSelected=false;
 
122
      
 
123
      old_style_drummap_mode = drumEditor->old_style_drummap_mode();
 
124
 
 
125
      if (old_style_drummap_mode)
 
126
      {
 
127
        if (debugMsg) printf("DrumCanvas in old style drummap mode\n");
 
128
        ourDrumMap = MusEGlobal::drumMap;
 
129
        must_delete_our_drum_map=false;
 
130
        
 
131
        instrument_number_mapping_t temp;
 
132
        for (MusECore::ciPart it=drumEditor->parts()->begin(); it!=drumEditor->parts()->end(); it++)
 
133
          temp.tracks.insert(it->second->track());
 
134
 
 
135
        for (int i=0;i<DRUM_MAPSIZE;i++)
 
136
        {
 
137
          temp.pitch=i;
 
138
          instrument_map.append(temp);
 
139
        }
 
140
      }
 
141
      else
 
142
      {
 
143
        if (debugMsg) printf("DrumCanvas in new style drummap mode\n");
 
144
        ourDrumMap=NULL;
 
145
        rebuildOurDrumMap();
 
146
      }
 
147
      
 
148
      
 
149
      
108
150
      setVirt(false);
109
151
      cursorPos= QPoint(0,0);
110
152
      _stepSize=1;
117
159
 
118
160
DrumCanvas::~DrumCanvas()
119
161
{
 
162
  
 
163
  if (must_delete_our_drum_map && ourDrumMap!=NULL)
 
164
    delete [] ourDrumMap;
 
165
  
 
166
  delete steprec;
120
167
}
121
168
 
122
169
//---------------------------------------------------------
196
243
                
197
244
                for(iCItem ici = items.begin(); ici != items.end(); ++ici) 
198
245
                {
199
 
                        CItem* ci = ici->second;
 
246
                        CItem* ci = ici->second;
200
247
                        
201
248
                        int x = ci->pos().x();
202
249
                        int y = ci->pos().y();
214
261
                        // Do not process if the event has already been processed (meaning it's an event in a clone part)...
215
262
                        if (idl == doneList.end())
216
263
                        {
217
 
                                operations.push_back(moveItem(ci, newpos, dtype));
 
264
                                if (moveItem(operations, ci, newpos, dtype) == false) //error?
 
265
        {
 
266
          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."));
 
267
          return MusECore::Undo(); //return empty list
 
268
        }
218
269
                                doneList.push_back(ci);
219
270
                        }
220
271
                        ci->move(newpos);
221
 
                                                
 
272
      
222
273
                        if(moving.size() == 1) 
223
274
                                                itemReleased(curItem, newpos);
224
275
 
246
297
//   moveItem
247
298
//---------------------------------------------------------
248
299
 
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)
250
301
      {
251
302
      DEvent* nevent   = (DEvent*) item;
252
303
      
253
 
      MusECore::MidiPart* part   = (MusECore::MidiPart*)nevent->part();   
 
304
      MusECore::MidiPart* part   = (MusECore::MidiPart*)nevent->part();
 
305
      MusECore::MidiPart* dest_part   = part;
254
306
      
 
307
      int nheight       = y2pitch(pos.y());
 
308
      if (nheight<0) nheight=0;
 
309
      if (nheight>=getOurDrumMapSize()) nheight=getOurDrumMapSize()-1;
 
310
            
 
311
      if (!instrument_map[nheight].tracks.contains(dest_part->track()))
 
312
      {
 
313
        if (debugMsg)
 
314
          printf("trying to move an event into a different track. checking if curPart is set correctly...\n");
 
315
        
 
316
        if (!instrument_map[nheight].tracks.contains(curPart->track()))
 
317
        {
 
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");
 
319
          return false;
 
320
        }
 
321
        else
 
322
          dest_part=(MusECore::MidiPart*)curPart;
 
323
      }
 
324
 
255
325
      MusECore::Event event      = nevent->event();
256
326
      int x            = pos.x();
257
327
      if (x < 0)
258
328
            x = 0;
259
 
      int ntick        = editor->rasterVal(x) - part->tick();
 
329
      int ntick        = editor->rasterVal(x) - dest_part->tick();
260
330
      if (ntick < 0)
261
331
            ntick = 0;
262
 
      int npitch       = y2pitch(pos.y());
263
332
      MusECore::Event newEvent   = event.clone();
264
333
 
265
 
      newEvent.setPitch(npitch);
 
334
      
 
335
      int ev_pitch = instrument_map[nheight].pitch;
 
336
      
 
337
      newEvent.setPitch(ev_pitch);
266
338
      newEvent.setTick(ntick);
267
339
 
268
340
      // don't check, whether the new event is within the part
270
342
      // resized yet. (flo93)
271
343
      
272
344
      if (dtype == MOVE_COPY || dtype == MOVE_CLONE)
273
 
            return MusECore::UndoOp(MusECore::UndoOp::AddEvent, newEvent, part, false, false);
 
345
            operations.push_back(MusECore::UndoOp(MusECore::UndoOp::AddEvent, newEvent, dest_part, false, false));
274
346
      else
275
 
            return MusECore::UndoOp(MusECore::UndoOp::ModifyEvent, newEvent, event, part, false, false);
 
347
      {
 
348
            if (dest_part == part)
 
349
                operations.push_back(MusECore::UndoOp(MusECore::UndoOp::ModifyEvent, newEvent, event, part, false, false));
 
350
            else
 
351
            {
 
352
                operations.push_back(MusECore::UndoOp(MusECore::UndoOp::DeleteEvent, event, part, false, false));
 
353
                operations.push_back(MusECore::UndoOp(MusECore::UndoOp::AddEvent, newEvent, dest_part, false, false));
 
354
            }
276
355
      }
 
356
      return true;
 
357
}
277
358
 
278
359
//---------------------------------------------------------
279
360
//   newItem
282
363
CItem* DrumCanvas::newItem(const QPoint& p, int state)
283
364
      {
284
365
      int instr = y2pitch(p.y());
285
 
      int velo  = MusEGlobal::drumMap[instr].lv4;
 
366
      if ((instr<0) || (instr>=getOurDrumMapSize()))
 
367
        return NULL;
 
368
      
 
369
      int velo  = ourDrumMap[instr].lv4;
286
370
      if (state == Qt::ShiftModifier)
287
 
            velo = MusEGlobal::drumMap[instr].lv3;
 
371
            velo = ourDrumMap[instr].lv3;
288
372
      else if (state == Qt::ControlModifier)
289
 
            velo = MusEGlobal::drumMap[instr].lv2;
 
373
            velo = ourDrumMap[instr].lv2;
290
374
      else if (state == (Qt::ControlModifier | Qt::ShiftModifier))
291
 
            velo = MusEGlobal::drumMap[instr].lv1;
 
375
            velo = ourDrumMap[instr].lv1;
292
376
      int tick = editor->rasterVal(p.x());
293
377
      return newItem(tick, instr, velo);
294
378
      }
299
383
 
300
384
CItem* DrumCanvas::newItem(int tick, int instrument, int velocity)
301
385
{
 
386
  if ((instrument<0) || (instrument>=getOurDrumMapSize()))
 
387
    return NULL;
 
388
 
 
389
  if (!old_style_drummap_mode && !instrument_map[instrument].tracks.contains(curPart->track()))
 
390
  {
 
391
    if (debugMsg)
 
392
      printf("tried to create a new Item which cannot be inside the current track. looking for destination part...\n");
 
393
    
 
394
    QSet<MusECore::Part*> parts = parts_at_tick(tick, instrument_map[instrument].tracks);
 
395
    
 
396
    if (parts.count() != 1)
 
397
    {
 
398
      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."));
 
399
      return NULL;
 
400
    }
 
401
    else
 
402
    {
 
403
      setCurrentPart(*parts.begin());
 
404
    }
 
405
  }
 
406
  // else or if we found an alternative part (which has now been set as curPart)
 
407
 
302
408
  tick    -= curPart->tick();
303
409
  if (tick < 0)
304
410
        //tick=0;
305
411
        return 0;
306
412
  MusECore::Event e(MusECore::Note);
307
413
  e.setTick(tick);
308
 
  e.setPitch(instrument);
 
414
  e.setPitch(instrument_map[instrument].pitch);
309
415
  e.setVelo(velocity);
310
 
  e.setLenTick(MusEGlobal::drumMap[instrument].len);
311
 
  return new DEvent(e, curPart);
 
416
  e.setLenTick(ourDrumMap[instrument].len);
 
417
 
 
418
  return new DEvent(e, curPart, instrument);
312
419
}
313
420
 
314
421
//---------------------------------------------------------
331
438
}
332
439
 
333
440
void DrumCanvas::newItem(CItem* item, bool noSnap, bool replace)
334
 
      {
 
441
{
 
442
   if (item)
 
443
   {
335
444
      DEvent* nevent = (DEvent*) item;
336
445
      MusECore::Event event    = nevent->event();
337
446
      int x = item->x();
341
450
            x = editor->rasterVal(x);
342
451
      event.setTick(x - nevent->part()->tick());
343
452
      int npitch = event.pitch();
344
 
      event.setPitch(npitch);
 
453
      //event.setPitch(npitch); // commented out by flo: has no effect
345
454
 
346
455
      // check for existing event
347
456
      //    if found change command semantic from insert to delete
375
484
      {
376
485
        operations.push_back(MusECore::UndoOp(MusECore::UndoOp::AddEvent,event, part, false, false));
377
486
        
378
 
        if (diff > 0)// part must be extended?
 
487
        if (diff > 0) // part must be extended?
379
488
        {
380
489
              schedule_resize_all_same_len_clone_parts(part, event.endTick(), operations);
381
490
              printf("newItem: extending\n");
385
494
      MusEGlobal::song->applyOperationGroup(operations);
386
495
      songChanged(SC_EVENT_INSERTED); //this forces an update of the itemlist, which is neccessary
387
496
                                      //to remove "forbidden" events from the list again
388
 
      }
 
497
   }
 
498
   else
 
499
    printf("THIS SHOULD NEVER HAPPEN: DrumCanvas::newItem called with NULL item!\n");
 
500
}
389
501
 
390
502
//---------------------------------------------------------
391
503
//   deleteItem
440
552
      else
441
553
      {
442
554
            int velo    = e->event().velo();
443
 
            MusECore::DrumMap* dm = &MusEGlobal::drumMap[y2pitch(y)]; //Get the drum item
 
555
            MusECore::DrumMap* dm = &ourDrumMap[y2pitch(y)]; //Get the drum item
444
556
            QColor color;
445
557
            if (velo < dm->lv1)
446
558
                  color.setRgb(240, 240, 255);
531
643
int DrumCanvas::y2pitch(int y) const
532
644
      {
533
645
      int pitch = y/TH;
534
 
      if (pitch >= DRUM_MAPSIZE)
535
 
            pitch = DRUM_MAPSIZE-1;
 
646
      if (pitch >= instrument_map.size())
 
647
            pitch = instrument_map.size()-1;
 
648
      else if (pitch<0)
 
649
            pitch = 0;
536
650
      return pitch;
537
651
      }
538
652
 
641
755
                              DEvent* devent = (DEvent*)(k->second);
642
756
                              MusECore::Event event    = devent->event();
643
757
                              MusECore::Event newEvent = event.clone();
644
 
                              newEvent.setLenTick(MusEGlobal::drumMap[event.pitch()].len);
 
758
                              // newEvent.setLenTick(drumMap[event.pitch()].len);
 
759
                              newEvent.setLenTick(ourDrumMap[y2pitch(devent->y())].len);
645
760
                              // Indicate no undo, and do not do port controller values and clone parts. 
646
761
                              MusEGlobal::audio->msgChangeEvent(event, newEvent, devent->part(), false, false, false);
647
762
                              }
744
859
//---------------------------------------------------------
745
860
 
746
861
void DrumCanvas::keyPressed(int index, int velocity)
747
 
      {
 
862
{
 
863
      using MusECore::MidiTrack;
 
864
      
 
865
      if ((index<0) || (index>=getOurDrumMapSize()))
 
866
        return;
 
867
      
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;
752
872
 
753
873
      // play note:
754
 
      MusECore::MidiPlayEvent e(0, port, channel, 0x90, pitch, velocity);
755
 
      MusEGlobal::audio->msgPlayMidiEvent(&e);
756
 
 
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);
759
 
            
 
874
      if(_playEvents)
 
875
      {
 
876
        MusECore::MidiPlayEvent e(0, port, channel, 0x90, pitch, velocity);
 
877
        MusEGlobal::audio->msgPlayMidiEvent(&e);
760
878
      }
 
879
      
 
880
      if (_steprec) /* && pos[0] >= start_tick && pos[0] < end_tick [removed by flo93: this is handled in steprec->record] */
 
881
      {
 
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 */);
 
884
        else
 
885
        {
 
886
          QSet<MusECore::Part*> parts = parts_at_tick(pos[0], instrument_map[index].tracks);
 
887
          
 
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."));
 
890
          else
 
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 */);
 
892
          
 
893
        }
 
894
      }            
 
895
}
761
896
 
762
897
//---------------------------------------------------------
763
898
//   keyReleased
765
900
 
766
901
void DrumCanvas::keyReleased(int index, bool)
767
902
      {
 
903
      using MusECore::MidiTrack;
 
904
      
 
905
      if ((index<0) || (index>=getOurDrumMapSize()))
 
906
        return;
 
907
      
768
908
      // called from DList - silence playing event
769
 
      int port = MusEGlobal::drumMap[index].port;
770
 
      int channel = MusEGlobal::drumMap[index].channel;
771
 
      int pitch = MusEGlobal::drumMap[index].anote;
 
909
      int port = old_style_drummap_mode ? ourDrumMap[index].port : dynamic_cast<MidiTrack*>(*instrument_map[index].tracks.begin())->outPort();
 
910
      int channel = old_style_drummap_mode ? ourDrumMap[index].channel : dynamic_cast<MidiTrack*>(*instrument_map[index].tracks.begin())->outChannel();
 
911
      int pitch = old_style_drummap_mode ? ourDrumMap[index].anote : instrument_map[index].pitch;
772
912
 
773
913
      // release note:
774
 
      MusECore::MidiPlayEvent e(0, port, channel, 0x90, pitch, 0);
775
 
      MusEGlobal::audio->msgPlayMidiEvent(&e);
 
914
      if(_playEvents)
 
915
      {
 
916
        MusECore::MidiPlayEvent e(0, port, channel, 0x90, pitch, 0);
 
917
        MusEGlobal::audio->msgPlayMidiEvent(&e);
 
918
      }
776
919
      }
777
920
 
778
921
//---------------------------------------------------------
780
923
//---------------------------------------------------------
781
924
 
782
925
void DrumCanvas::mapChanged(int spitch, int dpitch)
783
 
      {
 
926
{
 
927
   // spitch may be the same as dpitch! and something in here must be executed
 
928
   // even if they're same (i assume it's song->update(SC_DRUMMAP)) (flo93)
 
929
   
 
930
   if (old_style_drummap_mode)
 
931
   {
784
932
      MusECore::Undo operations;
785
933
      std::vector< std::pair<MusECore::Part*, MusECore::Event*> > delete_events;
786
934
      std::vector< std::pair<MusECore::Part*, MusECore::Event> > add_events;
858
1006
      
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()
 
1009
   }
 
1010
   else // if (!old_style_drummap_mode)
 
1011
   {
 
1012
      if (dpitch!=spitch)
 
1013
      {
 
1014
        using MusEGlobal::global_drum_ordering_t;
 
1015
        using MusEGlobal::global_drum_ordering;
 
1016
        
 
1017
        for (QSet<MusECore::Track*>::iterator it=instrument_map[spitch].tracks.begin();
 
1018
                                             it!=instrument_map[spitch].tracks.end(); it++)
 
1019
        {
 
1020
          if (dynamic_cast<MusECore::MidiTrack*>(*it))
 
1021
          dynamic_cast<MusECore::MidiTrack*>(*it)->set_drummap_ordering_tied_to_patch(false);
 
1022
        }
 
1023
        for (QSet<MusECore::Track*>::iterator it=instrument_map[dpitch].tracks.begin();
 
1024
                                             it!=instrument_map[dpitch].tracks.end(); it++)
 
1025
        {
 
1026
          if (dynamic_cast<MusECore::MidiTrack*>(*it))
 
1027
          dynamic_cast<MusECore::MidiTrack*>(*it)->set_drummap_ordering_tied_to_patch(false);
 
1028
        }
 
1029
        
 
1030
        MusECore::DrumMap dm_temp = ourDrumMap[spitch];
 
1031
        instrument_number_mapping_t im_temp = instrument_map[spitch];
 
1032
 
 
1033
        global_drum_ordering_t order_temp;
 
1034
        for (global_drum_ordering_t::iterator it=global_drum_ordering.begin(); it!=global_drum_ordering.end();)
 
1035
        {
 
1036
          if (im_temp.pitch==it->second && im_temp.tracks.contains(it->first))
 
1037
          {
 
1038
            order_temp.push_back(*it);
 
1039
            it=global_drum_ordering.erase(it);
 
1040
          }
 
1041
          else
 
1042
            it++;
 
1043
        }
 
1044
        
 
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())
 
1048
        {
 
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))
 
1051
            {
 
1052
              while (!order_temp.empty())
 
1053
                it=global_drum_ordering.insert(it, order_temp.takeLast());
 
1054
 
 
1055
              break;
 
1056
            }
 
1057
        }
 
1058
        else
 
1059
        {
 
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());
 
1063
        }
 
1064
 
 
1065
 
 
1066
 
 
1067
 
 
1068
 
 
1069
        if (dpitch > spitch)
 
1070
        {
 
1071
          for (int i=spitch; i<dpitch-1; i++)
 
1072
          {
 
1073
            ourDrumMap[i]=ourDrumMap[i+1];
 
1074
            instrument_map[i]=instrument_map[i+1];
 
1075
          }
 
1076
          
 
1077
          ourDrumMap[dpitch-1] = dm_temp;
 
1078
          instrument_map[dpitch-1] = im_temp;
 
1079
        }
 
1080
        else if (spitch > dpitch)
 
1081
        {
 
1082
          for (int i=spitch; i>dpitch; i--)
 
1083
          {
 
1084
            ourDrumMap[i]=ourDrumMap[i-1];
 
1085
            instrument_map[i]=instrument_map[i-1];
 
1086
          }
 
1087
          
 
1088
          ourDrumMap[dpitch] = dm_temp;
 
1089
          instrument_map[dpitch] = im_temp;
 
1090
        }
861
1091
      }
 
1092
      
 
1093
      
 
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
 
1097
   }
 
1098
}
862
1099
 
863
1100
//---------------------------------------------------------
864
1101
//   resizeEvent
944
1181
                        }
945
1182
                        break;
946
1183
                  case NoteInfo::VAL_PITCH:
 
1184
                        if (old_style_drummap_mode)
947
1185
                        {
948
1186
                        int pitch = val; 
949
1187
                        if(delta_mode)
954
1192
                              pitch = 0;
955
1193
                        newEvent.setPitch(pitch);
956
1194
                        }
 
1195
                        else
 
1196
                          printf("DrumCanvas::modifySelected - MusEWidget::NoteInfo::VAL_PITCH not implemented for new style drum editors\n");
957
1197
                        break;
958
1198
                  }
959
1199
            MusEGlobal::song->changeEvent(event, newEvent, part);
972
1212
 
973
1213
void DrumCanvas::curPartChanged()
974
1214
      {
 
1215
      EventCanvas::curPartChanged();
975
1216
      editor->setWindowTitle(getCaption());
976
1217
      }
977
1218
 
1033
1274
      return;
1034
1275
    }
1035
1276
    else if (key == shortcuts[SHRT_ADDNOTE_1].key) {
1036
 
          newItem(newItem(cursorPos.x(), cursorPos.y(), MusEGlobal::drumMap[cursorPos.y()].lv1),false,true);
1037
 
          keyPressed(cursorPos.y(), MusEGlobal::drumMap[cursorPos.y()].lv1);
 
1277
          newItem(newItem(cursorPos.x(), cursorPos.y(), ourDrumMap[cursorPos.y()].lv1),false,true);
 
1278
          keyPressed(cursorPos.y(), ourDrumMap[cursorPos.y()].lv1);
1038
1279
          keyReleased(cursorPos.y(), false);
1039
1280
          cursorPos.setX(getNextStep(cursorPos.x(),1, _stepSize));
1040
1281
          selectCursorEvent(getEventAtCursorPos());
1043
1284
          return;
1044
1285
    }
1045
1286
    else if (key == shortcuts[SHRT_ADDNOTE_2].key) {
1046
 
          newItem(newItem(cursorPos.x(), cursorPos.y(), MusEGlobal::drumMap[cursorPos.y()].lv2),false,true);
1047
 
          keyPressed(cursorPos.y(), MusEGlobal::drumMap[cursorPos.y()].lv2);
 
1287
          newItem(newItem(cursorPos.x(), cursorPos.y(), ourDrumMap[cursorPos.y()].lv2),false,true);
 
1288
          keyPressed(cursorPos.y(), ourDrumMap[cursorPos.y()].lv2);
1048
1289
          keyReleased(cursorPos.y(), false);
1049
1290
          cursorPos.setX(getNextStep(cursorPos.x(),1, _stepSize));
1050
1291
          selectCursorEvent(getEventAtCursorPos());
1053
1294
          return;
1054
1295
    }
1055
1296
    else if (key == shortcuts[SHRT_ADDNOTE_3].key) {
1056
 
          newItem(newItem(cursorPos.x(), cursorPos.y(), MusEGlobal::drumMap[cursorPos.y()].lv3),false,true);
1057
 
          keyPressed(cursorPos.y(), MusEGlobal::drumMap[cursorPos.y()].lv3);
 
1297
          newItem(newItem(cursorPos.x(), cursorPos.y(), ourDrumMap[cursorPos.y()].lv3),false,true);
 
1298
          keyPressed(cursorPos.y(), ourDrumMap[cursorPos.y()].lv3);
1058
1299
          keyReleased(cursorPos.y(), false);
1059
1300
          cursorPos.setX(getNextStep(cursorPos.x(),1, _stepSize));
1060
1301
          selectCursorEvent(getEventAtCursorPos());
1063
1304
          return;
1064
1305
    }
1065
1306
    else if (key == shortcuts[SHRT_ADDNOTE_4].key) {
1066
 
          newItem(newItem(cursorPos.x(), cursorPos.y(), MusEGlobal::drumMap[cursorPos.y()].lv4),false,true);
1067
 
          keyPressed(cursorPos.y(), MusEGlobal::drumMap[cursorPos.y()].lv4);
 
1307
          newItem(newItem(cursorPos.x(), cursorPos.y(), ourDrumMap[cursorPos.y()].lv4),false,true);
 
1308
          keyPressed(cursorPos.y(), ourDrumMap[cursorPos.y()].lv4);
1068
1309
          keyReleased(cursorPos.y(), false);
1069
1310
          cursorPos.setX(getNextStep(cursorPos.x(),1, _stepSize));
1070
1311
          selectCursorEvent(getEventAtCursorPos());
1112
1353
{
1113
1354
    if (_tool != CursorTool)
1114
1355
      return 0;
1115
 
    MusECore::EventList* el = curPart->events();
1116
 
    MusECore::iEvent lower  = el->lower_bound(cursorPos.x()-curPart->tick());
1117
 
    MusECore::iEvent upper  = el->upper_bound(cursorPos.x()-curPart->tick());
1118
 
    for (MusECore::iEvent i = lower; i != upper; ++i) {
1119
 
      MusECore::Event &ev = i->second;
1120
 
      if(!ev.isNote())
1121
 
        continue;
1122
 
      if (ev.pitch() == cursorPos.y()) {
1123
 
        return &ev;
 
1356
    if (instrument_map[cursorPos.y()].tracks.contains(curPart->track()))
 
1357
    {
 
1358
      MusECore::EventList* el = curPart->events();
 
1359
      MusECore::iEvent lower  = el->lower_bound(cursorPos.x()-curPart->tick());
 
1360
      MusECore::iEvent upper  = el->upper_bound(cursorPos.x()-curPart->tick());
 
1361
      int curPitch = instrument_map[cursorPos.y()].pitch;
 
1362
      for (MusECore::iEvent i = lower; i != upper; ++i) {
 
1363
        MusECore::Event &ev = i->second;
 
1364
        if (ev.isNote()  &&  ev.pitch() == curPitch)
 
1365
          return &ev;
1124
1366
      }
1125
1367
    }
 
1368
    // else or if the for loop didn't find anything
1126
1369
    return 0;
1127
1370
}
1128
1371
//---------------------------------------------------------
1146
1389
 
1147
1390
void DrumCanvas::moveAwayUnused()
1148
1391
{
1149
 
        using std::set;
 
1392
  if (!old_style_drummap_mode)
 
1393
  {
 
1394
    printf("THIS SHOULD NEVER HAPPEN: DrumCanvas::moveAwayUnused() cannot be used in new style mode\n");
 
1395
    return;
 
1396
  }
1150
1397
        
1151
 
        set<int> used;
 
1398
        QSet<int> used;
1152
1399
        for (iCItem it=items.begin(); it!=items.end(); it++)
1153
1400
        {
1154
1401
                const MusECore::Event& ev=it->second->event();
1158
1405
        }
1159
1406
        
1160
1407
        int count=0;
1161
 
        for (set<int>::iterator it=used.begin(); it!=used.end();)
 
1408
        for (QSet<int>::iterator it=used.begin(); it!=used.end();)
1162
1409
        {
1163
1410
                while ((*it != count) && (used.find(count)!=used.end())) count++;
1164
1411
                
1176
1423
//   midiNote
1177
1424
//---------------------------------------------------------
1178
1425
void DrumCanvas::midiNote(int pitch, int velo)
 
1426
{
 
1427
      using MusECore::Track;
 
1428
      using MusECore::Part;
 
1429
      
 
1430
      if (debugMsg) printf("DrumCanvas::midiNote: pitch=%i, velo=%i\n", pitch, velo);
 
1431
 
 
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()] */ )
1179
1433
      {
1180
 
      if (MusEGlobal::debugMsg) printf("DrumCanvas::midiNote: pitch=%i, velo=%i\n", pitch, velo);
1181
 
 
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
 
1435
         {
 
1436
           if (curPart)
 
1437
             steprec->record(curPart,0xdead,0xbeef,editor->raster(),velo,MusEGlobal::globalKeyState&Qt::ControlModifier,MusEGlobal::globalKeyState&Qt::ShiftModifier, pitch);
1187
1438
         }
1188
 
      }
 
1439
         else
 
1440
         {
 
1441
            QSet<Track*> possible_dest_tracks;
 
1442
            Part* rec_part=NULL;
 
1443
            int rec_index=-1;
 
1444
 
 
1445
            int ourDrumMapSize=getOurDrumMapSize();
 
1446
            int i;
 
1447
            for (i=0;i<ourDrumMapSize;i++)
 
1448
            {
 
1449
              if ( instrument_map[i].tracks.contains(curPart->track()) && ourDrumMap[i].enote==pitch)
 
1450
              {
 
1451
                rec_part=curPart;
 
1452
                rec_index=i;
 
1453
                break;
 
1454
              }
 
1455
              else if (ourDrumMap[i].enote==pitch)
 
1456
                possible_dest_tracks.unite(instrument_map[i].tracks);
 
1457
            }
 
1458
            
 
1459
            if (rec_part == NULL) // if recording to curPart isn't possible
 
1460
            {
 
1461
              QSet<Part*> possible_dest_parts = parts_at_tick(pos[0], possible_dest_tracks);
 
1462
              
 
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."));
 
1465
              else
 
1466
              {
 
1467
                rec_part = *possible_dest_parts.begin();
 
1468
                Track* dest_track=rec_part->track();
 
1469
                
 
1470
                for (i=0;i<ourDrumMapSize;i++)
 
1471
                  if ( instrument_map[i].tracks.contains(dest_track) && ourDrumMap[i].enote==pitch)
 
1472
                  {
 
1473
                    rec_index=i;
 
1474
                    break;
 
1475
                  }
 
1476
                
 
1477
                if (rec_index==-1)
 
1478
                {
 
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."));
 
1481
                  rec_part=NULL;
 
1482
                }
 
1483
              }
 
1484
            }
 
1485
            
 
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);
 
1488
         }   
 
1489
      }
 
1490
}
 
1491
 
 
1492
 
 
1493
int DrumCanvas::pitch_and_track_to_instrument(int pitch, MusECore::Track* track)
 
1494
{
 
1495
  for (int i=0; i<instrument_map.size(); i++)
 
1496
    if (instrument_map[i].tracks.contains(track) && instrument_map[i].pitch==pitch)
 
1497
      return i;
 
1498
  
 
1499
  if (heavyDebugMsg) printf("DrumCanvas::pitch_and_track_to_instrument() called with invalid arguments.\n");
 
1500
  return -1;
 
1501
}
 
1502
 
 
1503
void DrumCanvas::propagate_drummap_change(int instr, bool update_druminmap)
 
1504
{
 
1505
  const QSet<MusECore::Track*>& tracks=instrument_map[instr].tracks;
 
1506
  int index=instrument_map[instr].pitch;
 
1507
  
 
1508
  for (QSet<MusECore::Track*>::const_iterator it = tracks.begin(); it != tracks.end(); it++)
 
1509
  {
 
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();
 
1517
  }
 
1518
}
 
1519
 
 
1520
 
 
1521
void DrumCanvas::rebuildOurDrumMap()
 
1522
{
 
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;
 
1532
  
 
1533
  
 
1534
  if (!old_style_drummap_mode)
 
1535
  {
 
1536
    bool need_update = false;
 
1537
    
 
1538
    TrackList* tl=MusEGlobal::song->tracks();
 
1539
    QList< QSet<Track*> > track_groups;
 
1540
    QVector<instrument_number_mapping_t> old_instrument_map = instrument_map;
 
1541
    
 
1542
    instrument_map.clear();
 
1543
 
 
1544
    for (ciTrack track = tl->begin(); track!=tl->end(); track++)
 
1545
    {
 
1546
      ciPart p_it;
 
1547
      for (p_it=drumEditor->parts()->begin(); p_it!=drumEditor->parts()->end(); p_it++)
 
1548
        if (p_it->second->track() == *track)
 
1549
          break;
 
1550
      
 
1551
      if (p_it!=drumEditor->parts()->end()) // if *track is represented by some part in this editor
 
1552
      {
 
1553
        bool inserted=false;
 
1554
        
 
1555
        switch (drumEditor->group_mode())
 
1556
        {
 
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())) )
 
1562
              {
 
1563
                group->insert(*track);
 
1564
                inserted=true;
 
1565
                break;
 
1566
              }
 
1567
            break;
 
1568
          
 
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()))
 
1572
              {
 
1573
                group->insert(*track);
 
1574
                inserted=true;
 
1575
                break;
 
1576
              }
 
1577
            break;
 
1578
          
 
1579
          case DrumEdit::DONT_GROUP: 
 
1580
            inserted=false;
 
1581
            break;
 
1582
          
 
1583
          default:
 
1584
            printf("THIS SHOULD NEVER HAPPEN: group_mode() is invalid!\n");
 
1585
            inserted=false;
 
1586
        }
 
1587
 
 
1588
        if (!inserted)
 
1589
        {
 
1590
          QSet<Track*> temp;
 
1591
          temp.insert(*track);
 
1592
          track_groups.push_back(temp);
 
1593
        }
 
1594
      }
 
1595
    }
 
1596
 
 
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++)
 
1601
    {
 
1602
      // if this entry should be ignored, ignore it.
 
1603
      if (ignore_order_entries.contains(*order_it))
 
1604
        continue;
 
1605
      
 
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))
 
1610
          break;
 
1611
      
 
1612
      if (group!=track_groups.end()) // we have
 
1613
      {
 
1614
        int pitch=order_it->second;
 
1615
        
 
1616
        bool mute=true;
 
1617
        bool hidden=true;
 
1618
        
 
1619
        if (drumEditor->ignore_hide()) hidden=false;
 
1620
        
 
1621
        for (QSet<Track*>::iterator track=group->begin(); track!=group->end() && (mute || hidden); track++)
 
1622
        {
 
1623
          if (dynamic_cast<MidiTrack*>(*track)->drummap()[pitch].mute == false)
 
1624
            mute=false;
 
1625
          
 
1626
          if (dynamic_cast<MidiTrack*>(*track)->drummap_hidden()[pitch] == false)
 
1627
            hidden=false;
 
1628
        }
 
1629
 
 
1630
        if (!hidden)
 
1631
        {
 
1632
          for (QSet<Track*>::iterator track=group->begin(); track!=group->end(); track++)
 
1633
          {
 
1634
            DrumMap* dm = &dynamic_cast<MidiTrack*>(*track)->drummap()[pitch];
 
1635
            if (dm->mute != mute)
 
1636
            {
 
1637
              dm->mute=mute; 
 
1638
              need_update = true;
 
1639
            }
 
1640
          }
 
1641
          
 
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);
 
1644
          
 
1645
          instrument_map.append(instrument_number_mapping_t(*group, pitch));
 
1646
        }
 
1647
        
 
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));
 
1650
      }
 
1651
      // else ignore it
 
1652
    }
 
1653
 
 
1654
 
 
1655
    // maybe delete and then populate ourDrumMap
 
1656
    
 
1657
    if (must_delete_our_drum_map && ourDrumMap!=NULL)
 
1658
      delete [] ourDrumMap;
 
1659
    
 
1660
    int size = instrument_map.size();
 
1661
    ourDrumMap=new DrumMap[size];
 
1662
    must_delete_our_drum_map=true;
 
1663
 
 
1664
    for (int i=0;i<size;i++)
 
1665
      ourDrumMap[i] = dynamic_cast<MidiTrack*>(*instrument_map[i].tracks.begin())->drummap()[instrument_map[i].pitch];  
 
1666
    
 
1667
    if (instrument_map!=old_instrument_map)
 
1668
    {
 
1669
      if (debugMsg) printf("rebuilt drummap and instrument map, size is now %i\n",size);
 
1670
    
 
1671
      songChanged(SC_EVENT_INSERTED); // force an update of the itemlist
 
1672
      emit ourDrumMapChanged(true);
 
1673
    }
 
1674
    else
 
1675
      emit ourDrumMapChanged(false);
 
1676
    
 
1677
    if (need_update)
 
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
 
1681
  }
 
1682
}
1189
1683
 
1190
1684
} // namespace MusEGui