~ubuntu-branches/ubuntu/karmic/muse/karmic-proposed

« back to all changes in this revision

Viewing changes to ctrl/ctrlcanvas.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Daniel Kobras
  • Date: 2002-04-23 17:28:23 UTC
  • Revision ID: james.westby@ubuntu.com-20020423172823-w8yplzr81a759xa3
Tags: upstream-0.5.2
ImportĀ upstreamĀ versionĀ 0.5.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
//=========================================================
 
2
//  MusE
 
3
//  Linux Music Editor
 
4
//    $Id: ctrlcanvas.cpp,v 1.3 2002/02/07 10:02:48 muse Exp $
 
5
//  (C) Copyright 1999 Werner Schweer (ws@seh.de)
 
6
//=========================================================
 
7
 
 
8
#include <stdio.h>
 
9
 
 
10
#include <qlayout.h>
 
11
#include <qpainter.h>
 
12
#include <qtoolbutton.h>
 
13
#include <qpopupmenu.h>
 
14
#include <qlabel.h>
 
15
#include <qcursor.h>
 
16
 
 
17
#include "ctrledit.h"
 
18
#include "midieditor.h"
 
19
#include "icons.h"
 
20
#include "event.h"
 
21
#include "midiport.h"
 
22
#include "midithread.h"
 
23
 
 
24
extern void drawTickRaster(QPainter& p, int x, int y,
 
25
   int w, int h, int quant);
 
26
 
 
27
//---------------------------------------------------------
 
28
//   CEvent
 
29
//---------------------------------------------------------
 
30
 
 
31
CEvent::CEvent(MidiEvent* e, MidiPart* pt, int v)
 
32
      {
 
33
      _event = e;
 
34
      _part  = pt;
 
35
      _val   = v;
 
36
      ex     = e ? e->posTick() : 0;
 
37
      }
 
38
 
 
39
//---------------------------------------------------------
 
40
//   contains
 
41
//---------------------------------------------------------
 
42
 
 
43
bool CEvent::contains(int x1, int x2) const
 
44
      {
 
45
      int tick = _event ? _event->posTick() : 0;
 
46
      return ((tick >= x1 && tick < x2)
 
47
         || (ex >= x1 && ex < x2)
 
48
         || (tick < x1 && ex >= x2));
 
49
      }
 
50
 
 
51
//---------------------------------------------------------
 
52
//   CtrlCanvas
 
53
//---------------------------------------------------------
 
54
 
 
55
CtrlCanvas::CtrlCanvas(MidiEditor* e, QWidget* parent, int xmag,
 
56
   const char* name = 0) : View(parent, xmag, 1, name)
 
57
      {
 
58
      setBg(white);
 
59
      editor = e;
 
60
      drag   = DRAG_OFF;
 
61
      tool   = PointerTool;
 
62
      pos[0] = 0;
 
63
      pos[1] = 0;
 
64
      pos[2] = 0;
 
65
      connect(song, SIGNAL(posChanged(int, int, bool)), this, SLOT(setPos(int, int, bool)));
 
66
 
 
67
      setMouseTracking(true);
 
68
      if (editor->parts()->empty()) {
 
69
            curPart = 0;
 
70
            curTrack = 0;
 
71
            }
 
72
      else {
 
73
            curPart  = (MidiPart*)(editor->parts()->begin()->second);
 
74
            curTrack = (MidiTrack*)(curPart->track());
 
75
            }
 
76
      connect(song, SIGNAL(songChanged(int)), SLOT(songChanged(int)));
 
77
      songChanged(SC_TRACK_INSERTED);
 
78
      }
 
79
 
 
80
//---------------------------------------------------------
 
81
//   setPos
 
82
//    set one of three markers
 
83
//    idx   - 0-cpos  1-lpos  2-rpos
 
84
//    flag  - emit followEvent()
 
85
//---------------------------------------------------------
 
86
 
 
87
void CtrlCanvas::setPos(int idx, int val, bool adjustScrollbar)
 
