comparison layer/FlexiNoteLayer.cpp @ 1459:42c87368287c

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