InfoExampleUI.cpp (9326B)
1 /* 2 * DISTRHO Plugin Framework (DPF) 3 * Copyright (C) 2012-2024 Filipe Coelho <falktx@falktx.com> 4 * 5 * Permission to use, copy, modify, and/or distribute this software for any purpose with 6 * or without fee is hereby granted, provided that the above copyright notice and this 7 * permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD 10 * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN 11 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 12 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER 13 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 14 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 */ 16 17 #include "DistrhoUI.hpp" 18 19 #include "ResizeHandle.hpp" 20 21 START_NAMESPACE_DISTRHO 22 23 using DGL_NAMESPACE::ResizeHandle; 24 25 // ----------------------------------------------------------------------------------------------------------- 26 27 class InfoExampleUI : public UI 28 { 29 public: 30 InfoExampleUI() 31 : UI(DISTRHO_UI_DEFAULT_WIDTH, DISTRHO_UI_DEFAULT_HEIGHT), 32 fSampleRate(getSampleRate()), 33 fResizable(isResizable()), 34 fScale(1.0f), 35 fScaleFactor(getScaleFactor()), 36 fResizeHandle(this) 37 { 38 std::memset(fParameters, 0, sizeof(float)*kParameterCount); 39 std::memset(fStrBuf, 0, sizeof(char)*(0xff+1)); 40 41 #ifdef DGL_NO_SHARED_RESOURCES 42 createFontFromFile("sans", "/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans.ttf"); 43 #else 44 loadSharedResources(); 45 #endif 46 47 if (d_isNotEqual(fScaleFactor, 1.0)) 48 { 49 const uint width = DISTRHO_UI_DEFAULT_WIDTH * fScaleFactor; 50 const uint height = DISTRHO_UI_DEFAULT_HEIGHT * fScaleFactor; 51 setGeometryConstraints(width, height, true); 52 setSize(width, height); 53 } 54 else 55 { 56 setGeometryConstraints(DISTRHO_UI_DEFAULT_WIDTH, DISTRHO_UI_DEFAULT_HEIGHT, true); 57 } 58 59 // no need to show resize handle if window is user-resizable 60 if (fResizable) 61 fResizeHandle.hide(); 62 } 63 64 protected: 65 /* -------------------------------------------------------------------------------------------------------- 66 * DSP/Plugin Callbacks */ 67 68 /** 69 A parameter has changed on the plugin side. 70 This is called by the host to inform the UI about parameter changes. 71 */ 72 void parameterChanged(uint32_t index, float value) override 73 { 74 // some hosts send parameter change events for output parameters even when nothing changed 75 // we catch that here in order to prevent excessive repaints 76 if (d_isEqual(fParameters[index], value)) 77 return; 78 79 fParameters[index] = value; 80 repaint(); 81 } 82 83 /* -------------------------------------------------------------------------------------------------------- 84 * DSP/Plugin Callbacks (optional) */ 85 86 /** 87 Optional callback to inform the UI about a sample rate change on the plugin side. 88 */ 89 void sampleRateChanged(double newSampleRate) override 90 { 91 fSampleRate = newSampleRate; 92 repaint(); 93 } 94 95 /* -------------------------------------------------------------------------------------------------------- 96 * Widget Callbacks */ 97 98 /** 99 The NanoVG drawing function. 100 */ 101 void onNanoDisplay() override 102 { 103 const float lineHeight = 20 * fScale; 104 105 fontSize(15.0f * fScale); 106 textLineHeight(lineHeight); 107 108 float x = 0.0f * fScale; 109 float y = 15.0f * fScale; 110 111 // buffer size 112 drawLeft(x, y, "Buffer Size:"); 113 drawRight(x, y, getTextBufInt(fParameters[kParameterBufferSize])); 114 y+=lineHeight; 115 116 // sample rate 117 drawLeft(x, y, "Sample Rate:"); 118 drawRight(x, y, getTextBufFloat(fSampleRate)); 119 y+=lineHeight; 120 121 // separator 122 y+=lineHeight; 123 124 // time stuff 125 drawLeft(x, y, "Playing:"); 126 drawRight(x, y, (fParameters[kParameterTimePlaying] > 0.5f) ? "Yes" : "No"); 127 y+=lineHeight; 128 129 drawLeft(x, y, "Frame:"); 130 drawRight(x, y, getTextBufInt(fParameters[kParameterTimeFrame])); 131 y+=lineHeight; 132 133 drawLeft(x, y, "Time:"); 134 drawRight(x, y, getTextBufTime(fParameters[kParameterTimeFrame])); 135 y+=lineHeight; 136 137 // separator 138 y+=lineHeight; 139 140 // param changes 141 drawLeft(x, y, "Param Changes:", 20); 142 drawRight(x, y, (fParameters[kParameterCanRequestParameterValueChanges] > 0.5f) ? "Yes" : "No", 40); 143 y+=lineHeight; 144 145 // resizable 146 drawLeft(x, y, "Host resizable:", 20); 147 drawRight(x, y, fResizable ? "Yes" : "No", 40); 148 y+=lineHeight; 149 150 // host scale factor 151 drawLeft(x, y, "Host scale factor:", 20); 152 drawRight(x, y, getTextBufFloat(fScaleFactor), 40); 153 y+=lineHeight; 154 155 // BBT 156 x = 200.0f * fScale; 157 y = 15.0f * fScale; 158 159 const bool validBBT(fParameters[kParameterTimeValidBBT] > 0.5f); 160 drawLeft(x, y, "BBT Valid:"); 161 drawRight(x, y, validBBT ? "Yes" : "No"); 162 y+=lineHeight; 163 164 if (! validBBT) 165 return; 166 167 drawLeft(x, y, "Bar:"); 168 drawRight(x, y, getTextBufInt(fParameters[kParameterTimeBar])); 169 y+=lineHeight; 170 171 drawLeft(x, y, "Beat:"); 172 drawRight(x, y, getTextBufInt(fParameters[kParameterTimeBeat])); 173 y+=lineHeight; 174 175 drawLeft(x, y, "Tick:"); 176 drawRight(x, y, getTextBufFloatExtra(fParameters[kParameterTimeTick])); 177 y+=lineHeight; 178 179 drawLeft(x, y, "Bar Start Tick:"); 180 drawRight(x, y, getTextBufFloat(fParameters[kParameterTimeBarStartTick])); 181 y+=lineHeight; 182 183 drawLeft(x, y, "Beats Per Bar:"); 184 drawRight(x, y, getTextBufFloat(fParameters[kParameterTimeBeatsPerBar])); 185 y+=lineHeight; 186 187 drawLeft(x, y, "Beat Type:"); 188 drawRight(x, y, getTextBufFloat(fParameters[kParameterTimeBeatType])); 189 y+=lineHeight; 190 191 drawLeft(x, y, "Ticks Per Beat:"); 192 drawRight(x, y, getTextBufFloat(fParameters[kParameterTimeTicksPerBeat])); 193 y+=lineHeight; 194 195 drawLeft(x, y, "BPM:"); 196 drawRight(x, y, getTextBufFloat(fParameters[kParameterTimeBeatsPerMinute])); 197 y+=lineHeight; 198 } 199 200 void onResize(const ResizeEvent& ev) override 201 { 202 fScale = static_cast<float>(ev.size.getHeight())/static_cast<float>(DISTRHO_UI_DEFAULT_HEIGHT); 203 204 UI::onResize(ev); 205 } 206 207 void uiScaleFactorChanged(const double scaleFactor) override 208 { 209 fScaleFactor = scaleFactor; 210 } 211 212 // ------------------------------------------------------------------------------------------------------- 213 214 private: 215 // Parameters 216 float fParameters[kParameterCount]; 217 double fSampleRate; 218 219 // UI stuff 220 bool fResizable; 221 float fScale; // our internal scaling 222 double fScaleFactor; // host reported scale factor 223 ResizeHandle fResizeHandle; 224 225 // temp buf for text 226 char fStrBuf[0xff+1]; 227 228 // helpers for putting text into fStrBuf and returning it 229 const char* getTextBufInt(const int value) 230 { 231 std::snprintf(fStrBuf, 0xff, "%i", value); 232 return fStrBuf; 233 } 234 235 const char* getTextBufFloat(const float value) 236 { 237 std::snprintf(fStrBuf, 0xff, "%.1f", value); 238 return fStrBuf; 239 } 240 241 const char* getTextBufFloatExtra(const float value) 242 { 243 std::snprintf(fStrBuf, 0xff, "%.2f", value + 0.001f); 244 return fStrBuf; 245 } 246 247 const char* getTextBufTime(const uint64_t frame) 248 { 249 const uint32_t time = frame / uint64_t(fSampleRate); 250 const uint32_t secs = time % 60; 251 const uint32_t mins = (time / 60) % 60; 252 const uint32_t hrs = (time / 3600) % 60; 253 std::snprintf(fStrBuf, 0xff, "%02i:%02i:%02i", hrs, mins, secs); 254 return fStrBuf; 255 } 256 257 // helpers for drawing text 258 void drawLeft(float x, const float y, const char* const text, const int offset = 0) 259 { 260 const float width = (100.0f + offset) * fScale; 261 x += offset * fScale; 262 beginPath(); 263 fillColor(200, 200, 200); 264 textAlign(ALIGN_RIGHT|ALIGN_TOP); 265 textBox(x, y, width, text); 266 closePath(); 267 } 268 269 void drawRight(float x, const float y, const char* const text, const int offset = 0) 270 { 271 const float width = (100.0f + offset) * fScale; 272 x += offset * fScale; 273 beginPath(); 274 fillColor(255, 255, 255); 275 textAlign(ALIGN_LEFT|ALIGN_TOP); 276 textBox(x + (105 * fScale), y, width, text); 277 closePath(); 278 } 279 280 /** 281 Set our UI class as non-copyable and add a leak detector just in case. 282 */ 283 DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(InfoExampleUI) 284 }; 285 286 /* ------------------------------------------------------------------------------------------------------------ 287 * UI entry point, called by DPF to create a new UI instance. */ 288 289 UI* createUI() 290 { 291 return new InfoExampleUI(); 292 } 293 294 // ----------------------------------------------------------------------------------------------------------- 295 296 END_NAMESPACE_DISTRHO