88
      {
 
89
#if 1
 
90
//      printf("ctrlCanvas: setPos %d %d\n", idx, val);
 
91
      if (pos[idx] == val)
 
92
            return;
 
93
 
 
94
      int opos = mapx(pos[idx]);
 
95
      int npos = mapx(val);
 
96
 
 
97
      if (adjustScrollbar && idx == 0) {
 
98
            switch (song->follow()) {
 
99
                  case  Song::NO:
 
100
                        break;
 
101
                  case Song::JUMP:
 
102
                        if (npos >= width()) {
 
103
                              int ppos =  val - rmapxDev(width()/4);
 
104
                              if (ppos < 0)
 
105
                                    ppos = 0;
 
106
                              emit followEvent(ppos);
 
107
                              opos = mapx(pos[idx]);
 
108
                              npos = mapx(val);
 
109
                              }
 
110
                        else if (npos < 0) {
 
111
                              int ppos =  val - rmapxDev(width()*3/4);
 
112
                              if (ppos < 0)
 
113
                                    ppos = 0;
 
114
                              emit followEvent(ppos);
 
115
                              opos = mapx(pos[idx]);
 
116
                              npos = mapx(val);
 
117
                              }
 
118
                        break;
 
119
                  case Song::CONTINUOUS:
 
120
                        if (npos > (width()*5)/8) {
 
121
                              int ppos =  pos[idx] - rmapxDev(width()*5/8);
 
122
                              if (ppos < 0)
 
123
                                    ppos = 0;
 
124
                              emit followEvent(ppos);
 
125
                              opos = mapx(pos[idx]);
 
126
                              npos = mapx(val);
 
127
                              }
 
128
                        else if (npos < (width()*3)/8) {
 
129
                              int ppos =  pos[idx] - rmapxDev(width()*3/8);
 
130
                              if (ppos < 0)
 
131
                                    ppos = 0;
 
132
                              emit followEvent(ppos);
 
133
                              opos = mapx(pos[idx]);
 
134
                              npos = mapx(val);
 
135
                              }
 
136
                        break;
 
137
                  }
 
138
            }
 
139
 
 
140
      int x;
 
141
      int w = 1;
 
142
      if (opos > npos) {
 
143
            w += opos - npos;
 
144
            x = npos;
 
145
            }
 
146
      else {
 
147
            w += npos - opos;
 
148
            x = opos;
 
149
            }
 
150
      pos[idx] = val;
 
151
//printf("    redraw %d %d %d %d\n", x, 0, w, height());
 
152
      redraw(QRect(x, 0, w, height()));
 
153
 
 
154
#else
 
155
      if (pos[idx] == val)
 
156
            return;
 
157
 
 
158
      int opos = mapx(pos[idx]);
 
159
      pos[idx] = val;
 
160
 
 
161
      if (!isVisible())
 
162
            return;
 
163
      val = mapx(val);
 
164
      if (adjustScrollbar && idx == 0) {
 
165
            switch (song->follow()) {
 
166
                  case  Song::NO:
 
167
                        break;
 
168
                  case Song::JUMP:
 
169
                        if (val >= width()) {
 
170
                              emit followEvent(val);
 
171
                              return;
 
172
                              }
 
173
                        break;
 
174
                  case Song::CONTINUOUS:
 
175
                        if (val > width()/2) {
 
176
                              int ppos =  pos[idx] - rmapxDev(width()/2);
 
177
                              if (ppos < 0)
 
178
                                    ppos = 0;
 
179
                              emit followEvent(ppos);
 
180
                              return;
 
181
                              }
 
182
                        break;
 
183
                  }
 
184
            }
 
185
      int x;
 
186
      int w = 1;
 
187
      if (opos > val) {
 
188
            w += opos - val;
 
189
            x = val;
 
190
            }
 
191
      else {
 
192
            w += val - opos;
 
193
            x = opos;
 
194
            }
 
195
      paint(QRect(x, 0, w, height()));
 
196
#endif
 
197
      }
 
198
 
 
199
//---------------------------------------------------------
 
200
//   setCtrlType
 
201
//---------------------------------------------------------
 
202
 
 
203
void CtrlCanvas::setController(const MidiController& c)
 
204
      {
 
205
      ctrl = c;
 
206
      songChanged(-1);
 
207
      }
 
208
 
 
209
//---------------------------------------------------------
 
210
//   leaveEvent
 
211
//---------------------------------------------------------
 
212
 
 
213
void CtrlCanvas::leaveEvent(QEvent*)
 
214
      {
 
215
      emit xposChanged(-1);
 
216
      emit yposChanged(-1);
 
217
      }
 
218
 
 
219
QPoint CtrlCanvas::raster(const QPoint& p) const
 
220
      {
 
221
      return p;
 
222
      }
 
223
 
 
224
//---------------------------------------------------------
 
225
//   deselectAll
 
226
//---------------------------------------------------------
 
227
 
 
228
void CtrlCanvas::deselectAll()
 
229
      {
 
230
//    for (iCEvent i = selection.begin(); i != selection.end(); ++i)
 
231
//            (*i)->setState(CEvent::Normal);
 
232
//      selection.clear();
 
233
//      update();
 
234
      }
 
235
 
 
236
//---------------------------------------------------------
 
237
//   selectItem
 
238
//---------------------------------------------------------
 
239
 
 
240
void CtrlCanvas::selectItem(CEvent*)
 
241
      {
 
242
//      e->setState(CEvent::Selected);
 
243
//      selection.push_back(e);
 
244
//      update();
 
245
      }
 
246
 
 
247
//---------------------------------------------------------
 
248
//   deselectItem
 
249
//---------------------------------------------------------
 
250
 
 
251
void CtrlCanvas::deselectItem(CEvent*)
 
252
      {
 
253
/*      e->setState(CEvent::Normal);
 
254
      for (iCEvent i = selection.begin(); i != selection.end(); ++i) {
 
255
            if (*i == e) {
 
256
                  selection.erase(i);
 
257
                  break;
 
258
                  }
 
259
            }
 
260
      update();
 
261
      */
 
262
      }
 
263
 
 
264
//---------------------------------------------------------
 
265
//   songChanged
 
266
//    alle markierten Parts werden hier
 
267
//    in die interne Eventliste aufgenommen
 
268
//---------------------------------------------------------
 
269
 
 
270
void CtrlCanvas::songChanged(int)
 
