From 39a4df017e758d01348176749a835fec082e0181 Mon Sep 17 00:00:00 2001 From: Jean Pierre Cimalando Date: Wed, 14 Oct 2020 15:29:19 +0200 Subject: [PATCH] Update the piano --- editor/CMakeLists.txt | 2 + editor/layout/main.fl | 12 +- editor/src/editor/Editor.cpp | 24 ++- editor/src/editor/GUIComponents.cpp | 195 ----------------------- editor/src/editor/GUIComponents.h | 30 ---- editor/src/editor/GUIPiano.cpp | 237 ++++++++++++++++++++++++++++ editor/src/editor/GUIPiano.h | 72 +++++++++ editor/src/editor/layout/main.hpp | 5 +- 8 files changed, 343 insertions(+), 234 deletions(-) create mode 100644 editor/src/editor/GUIPiano.cpp create mode 100644 editor/src/editor/GUIPiano.h diff --git a/editor/CMakeLists.txt b/editor/CMakeLists.txt index 952a0e98..8f676d7e 100644 --- a/editor/CMakeLists.txt +++ b/editor/CMakeLists.txt @@ -34,6 +34,8 @@ add_library(sfizz_editor STATIC EXCLUDE_FROM_ALL src/editor/EditorController.h src/editor/GUIComponents.h src/editor/GUIComponents.cpp + src/editor/GUIPiano.h + src/editor/GUIPiano.cpp src/editor/NativeHelpers.h src/editor/NativeHelpers.cpp src/editor/layout/main.hpp diff --git a/editor/layout/main.fl b/editor/layout/main.fl index 602c1d05..59d22a06 100644 --- a/editor/layout/main.fl +++ b/editor/layout/main.fl @@ -56,7 +56,7 @@ widget_class mainView {open } Fl_Box sfzFileLabel_ { label {DefaultInstrument.sfz} - comment {tag=kTagLoadSfzFile} selected + comment {tag=kTagLoadSfzFile} xywh {195 11 250 31} labelsize 20 align 20 class ClickableLabel } @@ -138,7 +138,7 @@ widget_class mainView {open } } Fl_Group {subPanels_[kPanelGeneral]} { - xywh {5 110 791 285} hide + xywh {5 110 791 285} class LogicalGroup } { Fl_Group {} {open @@ -212,8 +212,8 @@ widget_class mainView {open } } } - Fl_Group {subPanels_[kPanelSettings]} { - xywh {5 109 790 286} + Fl_Group {subPanels_[kPanelSettings]} {open + xywh {5 109 790 286} hide class LogicalGroup } { Fl_Group {} { @@ -305,8 +305,8 @@ widget_class mainView {open } } } - Fl_Box {} { - xywh {5 400 790 70} + Fl_Box piano_ {selected + xywh {5 400 790 70} labelsize 12 class Piano } } diff --git a/editor/src/editor/Editor.cpp b/editor/src/editor/Editor.cpp index cb61ad38..dc4870b2 100644 --- a/editor/src/editor/Editor.cpp +++ b/editor/src/editor/Editor.cpp @@ -8,6 +8,7 @@ #include "EditorController.h" #include "EditIds.h" #include "GUIComponents.h" +#include "GUIPiano.h" #include "NativeHelpers.h" #include #include @@ -96,6 +97,8 @@ struct Editor::Impl : EditorController::Receiver, IControlListener { SActionMenu* fileOperationsMenu_ = nullptr; + SPiano* piano_ = nullptr; + void uiReceiveValue(EditId id, const EditValue& v) override; void createFrameContents(); @@ -554,8 +557,10 @@ void Editor::Impl::createFrameContents() auto createNextFileButton = [&createGlyphButton](const CRect& bounds, int tag, const char*, CHoriTxtAlign, int fontsize) { return createGlyphButton(u8"\ue0da", bounds, tag, fontsize); }; - auto createPiano = [](const CRect& bounds, int, const char*, CHoriTxtAlign, int) { + auto createPiano = [](const CRect& bounds, int, const char*, CHoriTxtAlign, int fontsize) { SPiano* piano = new SPiano(bounds); + auto font = owned(new CFontDesc("Roboto", fontsize)); + piano->setFont(font); return piano; }; auto createChevronDropDown = [this, &theme](const CRect& bounds, int, const char*, CHoriTxtAlign, int fontsize) { @@ -693,6 +698,23 @@ void Editor::Impl::createFrameContents() menu->addEntry("Edit file", kTagEditSfzFile); } + if (SPiano* piano = piano_) { + piano->onKeyPressed = [this](unsigned key, float vel) { + uint8_t msg[3]; + msg[0] = 0x90; + msg[1] = static_cast(key); + msg[2] = static_cast(std::max(1, static_cast(vel * 127))); + ctrl_->uiSendMIDI(msg, sizeof(msg)); + }; + piano->onKeyReleased = [this](unsigned key, float vel) { + uint8_t msg[3]; + msg[0] = 0x80; + msg[1] = static_cast(key); + msg[2] = static_cast(vel * 127); + ctrl_->uiSendMIDI(msg, sizeof(msg)); + }; + } + /// CViewContainer* panel; activePanel_ = 0; diff --git a/editor/src/editor/GUIComponents.cpp b/editor/src/editor/GUIComponents.cpp index 6a0fb92b..803698dd 100644 --- a/editor/src/editor/GUIComponents.cpp +++ b/editor/src/editor/GUIComponents.cpp @@ -154,201 +154,6 @@ bool SFileDropTarget::isFileDrop(IDataPackage* package) package->getDataType(0) == IDataPackage::kFilePath; } -/// -SPiano::SPiano(const CRect& bounds) - : CView(bounds), font_(kNormalFont) -{ -} - -void SPiano::setFont(CFontRef font) -{ - font_ = font; - invalid(); -} - -void SPiano::clearKeyRanges() -{ - keyInRange_.reset(); -} - -void SPiano::addKeyRange(int start, int end) -{ - start = std::min(127, std::max(0, start)); - end = std::min(127, std::max(0, end)); - - for (int x = start; x <= end; ++x) - keyInRange_.set(x); -} - -CCoord SPiano::getKeyWidth() -{ - return 6.0; -} - -CCoord SPiano::getKeySwitchesHeight() -{ - return 20.0; -} - -CCoord SPiano::getKeyRangesHeight() -{ - return 11.0; -} - -CCoord SPiano::getKeysHeight() const -{ - return getHeight() - - (getKeySwitchesHeight() + getKeyRangesHeight() + getOctavesHeight()); -} - -CCoord SPiano::getOctavesHeight() const -{ - return font_->getSize(); -} - -void SPiano::getZoneDimensions( - CRect* pKeySwitches, - CRect* pKeyboard, - CRect* pKeyRanges, - CRect* pOctaves) -{ - CRect bounds = getViewSize(); - - CRect keySwitches(bounds); - keySwitches.setHeight(getKeySwitchesHeight()); - - CRect keyboard(bounds); - keyboard.top = keySwitches.bottom; - keyboard.setHeight(getKeysHeight()); - - CRect keyRanges(bounds); - keyRanges.top = keyboard.bottom; - keyRanges.setHeight(getKeyRangesHeight()); - - CRect octaves(bounds); - octaves.top = keyRanges.bottom; - octaves.setHeight(getOctavesHeight()); - - // apply some paddings - keySwitches.extend(-2.0, -2.0); - keyboard.extend(-2.0, -2.0); - keyRanges.extend(-2.0, -4.0); - octaves.extend(-2.0, -2.0); - - // offsets for centered keyboard - CCoord keyWidth = getKeyWidth(); - CCoord offset = std::round((keyboard.getWidth() - (128.0 * keyWidth)) * 0.5); - if (offset > 0) { - keySwitches.extend(-offset, 0.0); - keyboard.extend(-offset, 0.0); - keyRanges.extend(-offset, 0.0); - octaves.extend(-offset, 0.0); - } - - // - if (pKeySwitches) - *pKeySwitches = keySwitches; - if (pKeyboard) - *pKeyboard = keyboard; - if (pKeyRanges) - *pKeyRanges = keyRanges; - if (pOctaves) - *pOctaves = octaves; -} - -void SPiano::draw(CDrawContext* dc) -{ - CRect bounds = getViewSize(); - - dc->setDrawMode(kAntiAliasing); - - SharedPointer path; - - path = owned(dc->createGraphicsPath()); - path->addRoundRect(bounds, 5.0); - dc->setFillColor(CColor(0xca, 0xca, 0xca)); - dc->drawGraphicsPath(path, CDrawContext::kPathFilled); - - // - CRect rectKeySwitches; - CRect rectKeyboard; - CRect rectKeyRanges; - CRect rectOctaves; - getZoneDimensions(&rectKeySwitches, &rectKeyboard, &rectKeyRanges, &rectOctaves); - - // - path = owned(dc->createGraphicsPath()); - path->addRoundRect(rectKeyboard, 1.0); - dc->setFillColor(CColor(0xff, 0xff, 0xff)); - dc->drawGraphicsPath(path, CDrawContext::kPathFilled); - - CCoord keyWidth = getKeyWidth(); - for (int key = 0; key < 128; ++key) { - CCoord keyX = rectKeyboard.left + key * keyWidth; - int key12 = key % 12; - if (key12 == 1 || key12 == 3 || - key12 == 6 || key12 == 8 || key12 == 10) - { - CRect blackRect(keyX, rectKeyboard.top + 2, keyX + keyWidth, rectKeyboard.bottom - 2); - path = owned(dc->createGraphicsPath()); - path->addRoundRect(blackRect, 1.0); - dc->setFillColor(CColor(0x02, 0x02, 0x02)); - dc->drawGraphicsPath(path, CDrawContext::kPathFilled); - } - if (key != 0 && key12 == 0) { - dc->setLineWidth(1.5); - dc->setFrameColor(CColor(0x63, 0x63, 0x63)); - dc->drawLine(CPoint(keyX, rectKeyboard.top), CPoint(keyX, rectKeyboard.bottom)); - } - if (key12 == 5) { - CCoord pad = rectKeyboard.getHeight() * 0.4; - dc->setLineWidth(1.0); - dc->setFrameColor(CColor(0x63, 0x63, 0x63)); - dc->drawLine(CPoint(keyX, rectKeyboard.top + pad), CPoint(keyX, rectKeyboard.bottom - pad)); - } - } - - // - - for (int rangeStart = 0; rangeStart < 128;) - { - if (!keyInRange_[rangeStart]) { - ++rangeStart; - } - else { - int rangeEnd = rangeStart; - while (rangeEnd + 1 < 128 && keyInRange_[rangeEnd + 1]) - ++rangeEnd; - - CCoord rangeStartX = rectKeyRanges.left + rangeStart * keyWidth; - CCoord rangeEndX = rectKeyRanges.left + (rangeEnd + 1.0) * keyWidth; - CRect rectRange(rangeStartX, rectKeyRanges.top, rangeEndX, rectKeyRanges.bottom); - - path = owned(dc->createGraphicsPath()); - path->addRoundRect(rectRange, 2.0); - dc->setFillColor(CColor(0x0f, 0x0f, 0x0f)); - dc->drawGraphicsPath(path, CDrawContext::kPathFilled); - - rangeStart = rangeEnd + 1; - } - } - - // - - for (int key = 0; key < 128; ++key) { - CCoord keyX = rectOctaves.left + key * keyWidth; - int key12 = key % 12; - if (key12 == 0) { - CRect textRect(keyX, rectOctaves.top, keyX + 12 * keyWidth, rectOctaves.bottom); - dc->setFont(font_); - dc->setFontColor(CColor(0x63, 0x63, 0x63)); - dc->drawString(std::to_string(key / 12 - 1).c_str(), textRect, kLeftText); - } - } - - // -} - /// SValueMenu::SValueMenu(const CRect& bounds, IControlListener* listener, int32_t tag) : CParamDisplay(bounds), menuListener_(owned(new MenuListener(*this))) diff --git a/editor/src/editor/GUIComponents.h b/editor/src/editor/GUIComponents.h index eab40417..5a807b98 100644 --- a/editor/src/editor/GUIComponents.h +++ b/editor/src/editor/GUIComponents.h @@ -82,36 +82,6 @@ private: FileDropFunction dropFunction_; }; -/// -class SPiano : public CView { -public: - explicit SPiano(const CRect& bounds); - CFontRef getFont() const { return font_; } - void setFont(CFontRef font); - - void clearKeyRanges(); - void addKeyRange(int start, int end); - -protected: - static CCoord getKeyWidth(); - static CCoord getKeySwitchesHeight(); - static CCoord getKeyRangesHeight(); - CCoord getKeysHeight() const; - CCoord getOctavesHeight() const; - - void getZoneDimensions( - CRect* pKeySwitches, - CRect* pKeyboard, - CRect* pKeyRanges, - CRect* pOctaves); - - void draw(CDrawContext* dc) override; - -private: - SharedPointer font_; - std::bitset<128> keyInRange_; -}; - /// class SValueMenu : public CParamDisplay { public: diff --git a/editor/src/editor/GUIPiano.cpp b/editor/src/editor/GUIPiano.cpp new file mode 100644 index 00000000..6d4919bb --- /dev/null +++ b/editor/src/editor/GUIPiano.cpp @@ -0,0 +1,237 @@ +// SPDX-License-Identifier: BSD-2-Clause + +// This code is part of the sfizz library and is licensed under a BSD 2-clause +// license. You should have receive a LICENSE.md file along with the code. +// If not, contact the sfizz maintainers at https://github.com/sfztools/sfizz + +#include "GUIPiano.h" +#include "utility/vstgui_before.h" +#include "vstgui/lib/cdrawcontext.h" +#include "vstgui/lib/cgraphicspath.h" +#include "utility/vstgui_after.h" +#include + +static constexpr CCoord keyoffs[12] = {0, 0.6, 1, 1.8, 2, 3, + 3.55, 4, 4.7, 5, 5.85, 6}; +static constexpr bool black[12] = {0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0}; + +SPiano::SPiano(CRect bounds) + : CView(bounds) +{ + setNumOctaves(10); +} + +void SPiano::setFont(CFontRef font) +{ + font_ = font; + getDimensions(true); + invalid(); +} + +void SPiano::setNumOctaves(unsigned octs) +{ + keyval_.resize(octs * 12); + octs_ = std::max(1u, octs); + getDimensions(true); + invalid(); +} + +void SPiano::draw(CDrawContext* dc) +{ + const Dimensions dim = getDimensions(false); + const unsigned octs = octs_; + const unsigned keyCount = octs * 12; + + dc->setDrawMode(kAntiAliasing); + + if (backgroundFill_.alpha > 0) { + SharedPointer path; + path = owned(dc->createGraphicsPath()); + path->addRoundRect(dim.bounds, backgroundRadius_); + dc->setFillColor(CColor(0xca, 0xca, 0xca)); + dc->drawGraphicsPath(path, CDrawContext::kPathFilled); + } + + for (unsigned key = 0; key < keyCount; ++key) { + if (!black[key % 12]) { + CRect rect = keyRect(key); + CColor keycolor = whiteFill_; + if (keyval_[key]) + keycolor = pressedFill_; + dc->setFillColor(keycolor); + dc->drawRect(rect, kDrawFilled); + } + } + + dc->setFrameColor(outline_); + dc->drawLine(dim.keyBounds.getTopLeft(), dim.keyBounds.getBottomLeft()); + for (unsigned key = 0; key < keyCount; ++key) { + if (!black[key % 12]) { + CRect rect = keyRect(key); + dc->drawLine(rect.getTopRight(), rect.getBottomRight()); + } + } + + for (unsigned key = 0; key < keyCount; ++key) { + if (black[key % 12]) { + CRect rect = keyRect(key); + CColor keycolor = blackFill_; + if (keyval_[key]) + keycolor = pressedFill_; + dc->setFillColor(keycolor); + dc->drawRect(rect, kDrawFilled); + dc->setFrameColor(outline_); + dc->drawRect(rect); + } + } + + if (const CFontRef& font = font_) { + for (unsigned o = 0; o < octs; ++o) { + CRect rect = keyRect(o * 12); + CRect textRect( + rect.left, dim.labelBounds.top, + rect.right, dim.labelBounds.bottom); + dc->setFont(font_); + dc->setFontColor(labelStroke_); + std::string text = std::to_string(static_cast(o) - 1); + dc->drawString(text.c_str(), textRect, kCenterText); + } + } + + { + dc->setFrameColor(outline_); + dc->drawLine(dim.keyBounds.getTopLeft(), dim.keyBounds.getTopRight()); + dc->setFrameColor(shadeOutline_); + dc->drawLine(dim.keyBounds.getBottomLeft(), dim.keyBounds.getBottomRight()); + } + + dc->setFrameColor(outline_); +} + +CMouseEventResult SPiano::onMouseDown(CPoint& where, const CButtonState& buttons) +{ + unsigned key = keyAtPos(where); + if (key != ~0u) { + keyval_[key] = 1; + mousePressedKey_ = key; + if (onKeyPressed) + onKeyPressed(key, mousePressVelocity(key, where.y)); + invalid(); + return kMouseEventHandled; + } + return CView::onMouseDown(where, buttons); +} + +CMouseEventResult SPiano::onMouseUp(CPoint& where, const CButtonState& buttons) +{ + unsigned key = mousePressedKey_; + if (key != ~0u) { + keyval_[key] = 0; + if (onKeyReleased) + onKeyReleased(key, mousePressVelocity(key, where.y)); + mousePressedKey_ = ~0u; + invalid(); + return kMouseEventHandled; + } + return CView::onMouseUp(where, buttons); +} + +CMouseEventResult SPiano::onMouseMoved(CPoint& where, const CButtonState& buttons) +{ + if (mousePressedKey_ != ~0u) { + unsigned key = keyAtPos(where); + if (mousePressedKey_ != key) { + keyval_[mousePressedKey_] = 0; + if (onKeyReleased) + onKeyReleased(mousePressedKey_, mousePressVelocity(key, where.y)); + // mousePressedKey_ = ~0u; + if (key != ~0u) { + keyval_[key] = 1; + mousePressedKey_ = key; + if (onKeyPressed) + onKeyPressed(key, mousePressVelocity(key, where.y)); + } + invalid(); + } + return kMouseEventHandled; + } + return CView::onMouseMoved(where, buttons); +} + +const SPiano::Dimensions& SPiano::getDimensions(bool forceUpdate) const +{ + if (!forceUpdate && dim_.bounds == getViewSize()) + return dim_; + + Dimensions dim; + dim.bounds = getViewSize(); + dim.paddedBounds = CRect(dim.bounds) + .extend(-innerPaddingX_, -innerPaddingY_); + CCoord keyHeight = std::floor(dim.paddedBounds.getHeight()); + CCoord fontHeight = font_ ? font_->getSize() : 0.0; + keyHeight -= spacingY_ + fontHeight; + dim.keyBounds = CRect(dim.paddedBounds) + .setHeight(keyHeight); + dim.keyWidth = static_cast( + dim.paddedBounds.getWidth() / octs_ / 7.0); + dim.keyBounds.setWidth(dim.keyWidth * octs_ * 7.0); + dim.keyBounds.offset( + 0.5 * (dim.paddedBounds.getWidth() - dim.keyBounds.getWidth()), 0.0); + + if (!font_) + dim.labelBounds = CRect(); + else + dim.labelBounds = CRect( + dim.keyBounds.left, dim.keyBounds.bottom, + dim.keyBounds.right, dim.keyBounds.bottom + (spacingY_ + fontHeight)); + + dim_ = dim; + return dim_; +} + +CRect SPiano::keyRect(const Dimensions& dim, unsigned key) +{ + unsigned oct = key / 12; + unsigned note = key % 12; + unsigned keyw = dim.keyWidth; + unsigned keyh = static_cast(dim.keyBounds.getHeight()); + CCoord octwidth = (keyoffs[11] + 1.0) * keyw; + CCoord octx = octwidth * oct; + CCoord notex = octx + keyoffs[note] * keyw; + CCoord notew = black[note] ? (0.6 * keyw) : keyw; + CCoord noteh = black[note] ? (0.6 * keyh) : keyh; + return CRect(notex, 0.0, notex + notew, noteh).offset(dim.keyBounds.getTopLeft()); +} + +CRect SPiano::keyRect(unsigned key) const +{ + return keyRect(getDimensions(false), key); +} + +unsigned SPiano::keyAtPos(CPoint pos) const +{ + const unsigned octs = octs_; + + for (unsigned key = 0; key < octs * 12; ++key) { + if (black[key % 12]) { + if (keyRect(key).pointInside(pos)) + return key; + } + } + + for (unsigned key = 0; key < octs * 12; ++key) { + if (!black[key % 12]) { + if (keyRect(key).pointInside(pos)) + return key; + } + } + + return ~0u; +} + +float SPiano::mousePressVelocity(unsigned key, CCoord posY) +{ + const CRect rect = keyRect(key); + CCoord value = (posY - rect.top) / rect.getHeight(); + return std::max(0.0f, std::min(1.0f, static_cast(value))); +} diff --git a/editor/src/editor/GUIPiano.h b/editor/src/editor/GUIPiano.h new file mode 100644 index 00000000..6927b06f --- /dev/null +++ b/editor/src/editor/GUIPiano.h @@ -0,0 +1,72 @@ +// SPDX-License-Identifier: BSD-2-Clause + +// This code is part of the sfizz library and is licensed under a BSD 2-clause +// license. You should have receive a LICENSE.md file along with the code. +// If not, contact the sfizz maintainers at https://github.com/sfztools/sfizz + +#pragma once +#include "utility/vstgui_before.h" +#include "vstgui/lib/cview.h" +#include "vstgui/lib/ccolor.h" +#include "utility/vstgui_after.h" +#include +#include + +using namespace VSTGUI; + +class SPiano : public CView { +public: + explicit SPiano(CRect bounds); + + CFontRef getFont() const { return font_; } + void setFont(CFontRef font); + + unsigned getNumOctaves() const { return octs_; } + void setNumOctaves(unsigned octs); + + std::function onKeyPressed; + std::function onKeyReleased; + +protected: + void draw(CDrawContext* dc) override; + CMouseEventResult onMouseDown(CPoint& where, const CButtonState& buttons) override; + CMouseEventResult onMouseUp(CPoint& where, const CButtonState& buttons) override; + CMouseEventResult onMouseMoved(CPoint& where, const CButtonState& buttons) override; + +private: + struct Dimensions { + CRect bounds {}; + CRect paddedBounds {}; + CRect keyBounds {}; + unsigned keyWidth {}; + CRect labelBounds {}; + }; + const Dimensions& getDimensions(bool forceUpdate) const; + + static CRect keyRect(const Dimensions& dim, unsigned key); + CRect keyRect(unsigned key) const; + unsigned keyAtPos(CPoint pos) const; + + float mousePressVelocity(unsigned key, CCoord posY); + +private: + unsigned octs_ {}; + std::vector keyval_; + unsigned mousePressedKey_ = ~0u; + + CCoord innerPaddingX_ = 4.0; + CCoord innerPaddingY_ = 4.0; + CCoord spacingY_ = 4.0; + + CColor backgroundFill_ { 0xca, 0xca, 0xca, 0xff }; + float backgroundRadius_ = 5.0; + CColor whiteFill_ { 0xee, 0xee, 0xec, 0xff }; + CColor blackFill_ { 0x2e, 0x34, 0x36, 0xff }; + CColor pressedFill_ { 0xa0, 0xa0, 0xa0, 0xff }; + CColor outline_ { 0x00, 0x00, 0x00, 0xff }; + CColor shadeOutline_ { 0x80, 0x80, 0x80, 0xff }; + CColor labelStroke_ { 0x63, 0x63, 0x63, 0xff }; + + mutable Dimensions dim_; + SharedPointer font_; +}; diff --git a/editor/src/editor/layout/main.hpp b/editor/src/editor/layout/main.hpp index c93cf64e..0c9c61e2 100644 --- a/editor/src/editor/layout/main.hpp +++ b/editor/src/editor/layout/main.hpp @@ -69,7 +69,6 @@ enterTheme(defaultTheme); LogicalGroup* const view__28 = createLogicalGroup(CRect(5, 110, 796, 395), -1, "", kCenterText, 14); subPanels_[kPanelGeneral] = view__28; view__0->addView(view__28); -view__28->setVisible(false); RoundedGroup* const view__29 = createRoundedGroup(CRect(0, 0, 175, 280), -1, "", kCenterText, 14); view__28->addView(view__29); Label* const view__30 = createLabel(CRect(15, 10, 75, 35), -1, "Curves:", kLeftText, 14); @@ -108,6 +107,7 @@ view__41->addView(view__42); LogicalGroup* const view__43 = createLogicalGroup(CRect(5, 109, 795, 395), -1, "", kCenterText, 14); subPanels_[kPanelSettings] = view__43; view__0->addView(view__43); +view__43->setVisible(false); TitleGroup* const view__44 = createTitleGroup(CRect(255, 26, 535, 126), -1, "Engine", kCenterText, 12); view__43->addView(view__44); ValueMenu* const view__45 = createValueMenu(CRect(25, 60, 85, 85), kTagSetNumVoices, "", kCenterText, 12); @@ -150,5 +150,6 @@ view__51->addView(view__59); ValueMenu* const view__60 = createValueMenu(CRect(170, 60, 200, 85), kTagSetScalaRootKey, "", kCenterText, 12); scalaRootOctaveSlider_ = view__60; view__51->addView(view__60); -Piano* const view__61 = createPiano(CRect(5, 400, 795, 470), -1, "", kCenterText, 14); +Piano* const view__61 = createPiano(CRect(5, 400, 795, 470), -1, "", kCenterText, 12); +piano_ = view__61; view__0->addView(view__61);