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