271
      {
 
272
      if (editor->parts()->empty())
 
273
            return;
 
274
      items.clear();
 
275
 
 
276
      MidiPort* port = &midiPorts[curTrack->outPort()];
 
277
 
 
278
      //---------------------------------------------------
 
279
      //    get initial controller value
 
280
      //---------------------------------------------------
 
281
 
 
282
      int val = 0;
 
283
      ChannelState* ics = port->iState(curTrack->outChannel());
 
284
      switch(ctrl.type()) {
 
285
            case MidiController::Controller7:
 
286
                  val = ics->controller[ctrl.hnum()];
 
287
                  break;
 
288
            case MidiController::Controller14:
 
289
                  {
 
290
                  int hval = ics->controller[ctrl.hnum()];
 
291
                  int lval = ics->controller[ctrl.lnum()];
 
292
                  if (hval == -1 && lval == -1)
 
293
                        val = -1;
 
294
                  else {
 
295
                        if (hval == -1)
 
296
                              hval = 0;
 
297
                        if (lval == -1)
 
298
                              lval = 0;
 
299
                        val = (hval << 7) + lval;
 
300
                        }
 
301
                  }
 
302
                  break;
 
303
            case MidiController::RPN:
 
304
            case MidiController::NRPN:
 
305
                  // TODO
 
306
                  break;
 
307
            case MidiController::Pitch:
 
308
                  val = ics->pitch;
 
309
                  break;
 
310
            case MidiController::XgSysex:
 
311
            case MidiController::Sysex:
 
312
                  // TODO
 
313
                  break;
 
314
            case MidiController::Velo:
 
315
                  break;
 
316
            }
 
317
 
 
318
      MidiEvent* last = 0;
 
319
      CEvent* lastce  = 0;
 
320
 
 
321
      for (iPart p = editor->parts()->begin(); p != editor->parts()->end(); ++p) {
 
322
            MidiPart* part = (MidiPart*)(p->second);
 
323
            EventList* el = part->events();
 
324
            for (iEvent i = el->begin(); i != el->end(); ++i) {
 
325
                  MidiEvent* e = (MidiEvent*)i->second;
 
326
                  switch(ctrl.type()) {
 
327
                        case MidiController::Velo:
 
328
                              if (e->type() != MidiEvent::Note)
 
329
                                    break;
 
330
                              items.add(new CEvent(e, part, e->velo()));
 
331
                              break;
 
332
                        case MidiController::Controller7:
 
333
                              if (e->type() != MidiEvent::Ctrl7)
 
334
                                    break;
 
335
                              if (e->cntrl() != ctrl.hnum())
 
336
                                    break;
 
337
                              if (last == 0) {
 
338
                                    lastce = new CEvent(0, part, val);
 
339
                                    items.add(lastce);
 
340
                                    }
 
341
                              if (lastce)
 
342
                                    lastce->setEX(e->posTick());
 
343
                              lastce = new CEvent(e, part, e->cntrlVal());
 
344
                              items.add(lastce);
 
345
                              last = e;
 
346
                              break;
 
347
                        case MidiController::Controller14:
 
348
                              if (e->type() != MidiEvent::Ctrl14)
 
349
                                    break;
 
350
                              if ((e->dataA() != ctrl.hnum()) || (e->dataC() != ctrl.lnum()))
 
351
                                    break;
 
352
                              if (last == 0) {
 
353
                                    lastce = new CEvent(0, part, val);
 
354
                                    items.add(lastce);
 
355
                                    }
 
356
                              if (lastce)
 
357
                                    lastce->setEX(e->posTick());
 
358
                              lastce = new CEvent(e, part, e->dataB());
 
359
                              items.add(lastce);
 
360
                              last = e;
 
361
                              break;
 
362
                        case MidiController::Pitch:
 
363
                              if (e->type() != MidiEvent::Pitch)
 
364
                                    break;
 
365
                              if (last == 0) {
 
366
                                    lastce = new CEvent(0, part, val);
 
367
                                    items.add(lastce);
 
368
                                    }
 
369
                              if (lastce)
 
370
                                    lastce->setEX(e->posTick());
 
371
                              lastce = new CEvent(e, part, e->dataA());
 
372
                              items.add(lastce);
 
373
                              last = e;
 
374
                              break;
 
375
                        default:
 
376
                              break;
 
377
                        }
 
378
                  }
 
379
            }
 
380
      redraw();
 
381
      }
 
382
 
 
383
//---------------------------------------------------------
 
384
//   viewMousePressEvent
 
385
//---------------------------------------------------------
 
386
 
 
387
void CtrlCanvas::viewMousePressEvent(QMouseEvent* event)
 
