comparison layer/NoteLayer.cpp @ 1471:f2525e6cbdf1 by-id

More layer updates
author Chris Cannam
date Mon, 01 Jul 2019 14:17:13 +0100
parents 696e569ff21b
children e540aa5d89cd
comparison
equal deleted inserted replaced
1470:696e569ff21b 1471:f2525e6cbdf1
46 46
47 //#define DEBUG_NOTE_LAYER 1 47 //#define DEBUG_NOTE_LAYER 1
48 48
49 NoteLayer::NoteLayer() : 49 NoteLayer::NoteLayer() :
50 SingleColourLayer(), 50 SingleColourLayer(),
51 m_model(nullptr),
52 m_editing(false), 51 m_editing(false),
53 m_dragPointX(0), 52 m_dragPointX(0),
54 m_dragPointY(0), 53 m_dragPointY(0),
55 m_dragStartX(0), 54 m_dragStartX(0),
56 m_dragStartY(0), 55 m_dragStartY(0),
72 if (model) return model->getCompletion(); 71 if (model) return model->getCompletion();
73 else return 0; 72 else return 0;
74 } 73 }
75 74
76 void 75 void
77 NoteLayer::setModel(ModelId model) 76 NoteLayer::setModel(ModelId modelId)
78 { 77 {
79 if (m_model == model) return; 78 auto newModel = ModelById::getAs<NoteModel>(modelId);
80 m_model = model; 79
81 80 if (!modelId.isNone() && !newModel) {
82 connectSignals(m_model); 81 throw std::logic_error("Not a NoteModel");
83 82 }
84 // SVDEBUG << "NoteLayer::setModel(" << model << ")" << endl; 83
85 84 if (m_model == modelId) return;
85 m_model = modelId;
86
87 if (newModel) {
88 connectSignals(m_model);
89 }
90
86 m_scaleMinimum = 0; 91 m_scaleMinimum = 0;
87 m_scaleMaximum = 0; 92 m_scaleMaximum = 0;
88 93
89 emit modelReplaced(); 94 emit modelReplaced();
90 } 95 }
124 } 129 }
125 130
126 QString 131 QString
127 NoteLayer::getScaleUnits() const 132 NoteLayer::getScaleUnits() const
128 { 133 {
129 if (m_model) return m_model->getScaleUnits(); 134 auto model = ModelById::getAs<NoteModel>(m_model);
135 if (model) return model->getScaleUnits();
130 else return ""; 136 else return "";
131 } 137 }
132 138
133 int 139 int
134 NoteLayer::getPropertyRangeAndValue(const PropertyName &name, 140 NoteLayer::getPropertyRangeAndValue(const PropertyName &name,
145 val = int(m_verticalScale); 151 val = int(m_verticalScale);
146 152
147 } else if (name == "Scale Units") { 153 } else if (name == "Scale Units") {
148 154
149 if (deflt) *deflt = 0; 155 if (deflt) *deflt = 0;
150 if (m_model) { 156 auto model = ModelById::getAs<NoteModel>(m_model);
157 if (model) {
151 val = UnitDatabase::getInstance()->getUnitId 158 val = UnitDatabase::getInstance()->getUnitId
152 (getScaleUnits()); 159 (model->getScaleUnits());
153 } 160 }
154 161
155 } else { 162 } else {
156 163
157 val = SingleColourLayer::getPropertyRangeAndValue(name, min, max, deflt); 164 val = SingleColourLayer::getPropertyRangeAndValue(name, min, max, deflt);
180 NoteLayer::setProperty(const PropertyName &name, int value) 187 NoteLayer::setProperty(const PropertyName &name, int value)
181 { 188 {
182 if (name == "Vertical Scale") { 189 if (name == "Vertical Scale") {
183 setVerticalScale(VerticalScale(value)); 190 setVerticalScale(VerticalScale(value));
184 } else if (name == "Scale Units") { 191 } else if (name == "Scale Units") {
185 if (m_model) { 192 auto model = ModelById::getAs<NoteModel>(m_model);
186 m_model->setScaleUnits 193 if (model) {
194 model->setScaleUnits
187 (UnitDatabase::getInstance()->getUnitById(value)); 195 (UnitDatabase::getInstance()->getUnitById(value));
188 emit modelChanged(); 196 emit modelChanged();
189 } 197 }
190 } else { 198 } else {
191 return SingleColourLayer::setProperty(name, value); 199 return SingleColourLayer::setProperty(name, value);
220 228
221 bool 229 bool
222 NoteLayer::getValueExtents(double &min, double &max, 230 NoteLayer::getValueExtents(double &min, double &max,
223 bool &logarithmic, QString &unit) const 231 bool &logarithmic, QString &unit) const
224 { 232 {
225 if (!m_model) return false; 233 auto model = ModelById::getAs<NoteModel>(m_model);
226 min = m_model->getValueMinimum(); 234 if (!model) return false;
227 max = m_model->getValueMaximum(); 235 min = model->getValueMinimum();
236 max = model->getValueMaximum();
228 237
229 if (shouldConvertMIDIToHz()) { 238 if (shouldConvertMIDIToHz()) {
230 unit = "Hz"; 239 unit = "Hz";
231 min = Pitch::getFrequencyForPitch(int(lrint(min))); 240 min = Pitch::getFrequencyForPitch(int(lrint(min)));
232 max = Pitch::getFrequencyForPitch(int(lrint(max + 1))); 241 max = Pitch::getFrequencyForPitch(int(lrint(max + 1)));
233 } else unit = getScaleUnits(); 242 } else unit = getScaleUnits();
234 243
235 if (m_verticalScale == MIDIRangeScale || 244 if (m_verticalScale == MIDIRangeScale ||
236 m_verticalScale == LogScale) logarithmic = true; 245 m_verticalScale == LogScale) {
246 logarithmic = true;
247 }
237 248
238 return true; 249 return true;
239 } 250 }
240 251
241 bool 252 bool
242 NoteLayer::getDisplayExtents(double &min, double &max) const 253 NoteLayer::getDisplayExtents(double &min, double &max) const
243 { 254 {
244 if (!m_model || shouldAutoAlign()) return false; 255 auto model = ModelById::getAs<NoteModel>(m_model);
256 if (!model || shouldAutoAlign()) return false;
245 257
246 if (m_verticalScale == MIDIRangeScale) { 258 if (m_verticalScale == MIDIRangeScale) {
247 min = Pitch::getFrequencyForPitch(0); 259 min = Pitch::getFrequencyForPitch(0);
248 max = Pitch::getFrequencyForPitch(127); 260 max = Pitch::getFrequencyForPitch(127);
249 return true; 261 return true;
250 } 262 }
251 263
252 if (m_scaleMinimum == m_scaleMaximum) { 264 if (m_scaleMinimum == m_scaleMaximum) {
253 min = m_model->getValueMinimum(); 265 min = model->getValueMinimum();
254 max = m_model->getValueMaximum(); 266 max = model->getValueMaximum();
255 } else { 267 } else {
256 min = m_scaleMinimum; 268 min = m_scaleMinimum;
257 max = m_scaleMaximum; 269 max = m_scaleMaximum;
258 } 270 }
259 271
270 } 282 }
271 283
272 bool 284 bool
273 NoteLayer::setDisplayExtents(double min, double max) 285 NoteLayer::setDisplayExtents(double min, double max)
274 { 286 {
275 if (!m_model) return false; 287 if (m_model.isNone()) return false;
276 288
277 if (min == max) { 289 if (min == max) {
278 if (min == 0.f) { 290 if (min == 0.f) {
279 max = 1.f; 291 max = 1.f;
280 } else { 292 } else {
294 } 306 }
295 307
296 int 308 int
297 NoteLayer::getVerticalZoomSteps(int &defaultStep) const 309 NoteLayer::getVerticalZoomSteps(int &defaultStep) const
298 { 310 {
299 if (shouldAutoAlign()) return 0; 311 if (shouldAutoAlign() || m_model.isNone()) return 0;
300 if (!m_model) return 0;
301
302 defaultStep = 0; 312 defaultStep = 0;
303 return 100; 313 return 100;
304 } 314 }
305 315
306 int 316 int
307 NoteLayer::getCurrentVerticalZoomStep() const 317 NoteLayer::getCurrentVerticalZoomStep() const
308 { 318 {
309 if (shouldAutoAlign()) return 0; 319 if (shouldAutoAlign() || m_model.isNone()) return 0;
310 if (!m_model) return 0;
311 320
312 RangeMapper *mapper = getNewVerticalZoomRangeMapper(); 321 RangeMapper *mapper = getNewVerticalZoomRangeMapper();
313 if (!mapper) return 0; 322 if (!mapper) return 0;
314 323
315 double dmin, dmax; 324 double dmin, dmax;
325 //!!! lots of duplication with TimeValueLayer 334 //!!! lots of duplication with TimeValueLayer
326 335
327 void 336 void
328 NoteLayer::setVerticalZoomStep(int step) 337 NoteLayer::setVerticalZoomStep(int step)
329 { 338 {
330 if (shouldAutoAlign()) return; 339 if (shouldAutoAlign() || m_model.isNone()) return;
331 if (!m_model) return;
332 340
333 RangeMapper *mapper = getNewVerticalZoomRangeMapper(); 341 RangeMapper *mapper = getNewVerticalZoomRangeMapper();
334 if (!mapper) return; 342 if (!mapper) return;
335 343
336 double min, max; 344 double min, max;
376 } 384 }
377 385
378 RangeMapper * 386 RangeMapper *
379 NoteLayer::getNewVerticalZoomRangeMapper() const 387 NoteLayer::getNewVerticalZoomRangeMapper() const
380 { 388 {
381 if (!m_model) return nullptr; 389 if (m_model.isNone()) return nullptr;
382 390
383 RangeMapper *mapper; 391 RangeMapper *mapper;
384 392
385 double min, max; 393 double min, max;
386 bool logarithmic; 394 bool logarithmic;
399 } 407 }
400 408
401 EventVector 409 EventVector
402 NoteLayer::getLocalPoints(LayerGeometryProvider *v, int x) const 410 NoteLayer::getLocalPoints(LayerGeometryProvider *v, int x) const
403 { 411 {
404 if (!m_model) return {}; 412 auto model = ModelById::getAs<NoteModel>(m_model);
413 if (!model) return {};
405 414
406 sv_frame_t frame = v->getFrameForX(x); 415 sv_frame_t frame = v->getFrameForX(x);
407 416
408 EventVector local = m_model->getEventsCovering(frame); 417 EventVector local = model->getEventsCovering(frame);
409 if (!local.empty()) return local; 418 if (!local.empty()) return local;
410 419
411 int fuzz = ViewManager::scalePixelSize(2); 420 int fuzz = ViewManager::scalePixelSize(2);
412 sv_frame_t start = v->getFrameForX(x - fuzz); 421 sv_frame_t start = v->getFrameForX(x - fuzz);
413 sv_frame_t end = v->getFrameForX(x + fuzz); 422 sv_frame_t end = v->getFrameForX(x + fuzz);
414 423
415 local = m_model->getEventsStartingWithin(frame, end - frame); 424 local = model->getEventsStartingWithin(frame, end - frame);
416 if (!local.empty()) return local; 425 if (!local.empty()) return local;
417 426
418 local = m_model->getEventsSpanning(start, frame - start); 427 local = model->getEventsSpanning(start, frame - start);
419 if (!local.empty()) return local; 428 if (!local.empty()) return local;
420 429
421 return {}; 430 return {};
422 } 431 }
423 432
424 bool 433 bool
425 NoteLayer::getPointToDrag(LayerGeometryProvider *v, int x, int y, Event &point) const 434 NoteLayer::getPointToDrag(LayerGeometryProvider *v, int x, int y, Event &point) const
426 { 435 {
427 if (!m_model) return false; 436 auto model = ModelById::getAs<NoteModel>(m_model);
437 if (!model) return false;
428 438
429 sv_frame_t frame = v->getFrameForX(x); 439 sv_frame_t frame = v->getFrameForX(x);
430 440
431 EventVector onPoints = m_model->getEventsCovering(frame); 441 EventVector onPoints = model->getEventsCovering(frame);
432 if (onPoints.empty()) return false; 442 if (onPoints.empty()) return false;
433 443
434 int nearestDistance = -1; 444 int nearestDistance = -1;
435 for (const auto &p: onPoints) { 445 for (const auto &p: onPoints) {
436 int distance = getYForValue(v, p.getValue()) - y; 446 int distance = getYForValue(v, p.getValue()) - y;
447 QString 457 QString
448 NoteLayer::getFeatureDescription(LayerGeometryProvider *v, QPoint &pos) const 458 NoteLayer::getFeatureDescription(LayerGeometryProvider *v, QPoint &pos) const
449 { 459 {
450 int x = pos.x(); 460 int x = pos.x();
451 461
452 if (!m_model || !m_model->getSampleRate()) return ""; 462 auto model = ModelById::getAs<NoteModel>(m_model);
463 if (!model || !model->getSampleRate()) return "";
453 464
454 EventVector points = getLocalPoints(v, x); 465 EventVector points = getLocalPoints(v, x);
455 466
456 if (points.empty()) { 467 if (points.empty()) {
457 if (!m_model->isReady()) { 468 if (!model->isReady()) {
458 return tr("In progress"); 469 return tr("In progress");
459 } else { 470 } else {
460 return tr("No local points"); 471 return tr("No local points");
461 } 472 }
462 } 473 }
467 for (i = points.begin(); i != points.end(); ++i) { 478 for (i = points.begin(); i != points.end(); ++i) {
468 479
469 int y = getYForValue(v, i->getValue()); 480 int y = getYForValue(v, i->getValue());
470 int h = 3; 481 int h = 3;
471 482
472 if (m_model->getValueQuantization() != 0.0) { 483 if (model->getValueQuantization() != 0.0) {
473 h = y - getYForValue 484 h = y - getYForValue
474 (v, i->getValue() + m_model->getValueQuantization()); 485 (v, i->getValue() + model->getValueQuantization());
475 if (h < 3) h = 3; 486 if (h < 3) h = 3;
476 } 487 }
477 488
478 if (pos.y() >= y - h && pos.y() <= y) { 489 if (pos.y() >= y - h && pos.y() <= y) {
479 note = *i; 490 note = *i;
482 } 493 }
483 494
484 if (i == points.end()) return tr("No local points"); 495 if (i == points.end()) return tr("No local points");
485 496
486 RealTime rt = RealTime::frame2RealTime(note.getFrame(), 497 RealTime rt = RealTime::frame2RealTime(note.getFrame(),
487 m_model->getSampleRate()); 498 model->getSampleRate());
488 RealTime rd = RealTime::frame2RealTime(note.getDuration(), 499 RealTime rd = RealTime::frame2RealTime(note.getDuration(),
489 m_model->getSampleRate()); 500 model->getSampleRate());
490 501
491 QString pitchText; 502 QString pitchText;
492 503
493 float value = note.getValue(); 504 float value = note.getValue();
494 505
536 bool 547 bool
537 NoteLayer::snapToFeatureFrame(LayerGeometryProvider *v, sv_frame_t &frame, 548 NoteLayer::snapToFeatureFrame(LayerGeometryProvider *v, sv_frame_t &frame,
538 int &resolution, 549 int &resolution,
539 SnapType snap) const 550 SnapType snap) const
540 { 551 {
541 if (!m_model) { 552 auto model = ModelById::getAs<NoteModel>(m_model);
553 if (!model) {
542 return Layer::snapToFeatureFrame(v, frame, resolution, snap); 554 return Layer::snapToFeatureFrame(v, frame, resolution, snap);
543 } 555 }
544 556
545 // SnapLeft / SnapRight: return frame of nearest feature in that 557 // SnapLeft / SnapRight: return frame of nearest feature in that
546 // direction no matter how far away 558 // direction no matter how far away
547 // 559 //
548 // SnapNeighbouring: return frame of feature that would be used in 560 // SnapNeighbouring: return frame of feature that would be used in
549 // an editing operation, i.e. closest feature in either direction 561 // an editing operation, i.e. closest feature in either direction
550 // but only if it is "close enough" 562 // but only if it is "close enough"
551 563
552 resolution = m_model->getResolution(); 564 resolution = model->getResolution();
553 565
554 if (snap == SnapNeighbouring) { 566 if (snap == SnapNeighbouring) {
555 EventVector points = getLocalPoints(v, v->getXForFrame(frame)); 567 EventVector points = getLocalPoints(v, v->getXForFrame(frame));
556 if (points.empty()) return false; 568 if (points.empty()) return false;
557 frame = points.begin()->getFrame(); 569 frame = points.begin()->getFrame();
558 return true; 570 return true;
559 } 571 }
560 572
561 Event e; 573 Event e;
562 if (m_model->getNearestEventMatching 574 if (model->getNearestEventMatching
563 (frame, 575 (frame,
564 [](Event) { return true; }, 576 [](Event) { return true; },
565 snap == SnapLeft ? EventSeries::Backward : EventSeries::Forward, 577 snap == SnapLeft ? EventSeries::Backward : EventSeries::Forward,
566 e)) { 578 e)) {
567 frame = e.getFrame(); 579 frame = e.getFrame();
576 { 588 {
577 min = 0.0; 589 min = 0.0;
578 max = 0.0; 590 max = 0.0;
579 log = false; 591 log = false;
580 592
593 auto model = ModelById::getAs<NoteModel>(m_model);
594 if (!model) return;
595
581 QString queryUnits; 596 QString queryUnits;
582 if (shouldConvertMIDIToHz()) queryUnits = "Hz"; 597 if (shouldConvertMIDIToHz()) queryUnits = "Hz";
583 else queryUnits = getScaleUnits(); 598 else queryUnits = getScaleUnits();
584 599
585 if (shouldAutoAlign()) { 600 if (shouldAutoAlign()) {
586 601
587 if (!v->getValueExtents(queryUnits, min, max, log)) { 602 if (!v->getValueExtents(queryUnits, min, max, log)) {
588 603
589 min = m_model->getValueMinimum(); 604 min = model->getValueMinimum();
590 max = m_model->getValueMaximum(); 605 max = model->getValueMaximum();
591 606
592 if (shouldConvertMIDIToHz()) { 607 if (shouldConvertMIDIToHz()) {
593 min = Pitch::getFrequencyForPitch(int(lrint(min))); 608 min = Pitch::getFrequencyForPitch(int(lrint(min)));
594 max = Pitch::getFrequencyForPitch(int(lrint(max + 1))); 609 max = Pitch::getFrequencyForPitch(int(lrint(max + 1)));
595 } 610 }
687 } 702 }
688 703
689 bool 704 bool
690 NoteLayer::shouldAutoAlign() const 705 NoteLayer::shouldAutoAlign() const
691 { 706 {
692 if (!m_model) return false; 707 if (m_model.isNone()) return false;
693 return (m_verticalScale == AutoAlignScale); 708 return (m_verticalScale == AutoAlignScale);
694 } 709 }
695 710
696 void 711 void
697 NoteLayer::paint(LayerGeometryProvider *v, QPainter &paint, QRect rect) const 712 NoteLayer::paint(LayerGeometryProvider *v, QPainter &paint, QRect rect) const
698 { 713 {
699 if (!m_model || !m_model->isOK()) return; 714 auto model = ModelById::getAs<NoteModel>(m_model);
700 715 if (!model || !model->isOK()) return;
701 sv_samplerate_t sampleRate = m_model->getSampleRate(); 716
717 sv_samplerate_t sampleRate = model->getSampleRate();
702 if (!sampleRate) return; 718 if (!sampleRate) return;
703 719
704 // Profiler profiler("NoteLayer::paint", true); 720 // Profiler profiler("NoteLayer::paint", true);
705 721
706 int x0 = rect.left(), x1 = rect.right(); 722 int x0 = rect.left(), x1 = rect.right();
707 sv_frame_t frame0 = v->getFrameForX(x0); 723 sv_frame_t frame0 = v->getFrameForX(x0);
708 sv_frame_t frame1 = v->getFrameForX(x1); 724 sv_frame_t frame1 = v->getFrameForX(x1);
709 725
710 EventVector points(m_model->getEventsSpanning(frame0, frame1 - frame0)); 726 EventVector points(model->getEventsSpanning(frame0, frame1 - frame0));
711 if (points.empty()) return; 727 if (points.empty()) return;
712 728
713 paint.setPen(getBaseQColor()); 729 paint.setPen(getBaseQColor());
714 730
715 QColor brushColour(getBaseQColor()); 731 QColor brushColour(getBaseQColor());
716 brushColour.setAlpha(80); 732 brushColour.setAlpha(80);
717 733
718 // SVDEBUG << "NoteLayer::paint: resolution is " 734 // SVDEBUG << "NoteLayer::paint: resolution is "
719 // << m_model->getResolution() << " frames" << endl; 735 // << model->getResolution() << " frames" << endl;
720 736
721 double min = m_model->getValueMinimum(); 737 double min = model->getValueMinimum();
722 double max = m_model->getValueMaximum(); 738 double max = model->getValueMaximum();
723 if (max == min) max = min + 1.0; 739 if (max == min) max = min + 1.0;
724 740
725 QPoint localPos; 741 QPoint localPos;
726 Event illuminatePoint; 742 Event illuminatePoint;
727 bool shouldIlluminate = false; 743 bool shouldIlluminate = false;
745 int x = v->getXForFrame(p.getFrame()); 761 int x = v->getXForFrame(p.getFrame());
746 int y = getYForValue(v, p.getValue()); 762 int y = getYForValue(v, p.getValue());
747 int w = v->getXForFrame(p.getFrame() + p.getDuration()) - x; 763 int w = v->getXForFrame(p.getFrame() + p.getDuration()) - x;
748 int h = 3; 764 int h = 3;
749 765
750 if (m_model->getValueQuantization() != 0.0) { 766 if (model->getValueQuantization() != 0.0) {
751 h = y - getYForValue(v, p.getValue() + m_model->getValueQuantization()); 767 h = y - getYForValue(v, p.getValue() + model->getValueQuantization());
752 if (h < 3) h = 3; 768 if (h < 3) h = 3;
753 } 769 }
754 770
755 if (w < 1) w = 1; 771 if (w < 1) w = 1;
756 paint.setPen(getBaseQColor()); 772 paint.setPen(getBaseQColor());
758 774
759 if (shouldIlluminate && illuminatePoint == p) { 775 if (shouldIlluminate && illuminatePoint == p) {
760 776
761 paint.setPen(v->getForeground()); 777 paint.setPen(v->getForeground());
762 paint.setBrush(v->getForeground()); 778 paint.setBrush(v->getForeground());
779
780 // Qt 5.13 deprecates QFontMetrics::width(), but its suggested
781 // replacement (horizontalAdvance) was only added in Qt 5.11
782 // which is too new for us
783 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
763 784
764 QString vlabel = QString("%1%2").arg(p.getValue()).arg(getScaleUnits()); 785 QString vlabel = QString("%1%2").arg(p.getValue()).arg(getScaleUnits());
765 PaintAssistant::drawVisibleText(v, paint, 786 PaintAssistant::drawVisibleText(v, paint,
766 x - paint.fontMetrics().width(vlabel) - 2, 787 x - paint.fontMetrics().width(vlabel) - 2,
767 y + paint.fontMetrics().height()/2 788 y + paint.fontMetrics().height()/2
768 - paint.fontMetrics().descent(), 789 - paint.fontMetrics().descent(),
769 vlabel, PaintAssistant::OutlinedText); 790 vlabel, PaintAssistant::OutlinedText);
770 791
771 QString hlabel = RealTime::frame2RealTime 792 QString hlabel = RealTime::frame2RealTime
772 (p.getFrame(), m_model->getSampleRate()).toText(true).c_str(); 793 (p.getFrame(), model->getSampleRate()).toText(true).c_str();
773 PaintAssistant::drawVisibleText(v, paint, 794 PaintAssistant::drawVisibleText(v, paint,
774 x, 795 x,
775 y - h/2 - paint.fontMetrics().descent() - 2, 796 y - h/2 - paint.fontMetrics().descent() - 2,
776 hlabel, PaintAssistant::OutlinedText); 797 hlabel, PaintAssistant::OutlinedText);
777 } 798 }
783 } 804 }
784 805
785 int 806 int
786 NoteLayer::getVerticalScaleWidth(LayerGeometryProvider *v, bool, QPainter &paint) const 807 NoteLayer::getVerticalScaleWidth(LayerGeometryProvider *v, bool, QPainter &paint) const
787 { 808 {
788 if (!m_model) { 809 if (m_model.isNone()) {
789 return 0; 810 return 0;
790 } 811 }
791 812
792 if (shouldAutoAlign() && !valueExtentsMatchMine(v)) { 813 if (shouldAutoAlign() && !valueExtentsMatchMine(v)) {
793 return 0; 814 return 0;
801 } 822 }
802 823
803 void 824 void
804 NoteLayer::paintVerticalScale(LayerGeometryProvider *v, bool, QPainter &paint, QRect) const 825 NoteLayer::paintVerticalScale(LayerGeometryProvider *v, bool, QPainter &paint, QRect) const
805 { 826 {
806 if (!m_model || m_model->isEmpty()) return; 827 auto model = ModelById::getAs<NoteModel>(m_model);
828 if (!model || model->isEmpty()) return;
807 829
808 QString unit; 830 QString unit;
809 double min, max; 831 double min, max;
810 bool logarithmic; 832 bool logarithmic;
811 833
841 void 863 void
842 NoteLayer::drawStart(LayerGeometryProvider *v, QMouseEvent *e) 864 NoteLayer::drawStart(LayerGeometryProvider *v, QMouseEvent *e)
843 { 865 {
844 // SVDEBUG << "NoteLayer::drawStart(" << e->x() << "," << e->y() << ")" << endl; 866 // SVDEBUG << "NoteLayer::drawStart(" << e->x() << "," << e->y() << ")" << endl;
845 867
846 if (!m_model) return; 868 auto model = ModelById::getAs<NoteModel>(m_model);
869 if (!model) return;
847 870
848 sv_frame_t frame = v->getFrameForX(e->x()); 871 sv_frame_t frame = v->getFrameForX(e->x());
849 if (frame < 0) frame = 0; 872 if (frame < 0) frame = 0;
850 frame = frame / m_model->getResolution() * m_model->getResolution(); 873 frame = frame / model->getResolution() * model->getResolution();
851 874
852 double value = getValueForY(v, e->y()); 875 double value = getValueForY(v, e->y());
853 876
854 m_editingPoint = Event(frame, float(value), 0, 0.8f, tr("New Point")); 877 m_editingPoint = Event(frame, float(value), 0, 0.8f, tr("New Point"));
855 m_originalPoint = m_editingPoint; 878 m_originalPoint = m_editingPoint;
856 879
857 if (m_editingCommand) finish(m_editingCommand); 880 if (m_editingCommand) finish(m_editingCommand);
858 m_editingCommand = new ChangeEventsCommand(m_model, tr("Draw Point")); 881 m_editingCommand = new ChangeEventsCommand(m_model.untyped, tr("Draw Point"));
859 m_editingCommand->add(m_editingPoint); 882 m_editingCommand->add(m_editingPoint);
860 883
861 m_editing = true; 884 m_editing = true;
862 } 885 }
863 886
864 void 887 void
865 NoteLayer::drawDrag(LayerGeometryProvider *v, QMouseEvent *e) 888 NoteLayer::drawDrag(LayerGeometryProvider *v, QMouseEvent *e)
866 { 889 {
867 // SVDEBUG << "NoteLayer::drawDrag(" << e->x() << "," << e->y() << ")" << endl; 890 // SVDEBUG << "NoteLayer::drawDrag(" << e->x() << "," << e->y() << ")" << endl;
868 891
869 if (!m_model || !m_editing) return; 892 auto model = ModelById::getAs<NoteModel>(m_model);
893 if (!model || !m_editing) return;
870 894
871 sv_frame_t frame = v->getFrameForX(e->x()); 895 sv_frame_t frame = v->getFrameForX(e->x());
872 if (frame < 0) frame = 0; 896 if (frame < 0) frame = 0;
873 frame = frame / m_model->getResolution() * m_model->getResolution(); 897 frame = frame / model->getResolution() * model->getResolution();
874 898
875 double newValue = getValueForY(v, e->y()); 899 double newValue = getValueForY(v, e->y());
876 900
877 sv_frame_t newFrame = m_editingPoint.getFrame(); 901 sv_frame_t newFrame = m_editingPoint.getFrame();
878 sv_frame_t newDuration = frame - newFrame; 902 sv_frame_t newDuration = frame - newFrame;
893 917
894 void 918 void
895 NoteLayer::drawEnd(LayerGeometryProvider *, QMouseEvent *) 919 NoteLayer::drawEnd(LayerGeometryProvider *, QMouseEvent *)
896 { 920 {
897 // SVDEBUG << "NoteLayer::drawEnd(" << e->x() << "," << e->y() << ")" << endl; 921 // SVDEBUG << "NoteLayer::drawEnd(" << e->x() << "," << e->y() << ")" << endl;
898 if (!m_model || !m_editing) return; 922 auto model = ModelById::getAs<NoteModel>(m_model);
923 if (!model || !m_editing) return;
899 finish(m_editingCommand); 924 finish(m_editingCommand);
900 m_editingCommand = nullptr; 925 m_editingCommand = nullptr;
901 m_editing = false; 926 m_editing = false;
902 } 927 }
903 928
904 void 929 void
905 NoteLayer::eraseStart(LayerGeometryProvider *v, QMouseEvent *e) 930 NoteLayer::eraseStart(LayerGeometryProvider *v, QMouseEvent *e)
906 { 931 {
907 if (!m_model) return; 932 auto model = ModelById::getAs<NoteModel>(m_model);
933 if (!model) return;
908 934
909 if (!getPointToDrag(v, e->x(), e->y(), m_editingPoint)) return; 935 if (!getPointToDrag(v, e->x(), e->y(), m_editingPoint)) return;
910 936
911 if (m_editingCommand) { 937 if (m_editingCommand) {
912 finish(m_editingCommand); 938 finish(m_editingCommand);
922 } 948 }
923 949
924 void 950 void
925 NoteLayer::eraseEnd(LayerGeometryProvider *v, QMouseEvent *e) 951 NoteLayer::eraseEnd(LayerGeometryProvider *v, QMouseEvent *e)
926 { 952 {
927 if (!m_model || !m_editing) return; 953 auto model = ModelById::getAs<NoteModel>(m_model);
954 if (!model || !m_editing) return;
928 955
929 m_editing = false; 956 m_editing = false;
930 957
931 Event p(0); 958 Event p(0);
932 if (!getPointToDrag(v, e->x(), e->y(), p)) return; 959 if (!getPointToDrag(v, e->x(), e->y(), p)) return;
933 if (p.getFrame() != m_editingPoint.getFrame() || 960 if (p.getFrame() != m_editingPoint.getFrame() ||
934 p.getValue() != m_editingPoint.getValue()) return; 961 p.getValue() != m_editingPoint.getValue()) return;
935 962
936 m_editingCommand = new ChangeEventsCommand(m_model, tr("Erase Point")); 963 m_editingCommand = new ChangeEventsCommand(m_model.untyped, tr("Erase Point"));
937 964
938 m_editingCommand->remove(m_editingPoint); 965 m_editingCommand->remove(m_editingPoint);
939 966
940 finish(m_editingCommand); 967 finish(m_editingCommand);
941 m_editingCommand = nullptr; 968 m_editingCommand = nullptr;
945 void 972 void
946 NoteLayer::editStart(LayerGeometryProvider *v, QMouseEvent *e) 973 NoteLayer::editStart(LayerGeometryProvider *v, QMouseEvent *e)
947 { 974 {
948 // SVDEBUG << "NoteLayer::editStart(" << e->x() << "," << e->y() << ")" << endl; 975 // SVDEBUG << "NoteLayer::editStart(" << e->x() << "," << e->y() << ")" << endl;
949 976
950 if (!m_model) return; 977 auto model = ModelById::getAs<NoteModel>(m_model);
978 if (!model) return;
951 979
952 if (!getPointToDrag(v, e->x(), e->y(), m_editingPoint)) return; 980 if (!getPointToDrag(v, e->x(), e->y(), m_editingPoint)) return;
953 m_originalPoint = m_editingPoint; 981 m_originalPoint = m_editingPoint;
954 982
955 m_dragPointX = v->getXForFrame(m_editingPoint.getFrame()); 983 m_dragPointX = v->getXForFrame(m_editingPoint.getFrame());
968 void 996 void
969 NoteLayer::editDrag(LayerGeometryProvider *v, QMouseEvent *e) 997 NoteLayer::editDrag(LayerGeometryProvider *v, QMouseEvent *e)
970 { 998 {
971 // SVDEBUG << "NoteLayer::editDrag(" << e->x() << "," << e->y() << ")" << endl; 999 // SVDEBUG << "NoteLayer::editDrag(" << e->x() << "," << e->y() << ")" << endl;
972 1000
973 if (!m_model || !m_editing) return; 1001 auto model = ModelById::getAs<NoteModel>(m_model);
1002 if (!model || !m_editing) return;
974 1003
975 int xdist = e->x() - m_dragStartX; 1004 int xdist = e->x() - m_dragStartX;
976 int ydist = e->y() - m_dragStartY; 1005 int ydist = e->y() - m_dragStartY;
977 int newx = m_dragPointX + xdist; 1006 int newx = m_dragPointX + xdist;
978 int newy = m_dragPointY + ydist; 1007 int newy = m_dragPointY + ydist;
979 1008
980 sv_frame_t frame = v->getFrameForX(newx); 1009 sv_frame_t frame = v->getFrameForX(newx);
981 if (frame < 0) frame = 0; 1010 if (frame < 0) frame = 0;
982 frame = frame / m_model->getResolution() * m_model->getResolution(); 1011 frame = frame / model->getResolution() * model->getResolution();
983 1012
984 double value = getValueForY(v, newy); 1013 double value = getValueForY(v, newy);
985 1014
986 if (!m_editingCommand) { 1015 if (!m_editingCommand) {
987 m_editingCommand = new ChangeEventsCommand(m_model, 1016 m_editingCommand = new ChangeEventsCommand
988 tr("Drag Point")); 1017 (m_model.untyped, tr("Drag Point"));
989 } 1018 }
990 1019
991 m_editingCommand->remove(m_editingPoint); 1020 m_editingCommand->remove(m_editingPoint);
992 m_editingPoint = m_editingPoint 1021 m_editingPoint = m_editingPoint
993 .withFrame(frame) 1022 .withFrame(frame)
997 1026
998 void 1027 void
999 NoteLayer::editEnd(LayerGeometryProvider *, QMouseEvent *) 1028 NoteLayer::editEnd(LayerGeometryProvider *, QMouseEvent *)
1000 { 1029 {
1001 // SVDEBUG << "NoteLayer::editEnd(" << e->x() << "," << e->y() << ")" << endl; 1030 // SVDEBUG << "NoteLayer::editEnd(" << e->x() << "," << e->y() << ")" << endl;
1002 if (!m_model || !m_editing) return; 1031 auto model = ModelById::getAs<NoteModel>(m_model);
1032 if (!model || !m_editing) return;
1003 1033
1004 if (m_editingCommand) { 1034 if (m_editingCommand) {
1005 1035
1006 QString newName = m_editingCommand->getName(); 1036 QString newName = m_editingCommand->getName();
1007 1037
1024 } 1054 }
1025 1055
1026 bool 1056 bool
1027 NoteLayer::editOpen(LayerGeometryProvider *v, QMouseEvent *e) 1057 NoteLayer::editOpen(LayerGeometryProvider *v, QMouseEvent *e)
1028 { 1058 {
1029 if (!m_model) return false; 1059 auto model = ModelById::getAs<NoteModel>(m_model);
1060 if (!model) return false;
1030 1061
1031 Event note(0); 1062 Event note(0);
1032 if (!getPointToDrag(v, e->x(), e->y(), note)) return false; 1063 if (!getPointToDrag(v, e->x(), e->y(), note)) return false;
1033 1064
1034 // Event note = *points.begin(); 1065 // Event note = *points.begin();
1035 1066
1036 ItemEditDialog *dialog = new ItemEditDialog 1067 ItemEditDialog *dialog = new ItemEditDialog
1037 (m_model->getSampleRate(), 1068 (model->getSampleRate(),
1038 ItemEditDialog::ShowTime | 1069 ItemEditDialog::ShowTime |
1039 ItemEditDialog::ShowDuration | 1070 ItemEditDialog::ShowDuration |
1040 ItemEditDialog::ShowValue | 1071 ItemEditDialog::ShowValue |
1041 ItemEditDialog::ShowText, 1072 ItemEditDialog::ShowText,
1042 getScaleUnits()); 1073 getScaleUnits());
1056 .withValue(dialog->getValue()) 1087 .withValue(dialog->getValue())
1057 .withDuration(dialog->getFrameDuration()) 1088 .withDuration(dialog->getFrameDuration())
1058 .withLabel(dialog->getText()); 1089 .withLabel(dialog->getText());
1059 1090
1060 ChangeEventsCommand *command = new ChangeEventsCommand 1091 ChangeEventsCommand *command = new ChangeEventsCommand
1061 (m_model, tr("Edit Point")); 1092 (m_model.untyped, tr("Edit Point"));
1062 command->remove(note); 1093 command->remove(note);
1063 command->add(newNote); 1094 command->add(newNote);
1064 finish(command); 1095 finish(command);
1065 } 1096 }
1066 1097
1072 } 1103 }
1073 1104
1074 void 1105 void
1075 NoteLayer::moveSelection(Selection s, sv_frame_t newStartFrame) 1106 NoteLayer::moveSelection(Selection s, sv_frame_t newStartFrame)
1076 { 1107 {
1077 if (!m_model) return; 1108 auto model = ModelById::getAs<NoteModel>(m_model);
1109 if (!model) return;
1078 1110
1079 ChangeEventsCommand *command = 1111 ChangeEventsCommand *command =
1080 new ChangeEventsCommand(m_model, tr("Drag Selection")); 1112 new ChangeEventsCommand(m_model.untyped, tr("Drag Selection"));
1081 1113
1082 EventVector points = 1114 EventVector points =
1083 m_model->getEventsStartingWithin(s.getStartFrame(), s.getDuration()); 1115 model->getEventsStartingWithin(s.getStartFrame(), s.getDuration());
1084 1116
1085 for (Event p: points) { 1117 for (Event p: points) {
1086 command->remove(p); 1118 command->remove(p);
1087 Event moved = p.withFrame(p.getFrame() + 1119 Event moved = p.withFrame(p.getFrame() +
1088 newStartFrame - s.getStartFrame()); 1120 newStartFrame - s.getStartFrame());
1093 } 1125 }
1094 1126
1095 void 1127 void
1096 NoteLayer::resizeSelection(Selection s, Selection newSize) 1128 NoteLayer::resizeSelection(Selection s, Selection newSize)
1097 { 1129 {
1098 if (!m_model || !s.getDuration()) return; 1130 auto model = ModelById::getAs<NoteModel>(m_model);
1131 if (!model || !s.getDuration()) return;
1099 1132
1100 ChangeEventsCommand *command = 1133 ChangeEventsCommand *command =
1101 new ChangeEventsCommand(m_model, tr("Resize Selection")); 1134 new ChangeEventsCommand(m_model.untyped, tr("Resize Selection"));
1102 1135
1103 EventVector points = 1136 EventVector points =
1104 m_model->getEventsStartingWithin(s.getStartFrame(), s.getDuration()); 1137 model->getEventsStartingWithin(s.getStartFrame(), s.getDuration());
1105 1138
1106 double ratio = double(newSize.getDuration()) / double(s.getDuration()); 1139 double ratio = double(newSize.getDuration()) / double(s.getDuration());
1107 double oldStart = double(s.getStartFrame()); 1140 double oldStart = double(s.getStartFrame());
1108 double newStart = double(newSize.getStartFrame()); 1141 double newStart = double(newSize.getStartFrame());
1109 1142
1123 } 1156 }
1124 1157
1125 void 1158 void
1126 NoteLayer::deleteSelection(Selection s) 1159 NoteLayer::deleteSelection(Selection s)
1127 { 1160 {
1128 if (!m_model) return; 1161 auto model = ModelById::getAs<NoteModel>(m_model);
1162 if (!model) return;
1129 1163
1130 ChangeEventsCommand *command = 1164 ChangeEventsCommand *command =
1131 new ChangeEventsCommand(m_model, tr("Delete Selected Points")); 1165 new ChangeEventsCommand(m_model.untyped, tr("Delete Selected Points"));
1132 1166
1133 EventVector points = 1167 EventVector points =
1134 m_model->getEventsStartingWithin(s.getStartFrame(), s.getDuration()); 1168 model->getEventsStartingWithin(s.getStartFrame(), s.getDuration());
1135 1169
1136 for (Event p: points) { 1170 for (Event p: points) {
1137 command->remove(p); 1171 command->remove(p);
1138 } 1172 }
1139 1173
1141 } 1175 }
1142 1176
1143 void 1177 void
1144 NoteLayer::copy(LayerGeometryProvider *v, Selection s, Clipboard &to) 1178 NoteLayer::copy(LayerGeometryProvider *v, Selection s, Clipboard &to)
1145 { 1179 {
1146 if (!m_model) return; 1180 auto model = ModelById::getAs<NoteModel>(m_model);
1181 if (!model) return;
1147 1182
1148 EventVector points = 1183 EventVector points =
1149 m_model->getEventsStartingWithin(s.getStartFrame(), s.getDuration()); 1184 model->getEventsStartingWithin(s.getStartFrame(), s.getDuration());
1150 1185
1151 for (Event p: points) { 1186 for (Event p: points) {
1152 to.addPoint(p.withReferenceFrame(alignToReference(v, p.getFrame()))); 1187 to.addPoint(p.withReferenceFrame(alignToReference(v, p.getFrame())));
1153 } 1188 }
1154 } 1189 }
1155 1190
1156 bool 1191 bool
1157 NoteLayer::paste(LayerGeometryProvider *v, const Clipboard &from, 1192 NoteLayer::paste(LayerGeometryProvider *v, const Clipboard &from,
1158 sv_frame_t /* frameOffset */, bool /* interactive */) 1193 sv_frame_t /* frameOffset */, bool /* interactive */)
1159 { 1194 {
1160 if (!m_model) return false; 1195 auto model = ModelById::getAs<NoteModel>(m_model);
1196 if (!model) return false;
1161 1197
1162 const EventVector &points = from.getPoints(); 1198 const EventVector &points = from.getPoints();
1163 1199
1164 bool realign = false; 1200 bool realign = false;
1165 1201
1179 realign = true; 1215 realign = true;
1180 } 1216 }
1181 } 1217 }
1182 1218
1183 ChangeEventsCommand *command = 1219 ChangeEventsCommand *command =
1184 new ChangeEventsCommand(m_model, tr("Paste")); 1220 new ChangeEventsCommand(m_model.untyped, tr("Paste"));
1185 1221
1186 for (EventVector::const_iterator i = points.begin(); 1222 for (EventVector::const_iterator i = points.begin();
1187 i != points.end(); ++i) { 1223 i != points.end(); ++i) {
1188 1224
1189 sv_frame_t frame = 0; 1225 sv_frame_t frame = 0;
1203 } 1239 }
1204 1240
1205 Event p = *i; 1241 Event p = *i;
1206 Event newPoint = p; 1242 Event newPoint = p;
1207 if (!p.hasValue()) { 1243 if (!p.hasValue()) {
1208 newPoint = newPoint.withValue((m_model->getValueMinimum() + 1244 newPoint = newPoint.withValue((model->getValueMinimum() +
1209 m_model->getValueMaximum()) / 2); 1245 model->getValueMaximum()) / 2);
1210 } 1246 }
1211 if (!p.hasDuration()) { 1247 if (!p.hasDuration()) {
1212 sv_frame_t nextFrame = frame; 1248 sv_frame_t nextFrame = frame;
1213 EventVector::const_iterator j = i; 1249 EventVector::const_iterator j = i;
1214 for (; j != points.end(); ++j) { 1250 for (; j != points.end(); ++j) {
1216 } 1252 }
1217 if (j != points.end()) { 1253 if (j != points.end()) {
1218 nextFrame = j->getFrame(); 1254 nextFrame = j->getFrame();
1219 } 1255 }
1220 if (nextFrame == frame) { 1256 if (nextFrame == frame) {
1221 newPoint = newPoint.withDuration(m_model->getResolution()); 1257 newPoint = newPoint.withDuration(model->getResolution());
1222 } else { 1258 } else {
1223 newPoint = newPoint.withDuration(nextFrame - frame); 1259 newPoint = newPoint.withDuration(nextFrame - frame);
1224 } 1260 }
1225 } 1261 }
1226 1262
1239 } 1275 }
1240 1276
1241 void 1277 void
1242 NoteLayer::addNoteOff(sv_frame_t frame, int pitch) 1278 NoteLayer::addNoteOff(sv_frame_t frame, int pitch)
1243 { 1279 {
1280 auto model = ModelById::getAs<NoteModel>(m_model);
1281
1244 for (NoteSet::iterator i = m_pendingNoteOns.begin(); 1282 for (NoteSet::iterator i = m_pendingNoteOns.begin();
1245 i != m_pendingNoteOns.end(); ++i) { 1283 i != m_pendingNoteOns.end(); ++i) {
1246 1284
1247 Event p = *i; 1285 Event p = *i;
1248 1286
1249 if (lrintf(p.getValue()) == pitch) { 1287 if (lrintf(p.getValue()) == pitch) {
1250 m_pendingNoteOns.erase(i); 1288 m_pendingNoteOns.erase(i);
1251 Event note = p.withDuration(frame - p.getFrame()); 1289 Event note = p.withDuration(frame - p.getFrame());
1252 if (m_model) { 1290 if (model) {
1253 ChangeEventsCommand *c = new ChangeEventsCommand 1291 ChangeEventsCommand *c = new ChangeEventsCommand
1254 (m_model, tr("Record Note")); 1292 (m_model.untyped, tr("Record Note"));
1255 c->add(note); 1293 c->add(note);
1256 // execute and bundle: 1294 // execute and bundle:
1257 CommandHistory::getInstance()->addCommand(c, true, true); 1295 CommandHistory::getInstance()->addCommand(c, true, true);
1258 } 1296 }
1259 break; 1297 break;