Mercurial > hg > svgui
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, ¢s); | 1173 int midiPitch = Pitch::getPitchForFrequency(m_editingPoint.getValue(), ¢s); |
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 ¬e) const | 1461 FlexiNoteLayer::updateNoteValueFromPitchCurve(LayerGeometryProvider *v, Event ¬e) 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 ¬e, int x, int y, bool &closeToLeft, bool &closeToRight, bool &closeToTop, bool &closeToBottom) const | 1543 FlexiNoteLayer::getRelativeMousePosition(LayerGeometryProvider *v, Event ¬e, 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) { |