388
      {
 
389
      start = event->pos();
 
390
      Tool activeTool = tool;
 
391
      bool shift = event->state() & ShiftButton;
 
392
 
 
393
      int xpos = start.x();
 
394
      int ypos = start.y();
 
395
 
 
396
      switch (activeTool) {
 
397
            case PointerTool:
 
398
                  drag = DRAG_LASSO_START;
 
399
                  break;
 
400
 
 
401
            case PencilTool:
 
402
                  if (shift) {
 
403
                        if (ctrl.type() != MidiController::Velo) {
 
404
                              drag = DRAG_NEW;
 
405
                              song->startUndo();
 
406
                              newVal(xpos, xpos, ypos);
 
407
                              }
 
408
                        }
 
409
                  else {
 
410
                        drag = DRAG_RESIZE;
 
411
                        song->startUndo();
 
412
                        changeVal(xpos, xpos, ypos);
 
413
                        }
 
414
                  break;
 
415
 
 
416
            case RubberTool:
 
417
                  if (ctrl.type() != MidiController::Velo) {
 
418
                        drag = DRAG_DELETE;
 
419
                        song->startUndo();
 
420
                        deleteVal(xpos, xpos, ypos);
 
421
                        }
 
422
                  break;
 
423
 
 
424
            case DrawTool:
 
425
                  if (drawLineMode) {
 
426
                        line2x = xpos;
 
427
                        line2y = ypos;
 
428
                        if (shift)
 
429
                              newValRamp(line1x, line1y, line2x, line2y);
 
430
                        else
 
431
                              changeValRamp(line1x, line1y, line2x, line2y);
 
432
                        drawLineMode = false;
 
433
                        }
 
434
                  else {
 
435
                        line2x = line1x = xpos;
 
436
                        line2y = line1y = ypos;
 
437
                        drawLineMode = true;
 
438
                        }
 
439
                  redraw();
 
440
                  break;
 
441
 
 
442
            default:
 
443
                  break;
 
444
            }
 
445
      }
 
446
 
 
447
//---------------------------------------------------------
 
448
//   newValRamp
 
449
//---------------------------------------------------------
 
450
 
 
451
void CtrlCanvas::newValRamp(int x1, int y1, int x2, int y2)
 
452
      {
 
453
      int xx1 = editor->rasterVal1(x1);
 
454
      int xx2 = editor->rasterVal2(x2);
 
455
      int min = ctrl.minVal();
 
456
      int max = ctrl.maxVal();
 
457
      int h   = height();
 
458
 
 
459
      int raster = editor->raster();
 
460
      if (raster == 1)          // set reasonable raster
 
461
            raster = division/4;
 
462
 
 
463
      song->startUndo();
 
464
 
 
465
      // delete existing events
 
466
 
 
467
      for (ciCEvent i = items.begin(); i != items.end(); ++i) {
 
468
            CEvent* ev = *i;
 
469
            MidiEvent* event = ev->event();
 
470
            if (event == 0)
 
471
                  continue;
 
472
            int x = event->posTick();
 
473
            if (x < xx1)
 
474
                  continue;
 
475
            if (x >= xx2)
 
476
                  break;
 
477
            midiThread->msgDeleteEvent(event, ev->part(), false);
 
478
            }
 
479
 
 
480
      // insert new events
 
481
      for (int x = xx1; x < xx2; x += raster) {
 
482
            int y = (x2==x1) ? y1 : (((y2-y1)*(x-x1))/(x2-x1))+y1;
 
483
            int nval = (((h - y) *  (max-min)) / h) + min;
 
484
            if (nval > max)
 
485
                  nval = max;
 
486
 
 
487
            MidiEvent* event = 0;
 
488
            switch(ctrl.type()) {
 
489
                  case MidiController::Controller7:
 
490
                        event = new MidiEvent(
 
491
                           curTrack->outPort(), curTrack->outChannel(),
 
492
                           x, MidiEvent::Ctrl7, ctrl.hnum(), nval, 0, 0);
 
493
                        break;
 
494
                  case MidiController::Controller14:
 
495
                        event = new MidiEvent(
 
496
                           curTrack->outPort(), curTrack->outChannel(),
 
497
                           x, MidiEvent::Ctrl14, ctrl.hnum(), nval, ctrl.lnum(), 0);
 
498
                        break;
 
499
                  case MidiController::RPN:
 
500
                        event = new MidiEvent(
 
501
                           curTrack->outPort(), curTrack->outChannel(),
 
502
                           x, MidiEvent::RPN, ctrl.hnum()*128+ctrl.lnum(), nval, 0, 0);
 
503
                        break;
 
504
                  case MidiController::NRPN:
 
505
                        event = new MidiEvent(
 
506
                           curTrack->outPort(), curTrack->outChannel(),
 
507
                           x, MidiEvent::RPN, ctrl.hnum()*128+ctrl.lnum(), nval, 0, 0);
 
508
                        break;
 
509
                  case MidiController::XgSysex:
 
510
                  case MidiController::Sysex:
 
511
                        break;
 
512
                  case MidiController::Pitch:
 
513
                        event = new MidiEvent(
 
514
                           curTrack->outPort(), curTrack->outChannel(),
 
515
                           x, MidiEvent::Pitch, nval, 0, 0, 0);
 
516
                        break;
 
517
                  case MidiController::Velo:
 
518
                        break;
 
519
                  }
 
520
            if (event) {
 
521
                  midiThread->msgAddEvent(event, curPart, false);
 
522
                  }
 
523
            }
 
524
      song->update(0);
 
525
      redraw();
 
526
      song->endUndo(SC_EVENT_MODIFIED | SC_EVENT_INSERTED | SC_EVENT_REMOVED);
 
527
      }
 
528
 
 
529
//---------------------------------------------------------
 
530
//   changeValRamp
 
531
//---------------------------------------------------------
 
532
 
 
533
void CtrlCanvas::changeValRamp(int x1, int y1, int x2, int y2)
 
