#include "DistrhoUI.hpp" #ifdef YAW_USE_WINTAB #include "wintab.cpp" #endif #ifdef YAW_USE_RTSTYLUS #include "rtstylus.cpp" #endif START_NAMESPACE_DISTRHO class TabUI : public UI { static const uint kInitialWidth = 405; static const uint kInitialHeight = 256; public: TabUI() : UI(kInitialWidth, kInitialHeight), fSampleRate(getSampleRate()), fResizable(isResizable()), fScale(1.0f), fScaleFactor(getScaleFactor()), tab(reinterpret_cast(getWindow().getNativeWindowHandle())) { std::memset(fParameters, 0, sizeof(float) * kParameterCount); std::memset(fStrBuf, 0, sizeof(char) * (0xff + 1)); #ifdef DGL_NO_SHARED_RESOURCES createFontFromFile("sans", "/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans.ttf"); #else loadSharedResources(); #endif setGeometryConstraints(kInitialWidth, kInitialHeight, true); } protected: void getTabletData() { //Lire donnés de la tablet tab.NewPacket(); float x = static_cast(tab.pkt.pkX) / tab.extX; float y = static_cast(tab.pkt.pkY) / tab.extY; float z = static_cast(tab.pkt.pkZ) / tab.extZ; float p = static_cast(tab.pkt.pkNormalPressure) / tab.extP; if (x != fParameters[kParameterTabletX]) { setParameterValue(kParameterTabletX, x); fParameters[kParameterTabletX] = x; } if (y != fParameters[kParameterTabletY]) { setParameterValue(kParameterTabletY, y); fParameters[kParameterTabletY] = y; } if (z != fParameters[kParameterTabletZ]) { setParameterValue(kParameterTabletZ, z); fParameters[kParameterTabletZ] = z; } if (p != fParameters[kParameterTabletPressure]) { setParameterValue(kParameterTabletPressure, p); fParameters[kParameterTabletPressure] = p; } } void parameterChanged(uint32_t index, float value) override { if (index != kParameterTime) { fParameters[index] = value; return; } getTabletData(); repaint(); } void sampleRateChanged(double newSampleRate) override { fSampleRate = newSampleRate; repaint(); } void uiIdle() override { getTabletData(); repaint(); } bool onMouse(const MouseEvent& ev) override { getTabletData(); repaint(); return false; //Allow event to propagate. } void onNanoDisplay() override { drawCircle( fParameters[kParameterTabletX], fParameters[kParameterTabletY], fParameters[kParameterTabletZ], fParameters[kParameterTabletPressure] ); const float lineHeight = 20 * fScale; fontSize(15.0f * fScale); textLineHeight(lineHeight); float x = 0.0f * fScale; float y = 15.0f * fScale; if (!tab.wintabAvailable) { drawLeft(x, y, "Failed to connect to tablet."); return; } drawLeft(x, y, "x:"); drawRight(x, y, getTextBufFloat(fParameters[kParameterTabletX])); y += lineHeight; drawLeft(x, y, "y:"); drawRight(x, y, getTextBufFloat(fParameters[kParameterTabletY])); y += lineHeight; drawLeft(x, y, "z:"); drawRight(x, y, getTextBufFloat(fParameters[kParameterTabletZ])); y += lineHeight; drawLeft(x, y, "p:"); drawRight(x, y, getTextBufFloat(fParameters[kParameterTabletPressure])); y += lineHeight; } void drawCircle(float x, float y, float z, float p) { static constexpr float circleRadius = 25.f; x *= getWidth(); y = (1.f - y) * getHeight(); z = 1.f - z; beginPath(); strokeColor(1.f, 1.f, 1.f, 0.5f); moveTo(x - z * circleRadius, y); lineTo(x + z * circleRadius, y); stroke(); closePath(); beginPath(); strokeColor(1.f, 1.f, 1.f, 0.5f); moveTo(x , y - z * circleRadius); lineTo(x , y + z * circleRadius); stroke(); closePath(); beginPath(); fillColor(1.f, 1.f, 1.f, p); strokeColor(255, 255, 255, 255); circle(x, y, circleRadius); fill(); stroke(); closePath(); beginPath(); strokeColor(1.f, 1.f, 1.f, z); circle(x, y, z * circleRadius); stroke(); closePath(); } void onResize(const ResizeEvent& ev) override { fScale = static_cast(ev.size.getHeight()) / static_cast(kInitialHeight); UI::onResize(ev); } void uiScaleFactorChanged(const double scaleFactor) override { fScaleFactor = scaleFactor; } // ------------------------------------------------------------------------------------------------------- private: // Parameters float fParameters[kParameterCount]; double fSampleRate; // UI stuff bool fResizable; float fScale; // our internal scaling double fScaleFactor; // host reported scale factor // Tablet context handler Tablet tab; // temp buf for text char fStrBuf[0xff + 1]; // helpers for putting text into fStrBuf and returning it const char* getTextBufInt(const int value) { std::snprintf(fStrBuf, 0xff, "%i", value); return fStrBuf; } const char* getTextBufFloat(const float value) { std::snprintf(fStrBuf, 0xff, "%.1f", value); return fStrBuf; } const char* getTextBufFloatExtra(const float value) { std::snprintf(fStrBuf, 0xff, "%.2f", value + 0.001f); return fStrBuf; } const char* getTextBufTime(const uint64_t frame) { const uint32_t time = frame / uint64_t(fSampleRate); const uint32_t secs = time % 60; const uint32_t mins = (time / 60) % 60; const uint32_t hrs = (time / 3600) % 60; std::snprintf(fStrBuf, 0xff, "%02i:%02i:%02i", hrs, mins, secs); return fStrBuf; } // helpers for drawing text void drawLeft(float x, const float y, const char* const text, const int offset = 0) { const float width = (100.0f + offset) * fScale; x += offset * fScale; beginPath(); fillColor(200, 200, 200); textAlign(ALIGN_RIGHT | ALIGN_TOP); textBox(x, y, width, text); closePath(); } void drawRight(float x, const float y, const char* const text, const int offset = 0) { const float width = (100.0f + offset) * fScale; x += offset * fScale; beginPath(); fillColor(255, 255, 255); textAlign(ALIGN_LEFT | ALIGN_TOP); textBox(x + (105 * fScale), y, width, text); closePath(); } /** Set our UI class as non-copyable and add a leak detector just in case. */ DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(TabUI) }; UI* createUI() { return new TabUI(); } END_NAMESPACE_DISTRHO