comparison layer/FlexiNoteLayer.cpp @ 1426:e1a08da75427 single-point

Update following FlexiNoteModel removal, using new NoteModel API where flexi was previously used
author Chris Cannam
date Thu, 14 Mar 2019 15:32:58 +0000
parents 62e908518c71
children f792a5001d80
comparison
equal deleted inserted replaced
1425:f9e3126d223c 1426:e1a08da75427
28 #include "PianoScale.h" 28 #include "PianoScale.h"
29 #include "LinearNumericalScale.h" 29 #include "LinearNumericalScale.h"
30 #include "LogNumericalScale.h" 30 #include "LogNumericalScale.h"
31 #include "PaintAssistant.h" 31 #include "PaintAssistant.h"
32 32
33 #include "data/model/FlexiNoteModel.h" 33 #include "data/model/NoteModel.h"
34 34
35 #include "view/View.h" 35 #include "view/View.h"
36 36
37 #include "widgets/ItemEditDialog.h" 37 #include "widgets/ItemEditDialog.h"
38 #include "widgets/TextAbbrev.h" 38 #include "widgets/TextAbbrev.h"
47 #include <cmath> 47 #include <cmath>
48 #include <utility> 48 #include <utility>
49 #include <limits> // GF: included to compile std::numerical_limits on linux 49 #include <limits> // GF: included to compile std::numerical_limits on linux
50 #include <vector> 50 #include <vector>
51 51
52 #define NOTE_HEIGHT 16
52 53
53 FlexiNoteLayer::FlexiNoteLayer() : 54 FlexiNoteLayer::FlexiNoteLayer() :
54 SingleColourLayer(), 55 SingleColourLayer(),
55 56
56 // m_model(0), 57 // m_model(0),
80 m_scaleMaximum(77) 81 m_scaleMaximum(77)
81 { 82 {
82 } 83 }
83 84
84 void 85 void
85 FlexiNoteLayer::setModel(FlexiNoteModel *model) 86 FlexiNoteLayer::setModel(NoteModel *model)
86 { 87 {
87 if (m_model == model) return; 88 if (m_model == model) return;
88 m_model = model; 89 m_model = model;
89 90
90 connectSignals(m_model); 91 connectSignals(m_model);
405 } 406 }
406 407
407 return mapper; 408 return mapper;
408 } 409 }
409 410
410 FlexiNoteModel::PointList 411 EventVector
411 FlexiNoteLayer::getLocalPoints(LayerGeometryProvider *v, int x) const 412 FlexiNoteLayer::getLocalPoints(LayerGeometryProvider *v, int x) const
412 { 413 {
413 if (!m_model) return FlexiNoteModel::PointList(); 414 if (!m_model) return {};
414 415
415 sv_frame_t frame = v->getFrameForX(x); 416 sv_frame_t frame = v->getFrameForX(x);
416 417
417 FlexiNoteModel::PointList onPoints = 418 EventVector local = m_model->getEventsCovering(frame);
418 m_model->getPoints(frame); 419 if (!local.empty()) return local;
419 420
420 if (!onPoints.empty()) { 421 int fuzz = ViewManager::scalePixelSize(2);
421 return onPoints; 422 sv_frame_t start = v->getFrameForX(x - fuzz);
422 } 423 sv_frame_t end = v->getFrameForX(x + fuzz);
423 424
424 FlexiNoteModel::PointList prevPoints = 425 local = m_model->getEventsStartingWithin(frame, end - frame);
425 m_model->getPreviousPoints(frame); 426 if (!local.empty()) return local;
426 FlexiNoteModel::PointList nextPoints = 427
427 m_model->getNextPoints(frame); 428 local = m_model->getEventsSpanning(start, frame - start);
428 429 if (!local.empty()) return local;
429 FlexiNoteModel::PointList usePoints = prevPoints; 430
430 431 return {};
431 if (prevPoints.empty()) {
432 usePoints = nextPoints;
433 } else if (prevPoints.begin()->frame < v->getStartFrame() &&
434 !(nextPoints.begin()->frame > v->getEndFrame())) {
435 usePoints = nextPoints;
436 } else if (nextPoints.begin()->frame - frame <
437 frame - prevPoints.begin()->frame) {
438 usePoints = nextPoints;
439 }
440
441 if (!usePoints.empty()) {
442 int fuzz = ViewManager::scalePixelSize(2);
443 int px = v->getXForFrame(usePoints.begin()->frame);
444 if ((px > x && px - x > fuzz) ||
445 (px < x && x - px > fuzz + 1)) {
446 usePoints.clear();
447 }
448 }
449
450 return usePoints;
451 } 432 }
452 433
453 bool 434 bool
454 FlexiNoteLayer::getPointToDrag(LayerGeometryProvider *v, int x, int y, FlexiNoteModel::Point &p) const 435 FlexiNoteLayer::getPointToDrag(LayerGeometryProvider *v, int x, int y, Event &point) const
455 { 436 {
456 if (!m_model) return false; 437 if (!m_model) return false;
457 438
458 sv_frame_t frame = v->getFrameForX(x); 439 sv_frame_t frame = v->getFrameForX(x);
459 440
460 FlexiNoteModel::PointList onPoints = m_model->getPoints(frame); 441 EventVector onPoints = m_model->getEventsCovering(frame);
461 if (onPoints.empty()) return false; 442 if (onPoints.empty()) return false;
462 443
463 // cerr << "frame " << frame << ": " << onPoints.size() << " candidate points" << endl;
464
465 int nearestDistance = -1; 444 int nearestDistance = -1;
466 445 for (const auto &p: onPoints) {
467 for (FlexiNoteModel::PointList::const_iterator i = onPoints.begin(); 446 int distance = getYForValue(v, p.getValue()) - y;
468 i != onPoints.end(); ++i) {
469
470 int distance = getYForValue(v, (*i).value) - y;
471 if (distance < 0) distance = -distance; 447 if (distance < 0) distance = -distance;
472 if (nearestDistance == -1 || distance < nearestDistance) { 448 if (nearestDistance == -1 || distance < nearestDistance) {
473 nearestDistance = distance; 449 nearestDistance = distance;
474 p = *i; 450 point = p;
475 } 451 }
476 } 452 }
477 453
478 return true; 454 return true;
479 } 455 }
480 456
481 bool 457 bool
482 FlexiNoteLayer::getNoteToEdit(LayerGeometryProvider *v, int x, int y, FlexiNoteModel::Point &p) const 458 FlexiNoteLayer::getNoteToEdit(LayerGeometryProvider *v, int x, int y, Event &point) const
483 { 459 {
484 // GF: find the note that is closest to the cursor 460 // GF: find the note that is closest to the cursor
485 if (!m_model) return false; 461 if (!m_model) return false;
486 462
487 sv_frame_t frame = v->getFrameForX(x); 463 sv_frame_t frame = v->getFrameForX(x);
488 464
489 FlexiNoteModel::PointList onPoints = m_model->getPoints(frame); 465 EventVector onPoints = m_model->getEventsCovering(frame);
490 if (onPoints.empty()) return false; 466 if (onPoints.empty()) return false;
491 467
492 // std::cerr << "frame " << frame << ": " << onPoints.size() << " candidate points" << std::endl;
493
494 int nearestDistance = -1; 468 int nearestDistance = -1;
495 469 for (const auto &p: onPoints) {
496 for (FlexiNoteModel::PointList::const_iterator i = onPoints.begin(); 470 int distance = getYForValue(v, p.getValue()) - y;
497 i != onPoints.end(); ++i) {
498
499 int distance = getYForValue(v, (*i).value) - y;
500 if (distance < 0) distance = -distance; 471 if (distance < 0) distance = -distance;
501 if (nearestDistance == -1 || distance < nearestDistance) { 472 if (nearestDistance == -1 || distance < nearestDistance) {
502 nearestDistance = distance; 473 nearestDistance = distance;
503 p = *i; 474 point = p;
504 } 475 }
505 } 476 }
506 477
507 return true; 478 return true;
508 } 479 }
512 { 483 {
513 int x = pos.x(); 484 int x = pos.x();
514 485
515 if (!m_model || !m_model->getSampleRate()) return ""; 486 if (!m_model || !m_model->getSampleRate()) return "";
516 487
517 FlexiNoteModel::PointList points = getLocalPoints(v, x); 488 EventVector points = getLocalPoints(v, x);
518 489
519 if (points.empty()) { 490 if (points.empty()) {
520 if (!m_model->isReady()) { 491 if (!m_model->isReady()) {
521 return tr("In progress"); 492 return tr("In progress");
522 } else { 493 } else {
523 return tr("No local points"); 494 return tr("No local points");
524 } 495 }
525 } 496 }
526 497
527 FlexiNote note(0); 498 Event note(0);
528 FlexiNoteModel::PointList::iterator i; 499 EventVector::iterator i;
529 500
530 for (i = points.begin(); i != points.end(); ++i) { 501 for (i = points.begin(); i != points.end(); ++i) {
531 502
532 int y = getYForValue(v, i->value); 503 int y = getYForValue(v, i->getValue());
533 int h = NOTE_HEIGHT; // GF: larger notes 504 int h = NOTE_HEIGHT; // GF: larger notes
534 505
535 if (m_model->getValueQuantization() != 0.0) { 506 if (m_model->getValueQuantization() != 0.0) {
536 h = y - getYForValue(v, i->value + m_model->getValueQuantization()); 507 h = y - getYForValue
508 (v, i->getValue() + m_model->getValueQuantization());
537 if (h < NOTE_HEIGHT) h = NOTE_HEIGHT; 509 if (h < NOTE_HEIGHT) h = NOTE_HEIGHT;
538 } 510 }
539 511
540 // GF: this is not quite correct 512 // GF: this is not quite correct
541 if (pos.y() >= y - 4 && pos.y() <= y + h) { 513 if (pos.y() >= y - 4 && pos.y() <= y + h) {
544 } 516 }
545 } 517 }
546 518
547 if (i == points.end()) return tr("No local points"); 519 if (i == points.end()) return tr("No local points");
548 520
549 RealTime rt = RealTime::frame2RealTime(note.frame, 521 RealTime rt = RealTime::frame2RealTime(note.getFrame(),
550 m_model->getSampleRate()); 522 m_model->getSampleRate());
551 RealTime rd = RealTime::frame2RealTime(note.duration, 523 RealTime rd = RealTime::frame2RealTime(note.getDuration(),
552 m_model->getSampleRate()); 524 m_model->getSampleRate());
553 525
554 QString pitchText; 526 QString pitchText;
555 527
556 if (shouldConvertMIDIToHz()) { 528 if (shouldConvertMIDIToHz()) {
557 529
558 int mnote = int(lrint(note.value)); 530 int mnote = int(lrint(note.getValue()));
559 int cents = int(lrint((note.value - double(mnote)) * 100)); 531 int cents = int(lrint((note.getValue() - double(mnote)) * 100));
560 double freq = Pitch::getFrequencyForPitch(mnote, cents); 532 double freq = Pitch::getFrequencyForPitch(mnote, cents);
561 pitchText = tr("%1 (%2, %3 Hz)") 533 pitchText = tr("%1 (%2, %3 Hz)")
562 .arg(Pitch::getPitchLabel(mnote, cents)) 534 .arg(Pitch::getPitchLabel(mnote, cents))
563 .arg(mnote) 535 .arg(mnote)
564 .arg(freq); 536 .arg(freq);
565 537
566 } else if (getScaleUnits() == "Hz") { 538 } else if (getScaleUnits() == "Hz") {
567 539
568 pitchText = tr("%1 Hz (%2, %3)") 540 pitchText = tr("%1 Hz (%2, %3)")
569 .arg(note.value) 541 .arg(note.getValue())
570 .arg(Pitch::getPitchLabelForFrequency(note.value)) 542 .arg(Pitch::getPitchLabelForFrequency(note.getValue()))
571 .arg(Pitch::getPitchForFrequency(note.value)); 543 .arg(Pitch::getPitchForFrequency(note.getValue()));
572 544
573 } else { 545 } else {
574 pitchText = tr("%1 %2") 546 pitchText = tr("%1 %2")
575 .arg(note.value).arg(getScaleUnits()); 547 .arg(note.getValue()).arg(getScaleUnits());
576 } 548 }
577 549
578 QString text; 550 QString text;
579 551
580 if (note.label == "") { 552 if (note.getLabel() == "") {
581 text = QString(tr("Time:\t%1\nPitch:\t%2\nDuration:\t%3\nNo label")) 553 text = QString(tr("Time:\t%1\nPitch:\t%2\nDuration:\t%3\nNo label"))
582 .arg(rt.toText(true).c_str()) 554 .arg(rt.toText(true).c_str())
583 .arg(pitchText) 555 .arg(pitchText)
584 .arg(rd.toText(true).c_str()); 556 .arg(rd.toText(true).c_str());
585 } else { 557 } else {
586 text = QString(tr("Time:\t%1\nPitch:\t%2\nDuration:\t%3\nLabel:\t%4")) 558 text = QString(tr("Time:\t%1\nPitch:\t%2\nDuration:\t%3\nLabel:\t%4"))
587 .arg(rt.toText(true).c_str()) 559 .arg(rt.toText(true).c_str())
588 .arg(pitchText) 560 .arg(pitchText)
589 .arg(rd.toText(true).c_str()) 561 .arg(rd.toText(true).c_str())
590 .arg(note.label); 562 .arg(note.getLabel());
591 } 563 }
592 564
593 pos = QPoint(v->getXForFrame(note.frame), 565 pos = QPoint(v->getXForFrame(note.getFrame()),
594 getYForValue(v, note.value)); 566 getYForValue(v, note.getValue()));
595 return text; 567 return text;
596 } 568 }
597 569
598 bool 570 bool
599 FlexiNoteLayer::snapToFeatureFrame(LayerGeometryProvider *v, sv_frame_t &frame, 571 FlexiNoteLayer::snapToFeatureFrame(LayerGeometryProvider *v, sv_frame_t &frame,
603 if (!m_model) { 575 if (!m_model) {
604 return Layer::snapToFeatureFrame(v, frame, resolution, snap); 576 return Layer::snapToFeatureFrame(v, frame, resolution, snap);
605 } 577 }
606 578
607 resolution = m_model->getResolution(); 579 resolution = m_model->getResolution();
608 FlexiNoteModel::PointList points; 580 EventVector points;
609 581
610 if (snap == SnapNeighbouring) { 582 if (snap == SnapNeighbouring) {
611 583
612 points = getLocalPoints(v, v->getXForFrame(frame)); 584 points = getLocalPoints(v, v->getXForFrame(frame));
613 if (points.empty()) return false; 585 if (points.empty()) return false;
614 frame = points.begin()->frame; 586 frame = points.begin()->getFrame();
615 return true; 587 return true;
616 } 588 }
617 589
618 points = m_model->getPoints(frame, frame); 590 points = m_model->getEventsCovering(frame);
619 sv_frame_t snapped = frame; 591 sv_frame_t snapped = frame;
620 bool found = false; 592 bool found = false;
621 593
622 for (FlexiNoteModel::PointList::const_iterator i = points.begin(); 594 for (EventVector::const_iterator i = points.begin();
623 i != points.end(); ++i) { 595 i != points.end(); ++i) {
624 596
625 cerr << "FlexiNoteModel: point at " << i->frame << endl;
626
627 if (snap == SnapRight) { 597 if (snap == SnapRight) {
628 598
629 if (i->frame > frame) { 599 if (i->getFrame() > frame) {
630 snapped = i->frame; 600 snapped = i->getFrame();
631 found = true; 601 found = true;
632 break; 602 break;
633 } else if (i->frame + i->duration >= frame) { 603 } else if (i->getFrame() + i->getDuration() >= frame) {
634 snapped = i->frame + i->duration; 604 snapped = i->getFrame() + i->getDuration();
635 found = true; 605 found = true;
636 break; 606 break;
637 } 607 }
638 608
639 } else if (snap == SnapLeft) { 609 } else if (snap == SnapLeft) {
640 610
641 if (i->frame <= frame) { 611 if (i->getFrame() <= frame) {
642 snapped = i->frame; 612 snapped = i->getFrame();
643 found = true; // don't break, as the next may be better 613 found = true; // don't break, as the next may be better
644 } else { 614 } else {
645 break; 615 break;
646 } 616 }
647 617
648 } else { // nearest 618 } else { // nearest
649 619
650 FlexiNoteModel::PointList::const_iterator j = i; 620 EventVector::const_iterator j = i;
651 ++j; 621 ++j;
652 622
653 if (j == points.end()) { 623 if (j == points.end()) {
654 624
655 snapped = i->frame; 625 snapped = i->getFrame();
656 found = true; 626 found = true;
657 break; 627 break;
658 628
659 } else if (j->frame >= frame) { 629 } else if (j->getFrame() >= frame) {
660 630
661 if (j->frame - frame < frame - i->frame) { 631 if (j->getFrame() - frame < frame - i->getFrame()) {
662 snapped = j->frame; 632 snapped = j->getFrame();
663 } else { 633 } else {
664 snapped = i->frame; 634 snapped = i->getFrame();
665 } 635 }
666 found = true; 636 found = true;
667 break; 637 break;
668 } 638 }
669 } 639 }
804 sv_samplerate_t sampleRate = m_model->getSampleRate(); 774 sv_samplerate_t sampleRate = m_model->getSampleRate();
805 if (!sampleRate) return; 775 if (!sampleRate) return;
806 776
807 // Profiler profiler("FlexiNoteLayer::paint", true); 777 // Profiler profiler("FlexiNoteLayer::paint", true);
808 778
809 int x1 = rect.right(); 779 int x0 = rect.left(), x1 = rect.right();
780 sv_frame_t frame0 = v->getFrameForX(x0);
810 sv_frame_t frame1 = v->getFrameForX(x1); 781 sv_frame_t frame1 = v->getFrameForX(x1);
811 782
812 FlexiNoteModel::PointList points(m_model->getPoints(0, frame1)); 783 EventVector points(m_model->getEventsSpanning(frame0, frame1 - frame0));
813 if (points.empty()) return; 784 if (points.empty()) return;
814 785
815 paint.setPen(getBaseQColor()); 786 paint.setPen(getBaseQColor());
816 787
817 QColor brushColour(getBaseQColor()); 788 QColor brushColour(getBaseQColor());
823 double min = m_model->getValueMinimum(); 794 double min = m_model->getValueMinimum();
824 double max = m_model->getValueMaximum(); 795 double max = m_model->getValueMaximum();
825 if (max == min) max = min + 1.0; 796 if (max == min) max = min + 1.0;
826 797
827 QPoint localPos; 798 QPoint localPos;
828 FlexiNoteModel::Point illuminatePoint(0); 799 Event illuminatePoint(0);
829 bool shouldIlluminate = false; 800 bool shouldIlluminate = false;
830 801
831 if (v->shouldIlluminateLocalFeatures(this, localPos)) { 802 if (v->shouldIlluminateLocalFeatures(this, localPos)) {
832 shouldIlluminate = getPointToDrag(v, localPos.x(), localPos.y(), 803 shouldIlluminate = getPointToDrag(v, localPos.x(), localPos.y(),
833 illuminatePoint); 804 illuminatePoint);
836 paint.save(); 807 paint.save();
837 paint.setRenderHint(QPainter::Antialiasing, false); 808 paint.setRenderHint(QPainter::Antialiasing, false);
838 809
839 int noteNumber = 0; 810 int noteNumber = 0;
840 811
841 for (FlexiNoteModel::PointList::const_iterator i = points.begin(); 812 for (EventVector::const_iterator i = points.begin();
842 i != points.end(); ++i) { 813 i != points.end(); ++i) {
843 814
844 ++noteNumber; 815 ++noteNumber;
845 const FlexiNoteModel::Point &p(*i); 816 const Event &p(*i);
846 817
847 int x = v->getXForFrame(p.frame); 818 int x = v->getXForFrame(p.getFrame());
848 int y = getYForValue(v, p.value); 819 int y = getYForValue(v, p.getValue());
849 int w = v->getXForFrame(p.frame + p.duration) - x; 820 int w = v->getXForFrame(p.getFrame() + p.getDuration()) - x;
850 int h = NOTE_HEIGHT; //GF: larger notes 821 int h = NOTE_HEIGHT; //GF: larger notes
851 822
852 if (m_model->getValueQuantization() != 0.0) { 823 if (m_model->getValueQuantization() != 0.0) {
853 h = y - getYForValue(v, p.value + m_model->getValueQuantization()); 824 h = y - getYForValue(v, p.getValue() + m_model->getValueQuantization());
854 if (h < NOTE_HEIGHT) h = NOTE_HEIGHT; //GF: larger notes 825 if (h < NOTE_HEIGHT) h = NOTE_HEIGHT; //GF: larger notes
855 } 826 }
856 827
857 if (w < 1) w = 1; 828 if (w < 1) w = 1;
858 paint.setPen(getBaseQColor()); 829 paint.setPen(getBaseQColor());
859 paint.setBrush(brushColour); 830 paint.setBrush(brushColour);
860 831
861 if (shouldIlluminate && 832 if (shouldIlluminate && illuminatePoint == p) {
862 // "illuminatePoint == p" 833
863 !FlexiNoteModel::Point::Comparator()(illuminatePoint, p) && 834 paint.drawLine(x, -1, x, v->getPaintHeight() + 1);
864 !FlexiNoteModel::Point::Comparator()(p, illuminatePoint)) { 835 paint.drawLine(x+w, -1, x+w, v->getPaintHeight() + 1);
865
866 paint.drawLine(x, -1, x, v->getPaintHeight() + 1);
867 paint.drawLine(x+w, -1, x+w, v->getPaintHeight() + 1);
868 836
869 paint.setPen(v->getForeground()); 837 paint.setPen(v->getForeground());
870 // paint.setBrush(v->getForeground());
871 838
872 QString vlabel = QString("freq: %1%2").arg(p.value).arg(m_model->getScaleUnits()); 839 QString vlabel = tr("freq: %1%2")
873 // PaintAssistant::drawVisibleText(v, paint, 840 .arg(p.getValue()).arg(m_model->getScaleUnits());
874 // x - paint.fontMetrics().width(vlabel) - 2, 841 PaintAssistant::drawVisibleText
875 // y + paint.fontMetrics().height()/2 842 (v, paint,
876 // - paint.fontMetrics().descent(), 843 x,
877 // vlabel, PaintAssistant::OutlinedText); 844 y - h/2 - 2 - paint.fontMetrics().height()
878 PaintAssistant::drawVisibleText(v, paint, 845 - paint.fontMetrics().descent(),
879 x, 846 vlabel, PaintAssistant::OutlinedText);
880 y - h/2 - 2 - paint.fontMetrics().height() 847
881 - paint.fontMetrics().descent(), 848 QString hlabel = tr("dur: %1")
882 vlabel, PaintAssistant::OutlinedText); 849 .arg(RealTime::frame2RealTime
883 850 (p.getDuration(), m_model->getSampleRate()).toText(true)
884 QString hlabel = "dur: " + QString(RealTime::frame2RealTime 851 .c_str());
885 (p.duration, m_model->getSampleRate()).toText(true).c_str()); 852 PaintAssistant::drawVisibleText
886 PaintAssistant::drawVisibleText(v, paint, 853 (v, paint,
887 x, 854 x,
888 y - h/2 - paint.fontMetrics().descent() - 2, 855 y - h/2 - paint.fontMetrics().descent() - 2,
889 hlabel, PaintAssistant::OutlinedText); 856 hlabel, PaintAssistant::OutlinedText);
890 857
891 QString llabel = QString("%1").arg(p.label); 858 QString llabel = QString("%1").arg(p.getLabel());
892 PaintAssistant::drawVisibleText(v, paint, 859 PaintAssistant::drawVisibleText
893 x, 860 (v, paint,
894 y + h + 2 + paint.fontMetrics().descent(), 861 x,
895 llabel, PaintAssistant::OutlinedText); 862 y + h + 2 + paint.fontMetrics().descent(),
896 QString nlabel = QString("%1").arg(noteNumber); 863 llabel, PaintAssistant::OutlinedText);
897 PaintAssistant::drawVisibleText(v, paint, 864
898 x + paint.fontMetrics().averageCharWidth() / 2, 865 QString nlabel = QString("%1").arg(noteNumber);
899 y + h/2 - paint.fontMetrics().descent(), 866 PaintAssistant::drawVisibleText
900 nlabel, PaintAssistant::OutlinedText); 867 (v, paint,
868 x + paint.fontMetrics().averageCharWidth() / 2,
869 y + h/2 - paint.fontMetrics().descent(),
870 nlabel, PaintAssistant::OutlinedText);
901 } 871 }
902 872
903 paint.drawRect(x, y - h/2, w, h); 873 paint.drawRect(x, y - h/2, w, h);
904 } 874 }
905 875
921 } 891 }
922 892
923 void 893 void
924 FlexiNoteLayer::paintVerticalScale(LayerGeometryProvider *v, bool, QPainter &paint, QRect) const 894 FlexiNoteLayer::paintVerticalScale(LayerGeometryProvider *v, bool, QPainter &paint, QRect) const
925 { 895 {
926 if (!m_model || m_model->getPoints().empty()) return; 896 if (!m_model || m_model->isEmpty()) return;
927 897
928 QString unit; 898 QString unit;
929 double min, max; 899 double min, max;
930 bool logarithmic; 900 bool logarithmic;
931 901
969 if (frame < 0) frame = 0; 939 if (frame < 0) frame = 0;
970 frame = frame / m_model->getResolution() * m_model->getResolution(); 940 frame = frame / m_model->getResolution() * m_model->getResolution();
971 941
972 double value = getValueForY(v, e->y()); 942 double value = getValueForY(v, e->y());
973 943
974 m_editingPoint = FlexiNoteModel::Point(frame, float(value), 0, 0.8f, tr("New Point")); 944 m_editingPoint = Event(frame, float(value), 0, 0.8f, tr("New Point"));
975 m_originalPoint = m_editingPoint; 945 m_originalPoint = m_editingPoint;
976 946
977 if (m_editingCommand) finish(m_editingCommand); 947 if (m_editingCommand) finish(m_editingCommand);
978 m_editingCommand = new FlexiNoteModel::EditCommand(m_model, 948 m_editingCommand = new NoteModel::EditCommand(m_model, tr("Draw Point"));
979 tr("Draw Point")); 949 m_editingCommand->add(m_editingPoint);
980 m_editingCommand->addPoint(m_editingPoint);
981 950
982 m_editing = true; 951 m_editing = true;
983 } 952 }
984 953
985 void 954 void
993 if (frame < 0) frame = 0; 962 if (frame < 0) frame = 0;
994 frame = frame / m_model->getResolution() * m_model->getResolution(); 963 frame = frame / m_model->getResolution() * m_model->getResolution();
995 964
996 double newValue = getValueForY(v, e->y()); 965 double newValue = getValueForY(v, e->y());
997 966
998 sv_frame_t newFrame = m_editingPoint.frame; 967 sv_frame_t newFrame = m_editingPoint.getFrame();
999 sv_frame_t newDuration = frame - newFrame; 968 sv_frame_t newDuration = frame - newFrame;
1000 if (newDuration < 0) { 969 if (newDuration < 0) {
1001 newFrame = frame; 970 newFrame = frame;
1002 newDuration = -newDuration; 971 newDuration = -newDuration;
1003 } else if (newDuration == 0) { 972 } else if (newDuration == 0) {
1004 newDuration = 1; 973 newDuration = 1;
1005 } 974 }
1006 975
1007 m_editingCommand->deletePoint(m_editingPoint); 976 m_editingCommand->remove(m_editingPoint);
1008 m_editingPoint.frame = newFrame; 977 m_editingPoint = m_editingPoint
1009 m_editingPoint.value = float(newValue); 978 .withFrame(newFrame)
1010 m_editingPoint.duration = newDuration; 979 .withValue(float(newValue))
1011 m_editingCommand->addPoint(m_editingPoint); 980 .withDuration(newDuration);
981 m_editingCommand->add(m_editingPoint);
1012 } 982 }
1013 983
1014 void 984 void
1015 FlexiNoteLayer::drawEnd(LayerGeometryProvider *, QMouseEvent *) 985 FlexiNoteLayer::drawEnd(LayerGeometryProvider *, QMouseEvent *)
1016 { 986 {
1046 { 1016 {
1047 if (!m_model || !m_editing) return; 1017 if (!m_model || !m_editing) return;
1048 1018
1049 m_editing = false; 1019 m_editing = false;
1050 1020
1051 FlexiNoteModel::Point p(0); 1021 Event p(0);
1052 if (!getPointToDrag(v, e->x(), e->y(), p)) return; 1022 if (!getPointToDrag(v, e->x(), e->y(), p)) return;
1053 if (p.frame != m_editingPoint.frame || p.value != m_editingPoint.value) return; 1023 if (p.getFrame() != m_editingPoint.getFrame() || p.getValue() != m_editingPoint.getValue()) return;
1054 1024
1055 m_editingCommand = new FlexiNoteModel::EditCommand(m_model, tr("Erase Point")); 1025 m_editingCommand = new NoteModel::EditCommand(m_model, tr("Erase Point"));
1056 1026
1057 m_editingCommand->deletePoint(m_editingPoint); 1027 m_editingCommand->remove(m_editingPoint);
1058 1028
1059 finish(m_editingCommand); 1029 finish(m_editingCommand);
1060 m_editingCommand = nullptr; 1030 m_editingCommand = nullptr;
1061 m_editing = false; 1031 m_editing = false;
1062 } 1032 }
1068 std::cerr << "FlexiNoteLayer::editStart(" << e->x() << "," << e->y() << ")" << std::endl; 1038 std::cerr << "FlexiNoteLayer::editStart(" << e->x() << "," << e->y() << ")" << std::endl;
1069 1039
1070 if (!m_model) return; 1040 if (!m_model) return;
1071 1041
1072 if (!getPointToDrag(v, e->x(), e->y(), m_editingPoint)) return; 1042 if (!getPointToDrag(v, e->x(), e->y(), m_editingPoint)) return;
1073 m_originalPoint = FlexiNote(m_editingPoint); 1043 m_originalPoint = m_editingPoint;
1074 1044
1075 if (m_editMode == RightBoundary) { 1045 if (m_editMode == RightBoundary) {
1076 m_dragPointX = v->getXForFrame(m_editingPoint.frame + m_editingPoint.duration); 1046 m_dragPointX = v->getXForFrame
1047 (m_editingPoint.getFrame() + m_editingPoint.getDuration());
1077 } else { 1048 } else {
1078 m_dragPointX = v->getXForFrame(m_editingPoint.frame); 1049 m_dragPointX = v->getXForFrame
1079 } 1050 (m_editingPoint.getFrame());
1080 m_dragPointY = getYForValue(v, m_editingPoint.value); 1051 }
1052 m_dragPointY = getYForValue(v, m_editingPoint.getValue());
1081 1053
1082 if (m_editingCommand) { 1054 if (m_editingCommand) {
1083 finish(m_editingCommand); 1055 finish(m_editingCommand);
1084 m_editingCommand = nullptr; 1056 m_editingCommand = nullptr;
1085 } 1057 }
1086 1058
1087 m_editing = true; 1059 m_editing = true;
1088 m_dragStartX = e->x(); 1060 m_dragStartX = e->x();
1089 m_dragStartY = e->y(); 1061 m_dragStartY = e->y();
1090 1062
1091 sv_frame_t onset = m_originalPoint.frame; 1063 sv_frame_t onset = m_originalPoint.getFrame();
1092 sv_frame_t offset = m_originalPoint.frame + m_originalPoint.duration - 1; 1064 sv_frame_t offset =
1065 m_originalPoint.getFrame() +
1066 m_originalPoint.getDuration() - 1;
1093 1067
1094 m_greatestLeftNeighbourFrame = -1; 1068 m_greatestLeftNeighbourFrame = -1;
1095 m_smallestRightNeighbourFrame = std::numeric_limits<int>::max(); 1069 m_smallestRightNeighbourFrame = std::numeric_limits<int>::max();
1096 1070
1097 for (FlexiNoteModel::PointList::const_iterator i = m_model->getPoints().begin(); 1071 EventVector allEvents = m_model->getAllEvents();
1098 i != m_model->getPoints().end(); ++i) { 1072
1099 FlexiNote currentNote = *i; 1073 for (auto currentNote: allEvents) {
1100 1074
1101 // left boundary 1075 // left boundary
1102 if (currentNote.frame + currentNote.duration - 1 < onset) { 1076 if (currentNote.getFrame() + currentNote.getDuration() - 1 < onset) {
1103 m_greatestLeftNeighbourFrame = currentNote.frame + currentNote.duration - 1; 1077 m_greatestLeftNeighbourFrame =
1078 currentNote.getFrame() + currentNote.getDuration() - 1;
1104 } 1079 }
1105 1080
1106 // right boundary 1081 // right boundary
1107 if (currentNote.frame > offset) { 1082 if (currentNote.getFrame() > offset) {
1108 m_smallestRightNeighbourFrame = currentNote.frame; 1083 m_smallestRightNeighbourFrame = currentNote.getFrame();
1109 break; 1084 break;
1110 } 1085 }
1111 } 1086 }
1087
1112 std::cerr << "editStart: mode is " << m_editMode << ", note frame: " << onset << ", left boundary: " << m_greatestLeftNeighbourFrame << ", right boundary: " << m_smallestRightNeighbourFrame << std::endl; 1088 std::cerr << "editStart: mode is " << m_editMode << ", note frame: " << onset << ", left boundary: " << m_greatestLeftNeighbourFrame << ", right boundary: " << m_smallestRightNeighbourFrame << std::endl;
1113 } 1089 }
1114 1090
1115 void 1091 void
1116 FlexiNoteLayer::editDrag(LayerGeometryProvider *v, QMouseEvent *e) 1092 FlexiNoteLayer::editDrag(LayerGeometryProvider *v, QMouseEvent *e)
1130 dragFrame = dragFrame / m_model->getResolution() * m_model->getResolution(); 1106 dragFrame = dragFrame / m_model->getResolution() * m_model->getResolution();
1131 1107
1132 double value = getValueForY(v, newy); 1108 double value = getValueForY(v, newy);
1133 1109
1134 if (!m_editingCommand) { 1110 if (!m_editingCommand) {
1135 m_editingCommand = new FlexiNoteModel::EditCommand(m_model, 1111 m_editingCommand = new NoteModel::EditCommand(m_model,
1136 tr("Drag Point")); 1112 tr("Drag Point"));
1137 } 1113 }
1138 1114
1139 m_editingCommand->deletePoint(m_editingPoint); 1115 m_editingCommand->remove(m_editingPoint);
1140 1116
1141 std::cerr << "edit mode: " << m_editMode << " intelligent actions = " 1117 std::cerr << "edit mode: " << m_editMode << " intelligent actions = "
1142 << m_intelligentActions << std::endl; 1118 << m_intelligentActions << std::endl;
1143 1119
1144 switch (m_editMode) { 1120 switch (m_editMode) {
1121
1145 case LeftBoundary : { 1122 case LeftBoundary : {
1146 // left 1123 // left
1147 if (m_intelligentActions && dragFrame <= m_greatestLeftNeighbourFrame) dragFrame = m_greatestLeftNeighbourFrame + 1; 1124 if (m_intelligentActions &&
1125 dragFrame <= m_greatestLeftNeighbourFrame) {
1126 dragFrame = m_greatestLeftNeighbourFrame + 1;
1127 }
1148 // right 1128 // right
1149 if (m_intelligentActions && dragFrame >= m_originalPoint.frame + m_originalPoint.duration) { 1129 if (m_intelligentActions &&
1150 dragFrame = m_originalPoint.frame + m_originalPoint.duration - 1; 1130 dragFrame >= m_originalPoint.getFrame() + m_originalPoint.getDuration()) {
1151 } 1131 dragFrame = m_originalPoint.getFrame() + m_originalPoint.getDuration() - 1;
1152 m_editingPoint.frame = dragFrame; 1132 }
1153 m_editingPoint.duration = m_originalPoint.frame - dragFrame + m_originalPoint.duration; 1133 m_editingPoint = m_editingPoint
1134 .withFrame(dragFrame)
1135 .withDuration(m_originalPoint.getFrame() -
1136 dragFrame + m_originalPoint.getDuration());
1154 break; 1137 break;
1155 } 1138 }
1139
1156 case RightBoundary : { 1140 case RightBoundary : {
1157 // left 1141 // left
1158 if (m_intelligentActions && dragFrame <= m_greatestLeftNeighbourFrame) dragFrame = m_greatestLeftNeighbourFrame + 1; 1142 if (m_intelligentActions &&
1159 if (m_intelligentActions && dragFrame >= m_smallestRightNeighbourFrame) dragFrame = m_smallestRightNeighbourFrame - 1; 1143 dragFrame <= m_greatestLeftNeighbourFrame) {
1160 m_editingPoint.duration = dragFrame - m_originalPoint.frame + 1; 1144 dragFrame = m_greatestLeftNeighbourFrame + 1;
1145 }
1146 if (m_intelligentActions &&
1147 dragFrame >= m_smallestRightNeighbourFrame) {
1148 dragFrame = m_smallestRightNeighbourFrame - 1;
1149 }
1150 m_editingPoint = m_editingPoint
1151 .withDuration(dragFrame - m_originalPoint.getFrame() + 1);
1161 break; 1152 break;
1162 } 1153 }
1154
1163 case DragNote : { 1155 case DragNote : {
1164 // left 1156 // left
1165 if (m_intelligentActions && dragFrame <= m_greatestLeftNeighbourFrame) dragFrame = m_greatestLeftNeighbourFrame + 1; 1157 if (m_intelligentActions &&
1158 dragFrame <= m_greatestLeftNeighbourFrame) {
1159 dragFrame = m_greatestLeftNeighbourFrame + 1;
1160 }
1166 // right 1161 // right
1167 if (m_intelligentActions && dragFrame + m_originalPoint.duration >= m_smallestRightNeighbourFrame) { 1162 if (m_intelligentActions &&
1168 dragFrame = m_smallestRightNeighbourFrame - m_originalPoint.duration; 1163 dragFrame + m_originalPoint.getDuration() >= m_smallestRightNeighbourFrame) {
1169 } 1164 dragFrame = m_smallestRightNeighbourFrame - m_originalPoint.getDuration();
1170 m_editingPoint.frame = dragFrame; 1165 }
1171 1166
1172 m_editingPoint.value = float(value); 1167 m_editingPoint = m_editingPoint
1168 .withFrame(dragFrame)
1169 .withValue(float(value));
1173 1170
1174 // Re-analyse region within +/- 1 semitone of the dragged value 1171 // Re-analyse region within +/- 1 semitone of the dragged value
1175 float cents = 0; 1172 float cents = 0;
1176 int midiPitch = Pitch::getPitchForFrequency(m_editingPoint.value, &cents); 1173 int midiPitch = Pitch::getPitchForFrequency(m_editingPoint.getValue(), &cents);
1177 double lower = Pitch::getFrequencyForPitch(midiPitch - 1, cents); 1174 double lower = Pitch::getFrequencyForPitch(midiPitch - 1, cents);
1178 double higher = Pitch::getFrequencyForPitch(midiPitch + 1, cents); 1175 double higher = Pitch::getFrequencyForPitch(midiPitch + 1, cents);
1179 1176
1180 emit reAnalyseRegion(m_editingPoint.frame, 1177 emit reAnalyseRegion(m_editingPoint.getFrame(),
1181 m_editingPoint.frame + m_editingPoint.duration, 1178 m_editingPoint.getFrame() +
1179 m_editingPoint.getDuration(),
1182 float(lower), float(higher)); 1180 float(lower), float(higher));
1183 break; 1181 break;
1184 } 1182 }
1183
1185 case SplitNote: // nothing 1184 case SplitNote: // nothing
1186 break; 1185 break;
1187 } 1186 }
1188 1187
1189 // updateNoteValueFromPitchCurve(v, m_editingPoint); 1188 m_editingCommand->add(m_editingPoint);
1190 m_editingCommand->addPoint(m_editingPoint); 1189
1191 1190 std::cerr << "added new point(" << m_editingPoint.getFrame() << "," << m_editingPoint.getDuration() << ")" << std::endl;
1192 std::cerr << "added new point(" << m_editingPoint.frame << "," << m_editingPoint.duration << ")" << std::endl;
1193 } 1191 }
1194 1192
1195 void 1193 void
1196 FlexiNoteLayer::editEnd(LayerGeometryProvider *v, QMouseEvent *e) 1194 FlexiNoteLayer::editEnd(LayerGeometryProvider *v, QMouseEvent *e)
1197 { 1195 {
1198 // SVDEBUG << "FlexiNoteLayer::editEnd(" << e->x() << "," << e->y() << ")" << endl; 1196 std::cerr << "FlexiNoteLayer::editEnd("
1199 std::cerr << "FlexiNoteLayer::editEnd(" << e->x() << "," << e->y() << ")" << std::endl; 1197 << e->x() << "," << e->y() << ")" << std::endl;
1200 1198
1201 if (!m_model || !m_editing) return; 1199 if (!m_model || !m_editing) return;
1202 1200
1203 if (m_editingCommand) { 1201 if (m_editingCommand) {
1204 1202
1207 if (m_editMode == DragNote) { 1205 if (m_editMode == DragNote) {
1208 //!!! command nesting is wrong? 1206 //!!! command nesting is wrong?
1209 emit materialiseReAnalysis(); 1207 emit materialiseReAnalysis();
1210 } 1208 }
1211 1209
1212 m_editingCommand->deletePoint(m_editingPoint); 1210 m_editingCommand->remove(m_editingPoint);
1213 updateNoteValueFromPitchCurve(v, m_editingPoint); 1211 updateNoteValueFromPitchCurve(v, m_editingPoint);
1214 m_editingCommand->addPoint(m_editingPoint); 1212 m_editingCommand->add(m_editingPoint);
1215 1213
1216 if (m_editingPoint.frame != m_originalPoint.frame) { 1214 if (m_editingPoint.getFrame() != m_originalPoint.getFrame()) {
1217 if (m_editingPoint.value != m_originalPoint.value) { 1215 if (m_editingPoint.getValue() != m_originalPoint.getValue()) {
1218 newName = tr("Edit Point"); 1216 newName = tr("Edit Point");
1219 } else { 1217 } else {
1220 newName = tr("Relocate Point"); 1218 newName = tr("Relocate Point");
1221 } 1219 }
1222 } else { 1220 } else {
1239 if (!m_model) return; 1237 if (!m_model) return;
1240 1238
1241 if (!getPointToDrag(v, e->x(), e->y(), m_editingPoint)) return; 1239 if (!getPointToDrag(v, e->x(), e->y(), m_editingPoint)) return;
1242 // m_originalPoint = m_editingPoint; 1240 // m_originalPoint = m_editingPoint;
1243 // 1241 //
1244 // m_dragPointX = v->getXForFrame(m_editingPoint.frame); 1242 // m_dragPointX = v->getXForFrame(m_editingPoint.getFrame());
1245 // m_dragPointY = getYForValue(v, m_editingPoint.value); 1243 // m_dragPointY = getYForValue(v, m_editingPoint.getValue());
1246 1244
1247 if (m_editingCommand) { 1245 if (m_editingCommand) {
1248 finish(m_editingCommand); 1246 finish(m_editingCommand);
1249 m_editingCommand = nullptr; 1247 m_editingCommand = nullptr;
1250 } 1248 }
1280 } 1278 }
1281 1279
1282 void 1280 void
1283 FlexiNoteLayer::splitNotesAt(LayerGeometryProvider *v, sv_frame_t frame, QMouseEvent *e) 1281 FlexiNoteLayer::splitNotesAt(LayerGeometryProvider *v, sv_frame_t frame, QMouseEvent *e)
1284 { 1282 {
1285 FlexiNoteModel::PointList onPoints = m_model->getPoints(frame); 1283 EventVector onPoints = m_model->getEventsCovering(frame);
1286 if (onPoints.empty()) return; 1284 if (onPoints.empty()) return;
1287 1285
1288 FlexiNote note(*onPoints.begin()); 1286 Event note(*onPoints.begin());
1289 1287
1290 FlexiNoteModel::EditCommand *command = new FlexiNoteModel::EditCommand 1288 NoteModel::EditCommand *command = new NoteModel::EditCommand
1291 (m_model, tr("Edit Point")); 1289 (m_model, tr("Edit Point"));
1292 command->deletePoint(note); 1290 command->remove(note);
1293 1291
1294 if (!e || !(e->modifiers() & Qt::ShiftModifier)) { 1292 if (!e || !(e->modifiers() & Qt::ShiftModifier)) {
1295 1293
1296 int gap = 0; // MM: I prefer a gap of 0, but we can decide later 1294 int gap = 0; // MM: I prefer a gap of 0, but we can decide later
1297 1295
1298 FlexiNote newNote1(note.frame, note.value, 1296 Event newNote1(note.getFrame(), note.getValue(),
1299 frame - note.frame - gap, 1297 frame - note.getFrame() - gap,
1300 note.level, note.label); 1298 note.getLevel(), note.getLabel());
1301 1299
1302 FlexiNote newNote2(frame, note.value, 1300 Event newNote2(frame, note.getValue(),
1303 note.duration - newNote1.duration, 1301 note.getDuration() - newNote1.getDuration(),
1304 note.level, note.label); 1302 note.getLevel(), note.getLabel());
1305 1303
1306 if (m_intelligentActions) { 1304 if (m_intelligentActions) {
1307 if (updateNoteValueFromPitchCurve(v, newNote1)) { 1305 if (updateNoteValueFromPitchCurve(v, newNote1)) {
1308 command->addPoint(newNote1); 1306 command->add(newNote1);
1309 } 1307 }
1310 if (updateNoteValueFromPitchCurve(v, newNote2)) { 1308 if (updateNoteValueFromPitchCurve(v, newNote2)) {
1311 command->addPoint(newNote2); 1309 command->add(newNote2);
1312 } 1310 }
1313 } else { 1311 } else {
1314 command->addPoint(newNote1); 1312 command->add(newNote1);
1315 command->addPoint(newNote2); 1313 command->add(newNote2);
1316 } 1314 }
1317 } 1315 }
1318 1316
1319 finish(command); 1317 finish(command);
1320 } 1318 }
1328 sv_frame_t duration = 10000; 1326 sv_frame_t duration = 10000;
1329 1327
1330 sv_frame_t frame = v->getFrameForX(e->x()); 1328 sv_frame_t frame = v->getFrameForX(e->x());
1331 double value = getValueForY(v, e->y()); 1329 double value = getValueForY(v, e->y());
1332 1330
1333 FlexiNoteModel::PointList noteList = m_model->getPoints(); 1331 EventVector noteList = m_model->getAllEvents();
1334 1332
1335 if (m_intelligentActions) { 1333 if (m_intelligentActions) {
1336 sv_frame_t smallestRightNeighbourFrame = 0; 1334 sv_frame_t smallestRightNeighbourFrame = 0;
1337 for (FlexiNoteModel::PointList::const_iterator i = noteList.begin(); 1335 for (EventVector::const_iterator i = noteList.begin();
1338 i != noteList.end(); ++i) { 1336 i != noteList.end(); ++i) {
1339 FlexiNote currentNote = *i; 1337 Event currentNote = *i;
1340 if (currentNote.frame > frame) { 1338 if (currentNote.getFrame() > frame) {
1341 smallestRightNeighbourFrame = currentNote.frame; 1339 smallestRightNeighbourFrame = currentNote.getFrame();
1342 break; 1340 break;
1343 } 1341 }
1344 } 1342 }
1345 if (smallestRightNeighbourFrame > 0) { 1343 if (smallestRightNeighbourFrame > 0) {
1346 duration = std::min(smallestRightNeighbourFrame - frame + 1, duration); 1344 duration = std::min(smallestRightNeighbourFrame - frame + 1, duration);
1347 duration = (duration > 0) ? duration : 0; 1345 duration = (duration > 0) ? duration : 0;
1348 } 1346 }
1349 } 1347 }
1350 1348
1351 if (!m_intelligentActions || 1349 if (!m_intelligentActions ||
1352 (m_model->getPoints(frame).empty() && duration > 0)) { 1350 (m_model->getEventsCovering(frame).empty() && duration > 0)) {
1353 FlexiNote newNote(frame, float(value), duration, 100.f, "new note"); 1351 Event newNote(frame, float(value), duration, 100.f, tr("new note"));
1354 FlexiNoteModel::EditCommand *command = new FlexiNoteModel::EditCommand 1352 NoteModel::EditCommand *command = new NoteModel::EditCommand
1355 (m_model, tr("Add Point")); 1353 (m_model, tr("Add Point"));
1356 command->addPoint(newNote); 1354 command->add(newNote);
1357 finish(command); 1355 finish(command);
1358 } 1356 }
1359 } 1357 }
1360 1358
1361 SparseTimeValueModel * 1359 SparseTimeValueModel *
1386 void 1384 void
1387 FlexiNoteLayer::snapSelectedNotesToPitchTrack(LayerGeometryProvider *v, Selection s) 1385 FlexiNoteLayer::snapSelectedNotesToPitchTrack(LayerGeometryProvider *v, Selection s)
1388 { 1386 {
1389 if (!m_model) return; 1387 if (!m_model) return;
1390 1388
1391 FlexiNoteModel::PointList points = 1389 EventVector points =
1392 m_model->getPoints(s.getStartFrame(), s.getEndFrame()); 1390 m_model->getEventsStartingWithin(s.getStartFrame(), s.getDuration());
1393 1391
1394 FlexiNoteModel::EditCommand *command = new FlexiNoteModel::EditCommand 1392 NoteModel::EditCommand *command = new NoteModel::EditCommand
1395 (m_model, tr("Snap Notes")); 1393 (m_model, tr("Snap Notes"));
1396 1394
1397 cerr << "snapSelectedNotesToPitchTrack: selection is from " << s.getStartFrame() << " to " << s.getEndFrame() << endl; 1395 cerr << "snapSelectedNotesToPitchTrack: selection is from " << s.getStartFrame() << " to " << s.getEndFrame() << endl;
1398 1396
1399 for (FlexiNoteModel::PointList::iterator i = points.begin(); 1397 for (EventVector::iterator i = points.begin();
1400 i != points.end(); ++i) { 1398 i != points.end(); ++i) {
1401 1399
1402 FlexiNote note(*i); 1400 Event note(*i);
1403 1401
1404 cerr << "snapSelectedNotesToPitchTrack: looking at note from " << note.frame << " to " << note.frame + note.duration << endl; 1402 cerr << "snapSelectedNotesToPitchTrack: looking at note from " << note.getFrame() << " to " << note.getFrame() + note.getDuration() << endl;
1405 1403
1406 if (!s.contains(note.frame) && 1404 if (!s.contains(note.getFrame()) &&
1407 !s.contains(note.frame + note.duration - 1)) { 1405 !s.contains(note.getFrame() + note.getDuration() - 1)) {
1408 continue; 1406 continue;
1409 } 1407 }
1410 1408
1411 cerr << "snapSelectedNotesToPitchTrack: making new note" << endl; 1409 cerr << "snapSelectedNotesToPitchTrack: making new note" << endl;
1412 FlexiNote newNote(note); 1410 Event newNote(note);
1413 1411
1414 command->deletePoint(note); 1412 command->remove(note);
1415 1413
1416 if (updateNoteValueFromPitchCurve(v, newNote)) { 1414 if (updateNoteValueFromPitchCurve(v, newNote)) {
1417 command->addPoint(newNote); 1415 command->add(newNote);
1418 } 1416 }
1419 } 1417 }
1420 1418
1421 finish(command); 1419 finish(command);
1422 } 1420 }
1423 1421
1424 void 1422 void
1425 FlexiNoteLayer::mergeNotes(LayerGeometryProvider *v, Selection s, bool inclusive) 1423 FlexiNoteLayer::mergeNotes(LayerGeometryProvider *v, Selection s, bool inclusive)
1426 { 1424 {
1427 FlexiNoteModel::PointList points = 1425 EventVector points;
1428 m_model->getPoints(s.getStartFrame(), s.getEndFrame());
1429
1430 FlexiNoteModel::PointList::iterator i = points.begin();
1431 if (inclusive) { 1426 if (inclusive) {
1432 while (i != points.end() && i->frame + i->duration < s.getStartFrame()) { 1427 points = m_model->getEventsSpanning(s.getStartFrame(), s.getDuration());
1433 ++i;
1434 }
1435 } else { 1428 } else {
1436 while (i != points.end() && i->frame < s.getStartFrame()) { 1429 points = m_model->getEventsWithin(s.getStartFrame(), s.getDuration());
1437 ++i;
1438 }
1439 } 1430 }
1440 1431
1432 EventVector::iterator i = points.begin();
1441 if (i == points.end()) return; 1433 if (i == points.end()) return;
1442 1434
1443 FlexiNoteModel::EditCommand *command = 1435 NoteModel::EditCommand *command =
1444 new FlexiNoteModel::EditCommand(m_model, tr("Merge Notes")); 1436 new NoteModel::EditCommand(m_model, tr("Merge Notes"));
1445 1437
1446 FlexiNote newNote(*i); 1438 Event newNote(*i);
1447 1439
1448 while (i != points.end()) { 1440 while (i != points.end()) {
1449 1441
1450 if (inclusive) { 1442 if (inclusive) {
1451 if (i->frame >= s.getEndFrame()) break; 1443 if (i->getFrame() >= s.getEndFrame()) break;
1452 } else { 1444 } else {
1453 if (i->frame + i->duration > s.getEndFrame()) break; 1445 if (i->getFrame() + i->getDuration() > s.getEndFrame()) break;
1454 } 1446 }
1455 1447
1456 newNote.duration = i->frame + i->duration - newNote.frame; 1448 newNote = newNote.withDuration
1457 command->deletePoint(*i); 1449 (i->getFrame() + i->getDuration() - newNote.getFrame());
1450 command->remove(*i);
1458 1451
1459 ++i; 1452 ++i;
1460 } 1453 }
1461 1454
1462 updateNoteValueFromPitchCurve(v, newNote); 1455 updateNoteValueFromPitchCurve(v, newNote);
1463 command->addPoint(newNote); 1456 command->add(newNote);
1464 finish(command); 1457 finish(command);
1465 } 1458 }
1466 1459
1467 bool 1460 bool
1468 FlexiNoteLayer::updateNoteValueFromPitchCurve(LayerGeometryProvider *v, FlexiNoteModel::Point &note) const 1461 FlexiNoteLayer::updateNoteValueFromPitchCurve(LayerGeometryProvider *v, Event &note) const
1469 { 1462 {
1470 SparseTimeValueModel *model = getAssociatedPitchModel(v); 1463 SparseTimeValueModel *model = getAssociatedPitchModel(v);
1471 if (!model) return false; 1464 if (!model) return false;
1472 1465
1473 std::cerr << model->getTypeName() << std::endl; 1466 std::cerr << model->getTypeName() << std::endl;
1474 1467
1475 SparseModel<TimeValuePoint>::PointList dataPoints = 1468 SparseModel<TimeValuePoint>::PointList dataPoints =
1476 model->getPoints(note.frame, note.frame + note.duration); 1469 model->getPoints(note.getFrame(), note.getFrame() + note.getDuration());
1477 1470
1478 std::cerr << "frame " << note.frame << ": " << dataPoints.size() << " candidate points" << std::endl; 1471 std::cerr << "frame " << note.getFrame() << ": " << dataPoints.size() << " candidate points" << std::endl;
1479 1472
1480 if (dataPoints.empty()) return false; 1473 if (dataPoints.empty()) return false;
1481 1474
1482 std::vector<double> pitchValues; 1475 std::vector<double> pitchValues;
1483 1476
1484 for (SparseModel<TimeValuePoint>::PointList::const_iterator i = 1477 for (SparseModel<TimeValuePoint>::PointList::const_iterator i =
1485 dataPoints.begin(); i != dataPoints.end(); ++i) { 1478 dataPoints.begin(); i != dataPoints.end(); ++i) {
1486 if (i->frame >= note.frame && 1479 if (i->frame >= note.getFrame() &&
1487 i->frame < note.frame + note.duration) { 1480 i->frame < note.getFrame() + note.getDuration()) {
1488 pitchValues.push_back(i->value); 1481 pitchValues.push_back(i->value);
1489 } 1482 }
1490 } 1483 }
1491 1484
1492 if (pitchValues.empty()) return false; 1485 if (pitchValues.empty()) return false;
1499 median = (pitchValues[size/2 - 1] + pitchValues[size/2]) / 2; 1492 median = (pitchValues[size/2 - 1] + pitchValues[size/2]) / 2;
1500 } else { 1493 } else {
1501 median = pitchValues[size/2]; 1494 median = pitchValues[size/2];
1502 } 1495 }
1503 1496
1504 std::cerr << "updateNoteValueFromPitchCurve: corrected from " << note.value << " to median " << median << std::endl; 1497 std::cerr << "updateNoteValueFromPitchCurve: corrected from " << note.getValue() << " to median " << median << std::endl;
1505 1498
1506 note.value = float(median); 1499 note = note.withValue(float(median));
1507 1500
1508 return true; 1501 return true;
1509 } 1502 }
1510 1503
1511 void 1504 void
1512 FlexiNoteLayer::mouseMoveEvent(LayerGeometryProvider *v, QMouseEvent *e) 1505 FlexiNoteLayer::mouseMoveEvent(LayerGeometryProvider *v, QMouseEvent *e)
1513 { 1506 {
1514 // GF: context sensitive cursors 1507 // GF: context sensitive cursors
1515 // v->getView()->setCursor(Qt::ArrowCursor); 1508 // v->getView()->setCursor(Qt::ArrowCursor);
1516 FlexiNoteModel::Point note(0); 1509 Event note(0);
1517 if (!getNoteToEdit(v, e->x(), e->y(), note)) { 1510 if (!getNoteToEdit(v, e->x(), e->y(), note)) {
1518 // v->getView()->setCursor(Qt::UpArrowCursor); 1511 // v->getView()->setCursor(Qt::UpArrowCursor);
1519 return; 1512 return;
1520 } 1513 }
1521 1514
1545 v->getView()->setCursor(Qt::ArrowCursor); 1538 v->getView()->setCursor(Qt::ArrowCursor);
1546 } 1539 }
1547 } 1540 }
1548 1541
1549 void 1542 void
1550 FlexiNoteLayer::getRelativeMousePosition(LayerGeometryProvider *v, FlexiNoteModel::Point &note, int x, int y, bool &closeToLeft, bool &closeToRight, bool &closeToTop, bool &closeToBottom) const 1543 FlexiNoteLayer::getRelativeMousePosition(LayerGeometryProvider *v, Event &note, int x, int y, bool &closeToLeft, bool &closeToRight, bool &closeToTop, bool &closeToBottom) const
1551 { 1544 {
1552 // GF: TODO: consoloidate the tolerance values 1545 // GF: TODO: consoloidate the tolerance values
1553 if (!m_model) return; 1546 if (!m_model) return;
1554 1547
1555 int ctol = 0; 1548 int ctol = 0;
1556 int noteStartX = v->getXForFrame(note.frame); 1549 int noteStartX = v->getXForFrame(note.getFrame());
1557 int noteEndX = v->getXForFrame(note.frame + note.duration); 1550 int noteEndX = v->getXForFrame(note.getFrame() + note.getDuration());
1558 int noteValueY = getYForValue(v,note.value); 1551 int noteValueY = getYForValue(v,note.getValue());
1559 int noteStartY = noteValueY - (NOTE_HEIGHT / 2); 1552 int noteStartY = noteValueY - (NOTE_HEIGHT / 2);
1560 int noteEndY = noteValueY + (NOTE_HEIGHT / 2); 1553 int noteEndY = noteValueY + (NOTE_HEIGHT / 2);
1561 1554
1562 bool closeToNote = false; 1555 bool closeToNote = false;
1563 1556
1579 FlexiNoteLayer::editOpen(LayerGeometryProvider *v, QMouseEvent *e) 1572 FlexiNoteLayer::editOpen(LayerGeometryProvider *v, QMouseEvent *e)
1580 { 1573 {
1581 std::cerr << "Opening note editor dialog" << std::endl; 1574 std::cerr << "Opening note editor dialog" << std::endl;
1582 if (!m_model) return false; 1575 if (!m_model) return false;
1583 1576
1584 FlexiNoteModel::Point note(0); 1577 Event note(0);
1585 if (!getPointToDrag(v, e->x(), e->y(), note)) return false; 1578 if (!getPointToDrag(v, e->x(), e->y(), note)) return false;
1586 1579
1587 // FlexiNoteModel::Point note = *points.begin(); 1580 // Event note = *points.begin();
1588 1581
1589 ItemEditDialog *dialog = new ItemEditDialog 1582 ItemEditDialog *dialog = new ItemEditDialog
1590 (m_model->getSampleRate(), 1583 (m_model->getSampleRate(),
1591 ItemEditDialog::ShowTime | 1584 ItemEditDialog::ShowTime |
1592 ItemEditDialog::ShowDuration | 1585 ItemEditDialog::ShowDuration |
1593 ItemEditDialog::ShowValue | 1586 ItemEditDialog::ShowValue |
1594 ItemEditDialog::ShowText, 1587 ItemEditDialog::ShowText,
1595 getScaleUnits()); 1588 getScaleUnits());
1596 1589
1597 dialog->setFrameTime(note.frame); 1590 dialog->setFrameTime(note.getFrame());
1598 dialog->setValue(note.value); 1591 dialog->setValue(note.getValue());
1599 dialog->setFrameDuration(note.duration); 1592 dialog->setFrameDuration(note.getDuration());
1600 dialog->setText(note.label); 1593 dialog->setText(note.getLabel());
1601 1594
1602 if (dialog->exec() == QDialog::Accepted) { 1595 if (dialog->exec() == QDialog::Accepted) {
1603 1596
1604 FlexiNoteModel::Point newNote = note; 1597 Event newNote = note
1605 newNote.frame = dialog->getFrameTime(); 1598 .withFrame(dialog->getFrameTime())
1606 newNote.value = dialog->getValue(); 1599 .withValue(dialog->getValue())
1607 newNote.duration = dialog->getFrameDuration(); 1600 .withDuration(dialog->getFrameDuration())
1608 newNote.label = dialog->getText(); 1601 .withLabel(dialog->getText());
1609 1602
1610 FlexiNoteModel::EditCommand *command = new FlexiNoteModel::EditCommand 1603 NoteModel::EditCommand *command = new NoteModel::EditCommand
1611 (m_model, tr("Edit Point")); 1604 (m_model, tr("Edit Point"));
1612 command->deletePoint(note); 1605 command->remove(note);
1613 command->addPoint(newNote); 1606 command->add(newNote);
1614 finish(command); 1607 finish(command);
1615 } 1608 }
1616 1609
1617 delete dialog; 1610 delete dialog;
1618 return true; 1611 return true;
1621 void 1614 void
1622 FlexiNoteLayer::moveSelection(Selection s, sv_frame_t newStartFrame) 1615 FlexiNoteLayer::moveSelection(Selection s, sv_frame_t newStartFrame)
1623 { 1616 {
1624 if (!m_model) return; 1617 if (!m_model) return;
1625 1618
1626 FlexiNoteModel::EditCommand *command = 1619 NoteModel::EditCommand *command =
1627 new FlexiNoteModel::EditCommand(m_model, tr("Drag Selection")); 1620 new NoteModel::EditCommand(m_model, tr("Drag Selection"));
1628 1621
1629 FlexiNoteModel::PointList points = 1622 EventVector points =
1630 m_model->getPoints(s.getStartFrame(), s.getEndFrame()); 1623 m_model->getEventsStartingWithin(s.getStartFrame(), s.getDuration());
1631 1624
1632 for (FlexiNoteModel::PointList::iterator i = points.begin(); 1625 for (Event p: points) {
1633 i != points.end(); ++i) { 1626 command->remove(p);
1634 1627 Event moved = p.withFrame(p.getFrame() +
1635 if (s.contains(i->frame)) { 1628 newStartFrame - s.getStartFrame());
1636 FlexiNoteModel::Point newPoint(*i); 1629 command->add(moved);
1637 newPoint.frame = i->frame + newStartFrame - s.getStartFrame();
1638 command->deletePoint(*i);
1639 command->addPoint(newPoint);
1640 }
1641 } 1630 }
1642 1631
1643 finish(command); 1632 finish(command);
1644 } 1633 }
1645 1634
1646 void 1635 void
1647 FlexiNoteLayer::resizeSelection(Selection s, Selection newSize) 1636 FlexiNoteLayer::resizeSelection(Selection s, Selection newSize)
1648 { 1637 {
1638 if (!m_model || !s.getDuration()) return;
1639
1640 NoteModel::EditCommand *command =
1641 new NoteModel::EditCommand(m_model, tr("Resize Selection"));
1642
1643 EventVector points =
1644 m_model->getEventsStartingWithin(s.getStartFrame(), s.getDuration());
1645
1646 double ratio = double(newSize.getDuration()) / double(s.getDuration());
1647 double oldStart = double(s.getStartFrame());
1648 double newStart = double(newSize.getStartFrame());
1649
1650 for (Event p: points) {
1651
1652 double newFrame = (double(p.getFrame()) - oldStart) * ratio + newStart;
1653 double newDuration = double(p.getDuration()) * ratio;
1654
1655 Event newPoint = p
1656 .withFrame(lrint(newFrame))
1657 .withDuration(lrint(newDuration));
1658 command->remove(p);
1659 command->add(newPoint);
1660 }
1661
1662 finish(command);
1663 }
1664
1665 void
1666 FlexiNoteLayer::deleteSelection(Selection s)
1667 {
1649 if (!m_model) return; 1668 if (!m_model) return;
1650 1669
1651 FlexiNoteModel::EditCommand *command = 1670 NoteModel::EditCommand *command =
1652 new FlexiNoteModel::EditCommand(m_model, tr("Resize Selection")); 1671 new NoteModel::EditCommand(m_model, tr("Delete Selected Points"));
1653 1672
1654 FlexiNoteModel::PointList points = 1673 EventVector points =
1655 m_model->getPoints(s.getStartFrame(), s.getEndFrame()); 1674 m_model->getEventsStartingWithin(s.getStartFrame(), s.getDuration());
1656 1675
1657 double ratio = 1676 for (Event p: points) {
1658 double(newSize.getEndFrame() - newSize.getStartFrame()) / 1677 command->remove(p);
1659 double(s.getEndFrame() - s.getStartFrame());
1660
1661 for (FlexiNoteModel::PointList::iterator i = points.begin();
1662 i != points.end(); ++i) {
1663
1664 if (s.contains(i->frame)) {
1665
1666 double targetStart = double(i->frame);
1667 targetStart = double(newSize.getStartFrame()) +
1668 targetStart - double(s.getStartFrame()) * ratio;
1669
1670 double targetEnd = double(i->frame + i->duration);
1671 targetEnd = double(newSize.getStartFrame()) +
1672 targetEnd - double(s.getStartFrame()) * ratio;
1673
1674 FlexiNoteModel::Point newPoint(*i);
1675 newPoint.frame = lrint(targetStart);
1676 newPoint.duration = lrint(targetEnd - targetStart);
1677 command->deletePoint(*i);
1678 command->addPoint(newPoint);
1679 }
1680 }
1681
1682 finish(command);
1683 }
1684
1685 void
1686 FlexiNoteLayer::deleteSelection(Selection s)
1687 {
1688 if (!m_model) return;
1689
1690 FlexiNoteModel::EditCommand *command =
1691 new FlexiNoteModel::EditCommand(m_model, tr("Delete Selected Points"));
1692
1693 FlexiNoteModel::PointList points =
1694 m_model->getPoints(s.getStartFrame(), s.getEndFrame());
1695
1696 for (FlexiNoteModel::PointList::iterator i = points.begin();
1697 i != points.end(); ++i) {
1698
1699 if (s.contains(i->frame)) {
1700 command->deletePoint(*i);
1701 }
1702 } 1678 }
1703 1679
1704 finish(command); 1680 finish(command);
1705 } 1681 }
1706 1682
1707 void 1683 void
1708 FlexiNoteLayer::deleteSelectionInclusive(Selection s) 1684 FlexiNoteLayer::deleteSelectionInclusive(Selection s)
1709 { 1685 {
1710 if (!m_model) return; 1686 if (!m_model) return;
1711 1687
1712 FlexiNoteModel::EditCommand *command = 1688 NoteModel::EditCommand *command =
1713 new FlexiNoteModel::EditCommand(m_model, tr("Delete Selected Points")); 1689 new NoteModel::EditCommand(m_model, tr("Delete Selected Points"));
1714 1690
1715 FlexiNoteModel::PointList points = 1691 EventVector points =
1716 m_model->getPoints(s.getStartFrame(), s.getEndFrame()); 1692 m_model->getEventsSpanning(s.getStartFrame(), s.getDuration());
1717 1693
1718 for (FlexiNoteModel::PointList::iterator i = points.begin(); 1694 for (Event p: points) {
1719 i != points.end(); ++i) { 1695 command->remove(p);
1720 bool overlap = !(
1721 ((s.getStartFrame() <= i->frame) && (s.getEndFrame() <= i->frame)) || // selection is left of note
1722 ((s.getStartFrame() >= (i->frame+i->duration)) && (s.getEndFrame() >= (i->frame+i->duration))) // selection is right of note
1723 );
1724 if (overlap) {
1725 command->deletePoint(*i);
1726 }
1727 } 1696 }
1728 1697
1729 finish(command); 1698 finish(command);
1730 } 1699 }
1731 1700
1732 void 1701 void
1733 FlexiNoteLayer::copy(LayerGeometryProvider *v, Selection s, Clipboard &to) 1702 FlexiNoteLayer::copy(LayerGeometryProvider *v, Selection s, Clipboard &to)
1734 { 1703 {
1735 if (!m_model) return; 1704 if (!m_model) return;
1736 1705
1737 FlexiNoteModel::PointList points = 1706 EventVector points =
1738 m_model->getPoints(s.getStartFrame(), s.getEndFrame()); 1707 m_model->getEventsStartingWithin(s.getStartFrame(), s.getDuration());
1739 1708
1740 for (FlexiNoteModel::PointList::iterator i = points.begin(); 1709 for (Event p: points) {
1741 i != points.end(); ++i) { 1710 to.addPoint(p.withReferenceFrame(alignToReference(v, p.getFrame())));
1742 if (s.contains(i->frame)) {
1743 Event point(i->frame, i->value, i->duration, i->level, i->label);
1744 to.addPoint(point.withReferenceFrame(alignToReference(v, i->frame)));
1745 }
1746 } 1711 }
1747 } 1712 }
1748 1713
1749 bool 1714 bool
1750 FlexiNoteLayer::paste(LayerGeometryProvider *v, const Clipboard &from, sv_frame_t /*frameOffset */, bool /* interactive */) 1715 FlexiNoteLayer::paste(LayerGeometryProvider *v, const Clipboard &from, sv_frame_t /*frameOffset */, bool /* interactive */)
1770 if (button == QMessageBox::Yes) { 1735 if (button == QMessageBox::Yes) {
1771 realign = true; 1736 realign = true;
1772 } 1737 }
1773 } 1738 }
1774 1739
1775 FlexiNoteModel::EditCommand *command = 1740 NoteModel::EditCommand *command =
1776 new FlexiNoteModel::EditCommand(m_model, tr("Paste")); 1741 new NoteModel::EditCommand(m_model, tr("Paste"));
1777 1742
1778 for (EventVector::const_iterator i = points.begin(); 1743 for (EventVector::const_iterator i = points.begin();
1779 i != points.end(); ++i) { 1744 i != points.end(); ++i) {
1780 1745
1781 sv_frame_t frame = 0; 1746 sv_frame_t frame = 0;
1792 } else { 1757 } else {
1793 frame = i->getFrame(); 1758 frame = i->getFrame();
1794 } 1759 }
1795 } 1760 }
1796 1761
1797 FlexiNoteModel::Point newPoint(frame); 1762 Event p = *i;
1798 1763 Event newPoint = p;
1799 if (i->hasLabel()) newPoint.label = i->getLabel(); 1764 if (!p.hasValue()) {
1800 if (i->hasValue()) newPoint.value = i->getValue(); 1765 newPoint = newPoint.withValue((m_model->getValueMinimum() +
1801 else newPoint.value = (m_model->getValueMinimum() + 1766 m_model->getValueMaximum()) / 2);
1802 m_model->getValueMaximum()) / 2; 1767 }
1803 if (i->hasLevel()) newPoint.level = i->getLevel(); 1768 if (!p.hasDuration()) {
1804 if (i->hasDuration()) newPoint.duration = i->getDuration();
1805 else {
1806 sv_frame_t nextFrame = frame; 1769 sv_frame_t nextFrame = frame;
1807 EventVector::const_iterator j = i; 1770 EventVector::const_iterator j = i;
1808 for (; j != points.end(); ++j) { 1771 for (; j != points.end(); ++j) {
1809 if (j != i) break; 1772 if (j != i) break;
1810 } 1773 }
1811 if (j != points.end()) { 1774 if (j != points.end()) {
1812 nextFrame = j->getFrame(); 1775 nextFrame = j->getFrame();
1813 } 1776 }
1814 if (nextFrame == frame) { 1777 if (nextFrame == frame) {
1815 newPoint.duration = m_model->getResolution(); 1778 newPoint = newPoint.withDuration(m_model->getResolution());
1816 } else { 1779 } else {
1817 newPoint.duration = nextFrame - frame; 1780 newPoint = newPoint.withDuration(nextFrame - frame);
1818 } 1781 }
1819 } 1782 }
1820 1783
1821 command->addPoint(newPoint); 1784 command->add(newPoint);
1822 } 1785 }
1823 1786
1824 finish(command); 1787 finish(command);
1825 return true; 1788 return true;
1826 } 1789 }
1827 1790
1828 void 1791 void
1829 FlexiNoteLayer::addNoteOn(sv_frame_t frame, int pitch, int velocity) 1792 FlexiNoteLayer::addNoteOn(sv_frame_t frame, int pitch, int velocity)
1830 { 1793 {
1831 m_pendingNoteOns.insert(FlexiNote(frame, float(pitch), 0, float(velocity / 127.0), "")); 1794 m_pendingNoteOns.insert(Event(frame, float(pitch), 0,
1795 float(velocity / 127.0), ""));
1832 } 1796 }
1833 1797
1834 void 1798 void
1835 FlexiNoteLayer::addNoteOff(sv_frame_t frame, int pitch) 1799 FlexiNoteLayer::addNoteOff(sv_frame_t frame, int pitch)
1836 { 1800 {
1837 for (FlexiNoteSet::iterator i = m_pendingNoteOns.begin(); 1801 for (NoteSet::iterator i = m_pendingNoteOns.begin();
1838 i != m_pendingNoteOns.end(); ++i) { 1802 i != m_pendingNoteOns.end(); ++i) {
1839 if (lrint((*i).value) == pitch) { 1803
1840 FlexiNote note(*i); 1804 Event p = *i;
1805
1806 if (lrintf(p.getValue()) == pitch) {
1841 m_pendingNoteOns.erase(i); 1807 m_pendingNoteOns.erase(i);
1842 note.duration = frame - note.frame; 1808 Event note = p.withDuration(frame - p.getFrame());
1843 if (m_model) { 1809 if (m_model) {
1844 FlexiNoteModel::AddPointCommand *c = new FlexiNoteModel::AddPointCommand 1810 NoteModel::EditCommand *c = new NoteModel::EditCommand
1845 (m_model, note, tr("Record FlexiNote")); 1811 (m_model, tr("Record Note"));
1812 c->add(note);
1846 // execute and bundle: 1813 // execute and bundle:
1847 CommandHistory::getInstance()->addCommand(c, true, true); 1814 CommandHistory::getInstance()->addCommand(c, true, true);
1848 } 1815 }
1849 break; 1816 break;
1850 } 1817 }
1883 1850
1884 bool ok; 1851 bool ok;
1885 VerticalScale scale = (VerticalScale) 1852 VerticalScale scale = (VerticalScale)
1886 attributes.value("verticalScale").toInt(&ok); 1853 attributes.value("verticalScale").toInt(&ok);
1887 if (ok) setVerticalScale(scale); 1854 if (ok) setVerticalScale(scale);
1888
1889 // bool alsoOk;
1890 // double min = attributes.value("scaleMinimum").toDouble(&ok);
1891 // double max = attributes.value("scaleMaximum").toDouble(&alsoOk);
1892 // if (ok && alsoOk && min != max) setDisplayExtents(min, max);
1893 } 1855 }
1894 1856
1895 void 1857 void
1896 FlexiNoteLayer::setVerticalRangeToNoteRange(LayerGeometryProvider *v) 1858 FlexiNoteLayer::setVerticalRangeToNoteRange(LayerGeometryProvider *v)
1897 { 1859 {
1898 double minf = std::numeric_limits<double>::max(); 1860 double minf = std::numeric_limits<double>::max();
1899 double maxf = 0; 1861 double maxf = 0;
1900 bool hasNotes = 0; 1862 bool hasNotes = 0;
1901 for (FlexiNoteModel::PointList::const_iterator i = m_model->getPoints().begin(); 1863 EventVector allPoints = m_model->getAllEvents();
1902 i != m_model->getPoints().end(); ++i) { 1864 for (EventVector::const_iterator i = allPoints.begin();
1865 i != allPoints.end(); ++i) {
1903 hasNotes = 1; 1866 hasNotes = 1;
1904 FlexiNote note = *i; 1867 Event note = *i;
1905 if (note.value < minf) minf = note.value; 1868 if (note.getValue() < minf) minf = note.getValue();
1906 if (note.value > maxf) maxf = note.value; 1869 if (note.getValue() > maxf) maxf = note.getValue();
1907 } 1870 }
1908 1871
1909 std::cerr << "min frequency:" << minf << ", max frequency: " << maxf << std::endl; 1872 std::cerr << "min frequency:" << minf << ", max frequency: " << maxf << std::endl;
1910 1873
1911 if (hasNotes) { 1874 if (hasNotes) {