534
      {
 
535
      int h   = height();
 
536
      int min = ctrl.minVal();
 
537
      int max = ctrl.maxVal();
 
538
      bool changed = false;
 
539
 
 
540
      song->startUndo();
 
541
      for (ciCEvent i = items.begin(); i != items.end(); ++i) {
 
542
            if ((*i)->contains(x1, x2)) {
 
543
                  CEvent* ev       = *i;
 
544
                  MidiEvent* event = ev->event();
 
545
                  if (event == 0)
 
546
                        continue;
 
547
 
 
548
                  MidiPart* part   = ev->part();
 
549
 
 
550
                  int x = event->posTick();
 
551
                  int y = (x2==x1) ? y1 : (((y2-y1)*(x-x1))/(x2-x1))+y1;
 
552
                  int nval = (((h - y) *  (max-min)) / h) + min;
 
553
                  if (nval > max)
 
554
                        nval = max;
 
555
 
 
556
                  ev->setVal(nval);
 
557
                  if (ctrl.type() == MidiController::Velo) {
 
558
                        if ((event->velo() != nval)) {
 
559
                              MidiEvent* newEvent = new MidiEvent(*event);
 
560
                              newEvent->setVelo(nval);
 
561
                              midiThread->msgChangeEvent(event, newEvent, part, false);
 
562
                              ev->setEvent(newEvent);
 
563
                              changed = true;
 
564
                              }
 
565
                        }
 
566
                  else if (ctrl.type() == MidiController::Controller7) {
 
567
                        if (event) {
 
568
                              if ((event->cntrlVal() != nval)) {
 
569
                                    MidiEvent* newEvent = new MidiEvent(*event);
 
570
                                    newEvent->setB(nval);
 
571
                                    midiThread->msgChangeEvent(event, newEvent, part, false);
 
572
                                    ev->setEvent(newEvent);
 
573
                                    changed = true;
 
574
                                    }
 
575
                              }
 
576
                        else {
 
577
                              MidiPort* port = &midiPorts[curTrack->outPort()];
 
578
                              int channel = curTrack->outChannel();
 
579
                              int oval = port->iState(channel)->controller[ctrl.hnum()];
 
580
                              if (oval != nval) {
 
581
                                    port->iState(channel)->controller[ctrl.hnum()] = nval;
 
582
                                    changed = true;
 
583
                                    }
 
584
                              }
 
585
                        }
 
586
                  }
 
587
            }
 
588
      if (changed)
 
589
            redraw();
 
590
      song->endUndo(SC_EVENT_MODIFIED);
 
591
      }
 
592
 
 
593
//---------------------------------------------------------
 
594
//   viewMouseMoveEvent
 
595
//---------------------------------------------------------
 
596
 
 
597
void CtrlCanvas::viewMouseMoveEvent(QMouseEvent* event)
 
598
      {
 
599
      QPoint pos  = event->pos();
 
600
      QPoint dist = pos - start;
 
601
      bool moving = dist.y() >= 3 || dist.y() <= 3 || dist.x() >= 3 || dist.x() <= 3;
 
602
      switch (drag) {
 
603
            case DRAG_LASSO_START:
 
604
                  if (!moving)
 
605
                        break;
 
606
                  drag = DRAG_LASSO;
 
607
                  // weiter mit DRAG_LASSO:
 
608
            case DRAG_LASSO:
 
609
                  lasso.setRect(start.x(), start.y(), dist.x(), dist.y());
 
610
                  redraw();
 
611
                  break;
 
612
            case DRAG_RESIZE:
 
613
                  changeVal(start.x(), pos.x(), pos.y());
 
614
                  start = pos;
 
615
                  break;
 
616
 
 
617
            case DRAG_NEW:
 
618
                  newVal(start.x(), pos.x(), pos.y());
 
619
                  start = pos;
 
620
                  break;
 
621
 
 
622
            case DRAG_DELETE:
 
623
                  deleteVal(start.x(), pos.x(), pos.y());
 
624
                  start = pos;
 
625
                  break;
 
626
 
 
627
            default:
 
628
                  break;
 
629
            }
 
630
      if (tool == DrawTool && drawLineMode) {
 
631
            line2x = pos.x();
 
632
            line2y = pos.y();
 
633
            redraw();
 
634
            }
 
635
      emit xposChanged(pos.x());
 
636
      int min = ctrl.minVal();
 
637
      int max = ctrl.maxVal();
 
638
      int val = max - (pos.y() * (max-min) / height());
 
639
      if (val < min)
 
640
            val = min;
 
641
      if (val > max)
 
642
            val = max;
 
643
      emit yposChanged(val);
 
644
      }
 
645
 
 
646
//---------------------------------------------------------
 
647
//   viewMouseReleaseEvent
 
648
//---------------------------------------------------------
 
649
 
 
650
void CtrlCanvas::viewMouseReleaseEvent(QMouseEvent* event)
 
651
      {
 
652
      bool shift = event->state() & ShiftButton;
 
653
 
 
654
      switch (drag) {
 
655
            case DRAG_RESIZE:
 
656
            case DRAG_NEW:
 
657
            case DRAG_DELETE:
 
658
                  song->endUndo(SC_EVENT_MODIFIED | SC_EVENT_INSERTED);
 
659
                  break;
 
660
 
 
661
            case DRAG_LASSO_START:
 
662
                  lasso.setRect(-1, -1, -1, -1);
 
663
 
 
664
            case DRAG_LASSO:
 
665
                  if (!shift)
 
666
                        deselectAll();
 
667
                  lasso = lasso.normalize();
 
668
                  for (iCEvent i = items.begin(); i != items.end(); ++i) {
 
669
#if 0
 
670
                        if ((*i)->intersects(lasso)) {
 
671
                              if (shift && (*i)->isSelected())
 
672
                                    deselectItem(*i);
 
673
                              else
 
674
                                    selectItem(*i);
 
675
                              }
 
676
#endif
 
677
                        }
 
678
                  drag = DRAG_OFF;
 
679
                  redraw();
 
680
                  break;
 
681
 
 
682
            default:
 
683
                  break;
 
684
            }
 
685
      drag = DRAG_OFF;
 
686
      }
 
687
 
 
688
//---------------------------------------------------------
 
689
//   changeVal
 
690
//---------------------------------------------------------
 
691
 
 
692
void CtrlCanvas::changeVal(int x1, int x2, int y)
 
693
      {
 
694
      int h   = height();
 
695
      int min = ctrl.minVal();
 
696
      int max = ctrl.maxVal();
 
697
 
 
698
      bool changed = false;
 
699
      int nval = (((h - y) *  (max-min)) / h) + min;
 
700
      if (nval > max)
 
701
            nval = max;
 
702
      for (ciCEvent i = items.begin(); i != items.end(); ++i) {
 
703
            if ((*i)->contains(x1, x2)) {
 
704
                  CEvent* ev       = *i;
 
705
                  MidiEvent* event = ev->event();
 
706
                  MidiPart* part   = ev->part();
 
707
                  ev->setVal(nval);
 
708
                  if (ctrl.type() == MidiController::Velo) {
 
709
                        if ((event->velo() != nval)) {
 
710
                              MidiEvent* newEvent = new MidiEvent(*event);
 
711
                              newEvent->setVelo(nval);
 
712
                              midiThread->msgChangeEvent(event, newEvent, part, false);
 
713
                              ev->setEvent(newEvent);
 
714
                              changed = true;
 
715
                              }
 
716
                        }
 
717
                  else if (ctrl.type() == MidiController::Controller7) {
 
718
                        if (event) {
 
719
                              if ((event->cntrlVal() != nval)) {
 
720
                                    MidiEvent* newEvent = new MidiEvent(*event);
 
721
                                    newEvent->setB(nval);
 
722
                                    midiThread->msgChangeEvent(event, newEvent, part, false);
 
723
                                    ev->setEvent(newEvent);
 
724
                                    changed = true;
 
725
                                    }
 
726
                              }
 
727
                        else {
 
728
                              MidiPort* port = &midiPorts[curTrack->outPort()];
 
729
                              int channel = curTrack->outChannel();
 
730
                              int oval = port->iState(channel)->controller[ctrl.hnum()];
 
731
                              if (oval != nval) {
 
732
                                    port->iState(channel)->controller[ctrl.hnum()] = nval;
 
733
                                    changed = true;
 
734
                                    }
 
735
                              }
 
736
                        }
 
737
                  }
 
738
            }
 
739
      if (changed)
 
740
            redraw();
 
741
      }
 
742
 
 
743
//---------------------------------------------------------
 
744
//   newVal
 
745
//---------------------------------------------------------
 
746
 
 
747
void CtrlCanvas::newVal(int x1, int x2, int y)
 
748
      {
 
749
      int xx1 = editor->rasterVal1(x1);
 
750
      int xx2 = editor->rasterVal2(x2);
 
751
      int min = ctrl.minVal();
 
752
      int max = ctrl.maxVal();
 
753
 
 
754
      int h = height();
 
755
      int nval = (((h - y) *  (max-min)) / h) + min;
 
756
      if (nval > max)
 
757
            nval = max;
 
758
 
 
759
      bool found = false;
 
760
      bool song_changed = false;
 
761
      for (ciCEvent i = items.begin(); i != items.end(); ++i) {
 
762
            CEvent* ev = *i;
 
763
            MidiEvent* event = ev->event();
 
764
            if (event == 0)
 
765
                  continue;
 
766
            int x = event->posTick();
 
767
            if (x < xx1)
 
768
                  continue;
 
769
            if (x >= xx2)
 
770
                  break;
 
771
            if (x == xx1) {
 
772
                  // change event
 
773
                  found = true;
 
774
                  ev->setVal(nval);
 
775
                  switch(ctrl.type()) {
 
776
                        case MidiController::Controller7:
 
777
                              if ((event->cntrlVal() != nval)) {
 
778
                                    MidiEvent* newEvent = new MidiEvent(*event);
 
779
                                    newEvent->setB(nval);
 
780
                                    midiThread->msgChangeEvent(event, newEvent, ev->part(), false);
 
781
                                    ev->setEvent(newEvent);
 
782
                                    song_changed = true;
 
783
                                    }
 
784
                              break;
 
785
                        case MidiController::Pitch:
 
786
                              {
 
787
                              //TODO: check for change
 
788
                              MidiEvent* newEvent = new MidiEvent(
 
789
                                 curTrack->outPort(), curTrack->outChannel(),
 
790
                                 xx1, MidiEvent::Pitch, nval, 0, 0, 0);
 
791
                              midiThread->msgChangeEvent(event, newEvent, ev->part(), false);
 
792
                              ev->setEvent(newEvent);
 
793
                              song_changed = true;
 
794
                              }
 
795
                              break;
 
796
                        default:
 
797
                              // TODO
 
798
                              break;
 
799
                        }
 
800
                  }
 
801
            else if (x < xx2) {
 
802
                  // delete event
 
803
                  MidiEvent* event = ev->event();
 
804
                  if (event) {
 
805
                        midiThread->msgDeleteEvent(event, ev->part(), false);
 
806
                        song_changed = true;
 
807
                        }
 
808
                  }
 
809
            }
 
810
      if (!found) {
 
811
            // new event
 
812
            MidiEvent* event = 0;
 
813
 
 
814
            switch(ctrl.type()) {
 
815
                  case MidiController::Controller7:
 
816
                        event = new MidiEvent(
 
817
                           curTrack->outPort(), curTrack->outChannel(),
 
818
                           xx1, MidiEvent::Ctrl7, ctrl.hnum(), nval, 0, 0);
 
819
                        break;
 
820
                  case MidiController::Controller14:
 
821
                        event = new MidiEvent(
 
822
                           curTrack->outPort(), curTrack->outChannel(),
 
823
                           xx1, MidiEvent::Ctrl14, ctrl.hnum(), nval, ctrl.lnum(), 0);
 
824
                        break;
 
825
                  case MidiController::RPN:
 
826
                        event = new MidiEvent(
 
827
                           curTrack->outPort(), curTrack->outChannel(),
 
828
                           xx1, MidiEvent::RPN, ctrl.hnum()*128+ctrl.lnum(), nval, 0, 0);
 
829
                        break;
 
830
                  case MidiController::NRPN:
 
831
                        event = new MidiEvent(
 
832
                           curTrack->outPort(), curTrack->outChannel(),
 
833
                           xx1, MidiEvent::RPN, ctrl.hnum()*128+ctrl.lnum(), nval, 0, 0);
 
834
                        break;
 
835
                  case MidiController::XgSysex:
 
836
                  case MidiController::Sysex:
 
837
                        break;
 
838
                  case MidiController::Pitch:
 
839
                        event = new MidiEvent(
 
840
                           curTrack->outPort(), curTrack->outChannel(),
 
841
                           xx1, MidiEvent::Pitch, nval, 0, 0, 0);
 
842
                        break;
 
843
                  case MidiController::Velo:
 
844
                        break;
 
845
                  }
 
846
            if (event) {
 
847
                  midiThread->msgAddEvent(event, curPart, false);
 
848
                  song_changed = true;
 
849
                  }
 
850
            }
 
851
      if (song_changed) {
 
852
            songChanged(0);
 
853
            return;
 
854
            }
 
855
      redraw();
 
856
      }
 
857
 
 
858
//---------------------------------------------------------
 
859
//   deleteVal
 
860
//---------------------------------------------------------
 
861
 
 
862
void CtrlCanvas::deleteVal(int x1, int x2, int)
 
863
      {
 
864
      int xx1 = editor->rasterVal1(x1);
 
865
      int xx2 = editor->rasterVal2(x2);
 
866
 
 
867
      bool song_changed = false;
 
868
      for (ciCEvent i = items.begin(); i != items.end(); ++i) {
 
869
            CEvent* ev = *i;
 
870
            MidiEvent* event = ev->event();
 
871
            if (event == 0)
 
872
                  continue;
 
873
            int x = event->posTick();
 
874
            if (x < xx1)
 
875
                  continue;
 
876
            if (x >= xx2)
 
877
                  break;
 
878
            if (event) {
 
879
                  midiThread->msgDeleteEvent(event, ev->part(), false);
 
880
                  song_changed = true;
 
881
                  }
 
882
            }
 
883
      if (song_changed) {
 
884
            songChanged(0);
 
885
            return;
 
886
            }
 
887
      }
 
888
 
 
889
//---------------------------------------------------------
 
890
//   setTool
 
891
//---------------------------------------------------------
 
892
 
 
893
void CtrlCanvas::setTool(int t)
 
894
      {
 
895
      if (tool == Tool(t))
 
896
            return;
 
897
      tool = Tool(t);
 
898
      switch(tool) {
 
899
            case PencilTool:
 
900
                  setCursor(QCursor(*pencilIcon, 4, 15));
 
901
                  break;
 
902
            case DrawTool:
 
903
                  drawLineMode = false;
 
904
                  break;
 
905
            default:
 
906
                  setCursor(QCursor(arrowCursor));
 
907
                  break;
 
908
            }
 
909
      }
 
910
 
 
911
//---------------------------------------------------------
 
912
//   pdraw
 
913
//---------------------------------------------------------
 
914
 
 
915
void CtrlCanvas::pdraw(QPainter& p, const QRect& rect)
 
916
      {
 
917
      int x = rect.x() - 1;   // compensate for 3 pixel line width
 
918
      int y = rect.y();
 
919
      int w = rect.width() + 2;
 
920
      int h = rect.height();
 
921
 
 
922
      int wh = height();
 
923
 
 
924
      //---------------------------------------------------
 
925
      // draw Canvas Items
 
926
      //---------------------------------------------------
 
927
 
 
928
      if (ctrl.type() == MidiController::Velo) {
 
929
            p.setPen(blue);
 
930
            for (iCEvent i = items.begin(); i != items.end(); ++i) {
 
931
                  CEvent* e = *i;
 
932
                  int tick = mapx(e->event()->posTick());
 
933
                  if (tick <= x)
 
934
                        continue;
 
935
                  if (tick > x+w)
 
936
                        break;
 
937
                  int y1 = wh - (e->val() * wh / 128);
 
938
 
 
939
                  p.setPen(QPen(blue, 3));
 
940
                  p.drawLine(tick, wh, tick, y1);
 
941
                  }
 
942
            }
 
943
      else {
 
944
            int min  = ctrl.minVal();
 
945
            int max  = ctrl.maxVal();
 
946
            int x1   = rect.x();
 
947
            int lval = -1;
 
948
            for (iCEvent i = items.begin(); i != items.end(); ++i) {
 
949
                  CEvent* e = *i;
 
950
                  int tick = mapx(e->event() ? e->event()->posTick() : 0);
 
951
                  if (tick <= x) {
 
952
                        if (e->val() == -1)
 
953
                              lval = -1;
 
954
                        else
 
955
                              lval = wh - ((e->val() - min) * wh / (max - min));
 
956
                        continue;
 
957
                        }
 
958
                  if (tick > x+w)
 
959
                        break;
 
960
                  if (lval == -1)
 
961
                        p.fillRect(x1, 0, tick - x1, wh, gray);
 
962
                  else
 
963
                        p.fillRect(x1, lval, tick - x1, wh - lval, blue);
 
964
                  x1 = tick;
 
965
                  if (e->val() == -1)
 
966
                        lval = -1;
 
967
                  else
 
968
                        lval = wh - ((e->val() - min) * wh / (max - min));
 
969
                  }
 
970
            if (lval == -1)
 
971
                  p.fillRect(x1, 0, (x+w) - x1, wh, gray);
 
972
            else
 
973
                  p.fillRect(x1, lval, (x+w) - x1, wh - lval, blue);
 
974
            }
 
975
 
 
976
      p.save();
 
977
      View::pdraw(p, rect);
 
978
      p.restore();
 
979
 
 
980
      //---------------------------------------------------
 
981
      //    draw marker
 
982
      //---------------------------------------------------
 
983
 
 
984
      int xp = mapx(pos[0]);
 
985
      if (xp >= x && xp < x+w) {
 
986
            p.setPen(red);
 
987
            p.drawLine(xp, y, xp, y+h);
 
988
            }
 
989
      xp = mapx(pos[1]);
 
990
      if (xp >= x && xp < x+w) {
 
991
            p.setPen(blue);
 
992
            p.drawLine(xp, y, xp, y+h);
 
993
            }
 
994
      xp = mapx(pos[2]);
 
995
      if (xp >= x && xp < x+w) {
 
996
            p.setPen(blue);
 
997
            p.drawLine(xp, y, xp, y+h);
 
998
            }
 
999
 
 
1000
      //---------------------------------------------------
 
1001
      //    draw lasso
 
1002
      //---------------------------------------------------
 
1003
 
 
1004
      if (drag == DRAG_LASSO) {
 
1005
            setPainter(p);
 
1006
            p.setPen(blue);
 
1007
            p.setBrush(NoBrush);
 
1008
            p.drawRect(lasso);
 
1009
            }
 
1010
//      View::pdraw(p, rect);
 
1011
      }
 
1012
 
 
1013
//---------------------------------------------------------
 
1014
//   drawOverlay
 
1015
//---------------------------------------------------------
 
1016
 
 
1017
void CtrlCanvas::drawOverlay(QPainter& p)
 
1018
      {
 
1019
      QString s(ctrl.name());
 
1020
//printf("draw overlay %s\n", ctrl.name().latin1());
 
1021
      p.setFont(font3);
 
1022
      p.setPen(black);
 
1023
      QFontMetrics fm(font3);
 
1024
      int y = fm.lineSpacing() + 2;
 
1025
      p.drawText(2, y, s);
 
1026
      }
 
1027
 
 
1028
//---------------------------------------------------------
 
1029
//   overlayRect
 
1030
//    returns geometry of overlay rectangle
 
1031
//---------------------------------------------------------
 
1032
 
 
1033
QRect CtrlCanvas::overlayRect() const
 
1034
      {
 
1035
      QFontMetrics fm(font3);
 
1036
      QRect r(fm.boundingRect(ctrl.name()));
 
1037
      r.moveBy(2, 2);   // top/left margin
 
1038
      return r;
 
1039
      }
 
1040
 
 
1041
//---------------------------------------------------------
 
1042
//   draw
 
1043
//---------------------------------------------------------
 
1044
 
 
1045
void CtrlCanvas::draw(QPainter& p, const QRect& rect)
 
1046
      {
 
1047
      drawTickRaster(p, rect.x(), rect.y(),
 
1048
         rect.width(), rect.height(), editor->quant());
 
1049
 
 
1050
      //---------------------------------------------------
 
1051
      //    draw line tool
 
1052
      //---------------------------------------------------
 
1053
 
 
1054
      if (drawLineMode && (tool == DrawTool)) {
 
1055
            p.setPen(black);
 
1056
            p.drawLine(line1x, line1y, line2x, line2y);
 
1057
            }
 
1058
      }
 
1059