You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

464 lines
9.4KB

  1. #pragma once
  2. //#define DEBUG
  3. #include "rack.hpp"
  4. #include "dsp/digital.hpp"
  5. #include <algorithm>
  6. #include <sstream>
  7. #include <iomanip>
  8. namespace rack_plugin_TheXOR {
  9. #define LVL_ON (10.0)
  10. #define LVL_OFF (0.0)
  11. using namespace rack;
  12. #define plugin "TheXOR"
  13. #if defined(ARCH_WIN) && defined(USE_LAUNCHPAD)
  14. #define LAUNCHPAD
  15. #endif
  16. #ifdef LAUNCHPAD
  17. #include "../digitalExt/launchpad.hpp"
  18. #include "../digitalExt/launchpadControls.hpp"
  19. #ifdef DEBUG
  20. #define LPTEST_MODULE
  21. #endif
  22. #endif
  23. #if defined(ARCH_WIN) && defined(USE_OSC)
  24. #define OSC_ENABLE
  25. #ifdef DEBUG
  26. #define OSCTEST_MODULE
  27. #endif
  28. #include "../digitalExt/osc/oscDriver.hpp"
  29. #endif
  30. #if defined(LAUNCHPAD) || defined(OSCTEST_MODULE)
  31. #define DIGITAL_EXT
  32. #endif
  33. struct _davies1900base : Davies1900hKnob
  34. {
  35. _davies1900base(const char *res)
  36. {
  37. setSVG(SVG::load(assetPlugin(plugin, res)));
  38. }
  39. void randomize() override
  40. {
  41. if(snap)
  42. setValue(roundf(rescale(randomUniform(), 0.0, 1.0, minValue, maxValue)));
  43. else
  44. Davies1900hKnob::randomize();
  45. }
  46. };
  47. struct Davies1900hFixWhiteKnob : _davies1900base
  48. {
  49. Davies1900hFixWhiteKnob() : _davies1900base("res/Davies1900hWhite.svg") {}
  50. };
  51. struct Davies1900hFixBlackKnob : _davies1900base
  52. {
  53. Davies1900hFixBlackKnob() : _davies1900base("res/Davies1900hBlack.svg") {}
  54. };
  55. struct Davies1900hFixRedKnob : _davies1900base
  56. {
  57. Davies1900hFixRedKnob() : _davies1900base("res/Davies1900hRed.svg") {}
  58. };
  59. struct Davies1900hFixWhiteKnobSmall : _davies1900base
  60. {
  61. Davies1900hFixWhiteKnobSmall() : _davies1900base("res/Davies1900hWhiteSmall.svg") {}
  62. };
  63. struct WhiteLight : GrayModuleLightWidget
  64. {
  65. WhiteLight()
  66. {
  67. addBaseColor(COLOR_WHITE);
  68. }
  69. };
  70. struct _ioPort : SVGPort
  71. {
  72. _ioPort(const char *res)
  73. {
  74. background->svg = SVG::load(assetPlugin(plugin, res));
  75. background->wrap();
  76. box.size = background->box.size;
  77. }
  78. };
  79. struct PJ301YPort : _ioPort
  80. {
  81. PJ301YPort() : _ioPort("res/PJ301Y.svg") {}
  82. };
  83. struct PJ301BPort : _ioPort
  84. {
  85. PJ301BPort() : _ioPort("res/PJ301B.svg") {}
  86. };
  87. struct PJ301GPort : _ioPort
  88. {
  89. PJ301GPort() : _ioPort("res/PJ301G.svg") {}
  90. };
  91. struct PJ301GRPort : _ioPort
  92. {
  93. PJ301GRPort() : _ioPort("res/PJ301GR.svg") {}
  94. };
  95. struct PJ301RPort : _ioPort
  96. {
  97. PJ301RPort() : _ioPort("res/PJ301R.svg") {}
  98. };
  99. struct PJ301WPort : _ioPort
  100. {
  101. PJ301WPort() : _ioPort("res/PJ301W.svg") {}
  102. };
  103. struct PJ301OPort : _ioPort
  104. {
  105. PJ301OPort() : _ioPort("res/PJ301O.svg") {}
  106. };
  107. struct PJ301BLUPort : _ioPort
  108. {
  109. PJ301BLUPort() : _ioPort("res/PJ301BLU.svg") {}
  110. };
  111. struct CL1362YPort : _ioPort
  112. {
  113. CL1362YPort() : _ioPort("res/CL1362Y.svg") {}
  114. };
  115. struct CL1362GPort : _ioPort
  116. {
  117. CL1362GPort() : _ioPort("res/CL1362G.svg") {}
  118. };
  119. struct CL1362RPort : _ioPort
  120. {
  121. CL1362RPort() : _ioPort("res/CL1362R.svg") {}
  122. };
  123. struct CL1362WPort : _ioPort
  124. {
  125. CL1362WPort() : _ioPort("res/CL1362W.svg") {}
  126. };
  127. struct BefacoPushBig : SVGSwitch, MomentarySwitch {
  128. BefacoPushBig() {
  129. addFrame(SVG::load(assetPlugin(plugin, "res/BefacoPush_0big.svg")));
  130. addFrame(SVG::load(assetPlugin(plugin, "res/BefacoPush_1big.svg")));
  131. }
  132. };
  133. struct CKSSFix : SVGSwitch, ToggleSwitch {
  134. CKSSFix() {
  135. addFrame(SVG::load(assetPlugin(plugin, "res/CKSS_0.svg")));
  136. addFrame(SVG::load(assetPlugin(plugin, "res/CKSS_1.svg")));
  137. }
  138. void randomize() override
  139. {
  140. setValue(roundf(rescale(randomUniform(), 0.0, 1.0, minValue, maxValue)));
  141. }
  142. };
  143. struct CKSSThreeFix : SVGSwitch, ToggleSwitch {
  144. CKSSThreeFix() {
  145. addFrame(SVG::load(assetPlugin(plugin, "res/CKSSThree_0.svg")));
  146. addFrame(SVG::load(assetPlugin(plugin, "res/CKSSThree_1.svg")));
  147. addFrame(SVG::load(assetPlugin(plugin, "res/CKSSThree_2.svg")));
  148. }
  149. void randomize() override
  150. {
  151. setValue(roundf(rescale(randomUniform(), 0.0, 1.0, minValue, maxValue)));
  152. }
  153. };
  154. struct TL1105Sw : SVGSwitch, ToggleSwitch {
  155. TL1105Sw() {
  156. addFrame(SVG::load(assetPlugin(plugin, "res/TL1105_0.svg")));
  157. addFrame(SVG::load(assetPlugin(plugin, "res/TL1105_1.svg")));
  158. }
  159. };
  160. struct SchmittTrigger2
  161. {
  162. // UNKNOWN is used to represent a stable state when the previous state is not yet set
  163. enum { UNKNOWN, LOW, HIGH } state = UNKNOWN;
  164. float low = 0.0;
  165. float high = 1.0;
  166. void setThresholds(float low, float high)
  167. {
  168. this->low = low;
  169. this->high = high;
  170. }
  171. int process(float in)
  172. {
  173. switch(state)
  174. {
  175. case LOW:
  176. if(in >= high)
  177. {
  178. state = HIGH;
  179. return 1;
  180. }
  181. break;
  182. case HIGH:
  183. if(in <= low)
  184. {
  185. state = LOW;
  186. return -1;
  187. }
  188. break;
  189. default:
  190. if(in >= high)
  191. {
  192. state = HIGH;
  193. } else if(in <= low)
  194. {
  195. state = LOW;
  196. }
  197. break;
  198. }
  199. return 0;
  200. }
  201. void reset()
  202. {
  203. state = UNKNOWN;
  204. }
  205. };
  206. struct NKK2 : SVGSwitch, ToggleSwitch
  207. {
  208. NKK2() {
  209. addFrame(SVG::load(assetPlugin(plugin, "res/NKK_0.svg")));
  210. addFrame(SVG::load(assetPlugin(plugin, "res/NKK_1.svg")));
  211. addFrame(SVG::load(assetPlugin(plugin, "res/NKK_2.svg")));
  212. }
  213. void randomize() override
  214. {
  215. setValue(roundf(rescale(randomUniform(), 0.0, 1.0, minValue, maxValue)));
  216. }
  217. };
  218. struct BefacoSnappedSwitch : SVGSwitch, ToggleSwitch
  219. {
  220. void randomize() override
  221. {
  222. if(randomUniform() >= 0.5)
  223. setValue(1.0);
  224. else
  225. setValue(0.0);
  226. }
  227. BefacoSnappedSwitch()
  228. {
  229. addFrame(SVG::load(assetPlugin(plugin, "res/BefacoSwitch_0.svg")));
  230. addFrame(SVG::load(assetPlugin(plugin, "res/BefacoSwitch_2.svg")));
  231. }
  232. };
  233. struct VerticalSwitch : SVGFader
  234. {
  235. VerticalSwitch()
  236. {
  237. snap = true;
  238. maxHandlePos = Vec(-mm2px(2.3-2.3/2.0), 0);
  239. minHandlePos = Vec(-mm2px(2.3-2.3/2.0),mm2px(13-2.8));
  240. background->svg = SVG::load(assetPlugin(plugin, "res/counterSwitchShort.svg"));
  241. background->wrap();
  242. background->box.pos = Vec(0, 0);
  243. box.size = background->box.size;
  244. handle->svg = SVG::load(assetPlugin(plugin, "res/counterSwitchPotHandle.svg"));
  245. handle->wrap();
  246. }
  247. void randomize() override { setValue(roundf(randomUniform() * maxValue)); }
  248. };
  249. template<class T> struct SeqMenuItem : MenuItem
  250. {
  251. public:
  252. SeqMenuItem(const char *title, T *pW, int act)
  253. {
  254. text = title;
  255. widget = pW;
  256. action = act;
  257. };
  258. void onAction(EventAction &e) override { widget->onMenu(action); };
  259. private:
  260. T *widget;
  261. int action;
  262. };
  263. class SequencerWidget : public ModuleWidget
  264. {
  265. protected:
  266. SequencerWidget(Module *module) : ModuleWidget(module) {}
  267. float yncscape(float y, float height)
  268. {
  269. return RACK_GRID_HEIGHT - mm2px(y + height);
  270. }
  271. int getParamIndex(int index)
  272. {
  273. auto it = std::find_if(params.begin(), params.end(), [&index](const ParamWidget *m) -> bool { return m->paramId == index; });
  274. if(it != params.end())
  275. return std::distance(params.begin(), it);
  276. return -1;
  277. }
  278. void std_randomize(int first_index, int last_index)
  279. {
  280. for(int k = first_index; k < last_index; k++)
  281. {
  282. int index = getParamIndex(k);
  283. if(index >= 0)
  284. {
  285. params[index]->randomize();
  286. }
  287. }
  288. }
  289. Menu *createContextMenu() override
  290. {
  291. Menu *menu = ModuleWidget::createContextMenu();
  292. MenuLabel *spacerLabel = new MenuLabel();
  293. menu->addChild(spacerLabel);
  294. return addContextMenu(menu);
  295. }
  296. virtual Menu *addContextMenu(Menu *menu) { return menu; }
  297. };
  298. #if defined(LAUNCHPAD) || defined(OSC_ENABLE)
  299. struct DigitalLed : SVGWidget
  300. {
  301. float *value;
  302. std::vector<std::shared_ptr<SVG>> frames;
  303. DigitalLed(int x, int y, float *pVal)
  304. {
  305. frames.push_back(SVG::load(assetPlugin(plugin, "res/digitalLed_off.svg")));
  306. frames.push_back(SVG::load(assetPlugin(plugin, "res/digitalLed_on.svg")));
  307. setSVG(frames[0]);
  308. wrap();
  309. box.pos = Vec(x, y);
  310. value = pVal;
  311. }
  312. void draw(NVGcontext *vg) override
  313. {
  314. int index = (*value > 0) ? 1 : 0;
  315. setSVG(frames[index]);
  316. SVGWidget::draw(vg);
  317. }
  318. };
  319. #endif
  320. struct SigDisplayWidget : TransparentWidget
  321. {
  322. private:
  323. int digits;
  324. int precision;
  325. std::shared_ptr<Font> font;
  326. public:
  327. float *value;
  328. SigDisplayWidget(int digit, int precis = 0)
  329. {
  330. digits = digit;
  331. precision = precis;
  332. font = Font::load(assetPlugin(plugin, "res/Segment7Standard.ttf"));
  333. };
  334. void draw(NVGcontext *vg) override
  335. {
  336. // Background
  337. NVGcolor backgroundColor = nvgRGB(0x20, 0x20, 0x20);
  338. NVGcolor borderColor = nvgRGB(0x10, 0x10, 0x10);
  339. nvgBeginPath(vg);
  340. nvgRoundedRect(vg, 0.0, 0.0, box.size.x, box.size.y, 4.0);
  341. nvgFillColor(vg, backgroundColor);
  342. nvgFill(vg);
  343. nvgStrokeWidth(vg, 1.0);
  344. nvgStrokeColor(vg, borderColor);
  345. nvgStroke(vg);
  346. // text
  347. nvgFontSize(vg, 18);
  348. nvgFontFaceId(vg, font->handle);
  349. nvgTextLetterSpacing(vg, 2.5);
  350. std::stringstream to_display;
  351. if(precision == 0)
  352. to_display << std::setw(digits) << std::round(*value);
  353. else
  354. to_display << std::fixed << std::setw(digits) << std::setprecision(precision) << *value;
  355. Vec textPos = Vec(3, 17);
  356. NVGcolor textColor = nvgRGB(0xdf, 0xd2, 0x2c);
  357. nvgFillColor(vg, nvgTransRGBA(textColor, 16));
  358. nvgText(vg, textPos.x, textPos.y, "~~", NULL);
  359. textColor = nvgRGB(0xda, 0xe9, 0x29);
  360. nvgFillColor(vg, nvgTransRGBA(textColor, 16));
  361. nvgText(vg, textPos.x, textPos.y, "\\\\", NULL);
  362. textColor = nvgRGB(0xf0, 0x00, 0x00);
  363. nvgFillColor(vg, textColor);
  364. nvgText(vg, textPos.x, textPos.y, to_display.str().c_str(), NULL);
  365. }
  366. };
  367. struct TIMER
  368. {
  369. float Reset()
  370. {
  371. prevTime = clock();
  372. return Begin();
  373. }
  374. void RestartStopWatch() { stopwatch = 0; }
  375. float Begin()
  376. {
  377. RestartStopWatch();
  378. return totalPulseTime = 0;
  379. }
  380. float Elapsed() { return totalPulseTime; }
  381. float StopWatch() { return stopwatch; }
  382. float Step()
  383. {
  384. clock_t curTime = clock();
  385. clock_t deltaTime = curTime - prevTime;
  386. prevTime = curTime;
  387. float t = float(deltaTime) / CLOCKS_PER_SEC;
  388. totalPulseTime += t;
  389. stopwatch += t;
  390. return t;
  391. }
  392. private:
  393. clock_t prevTime;
  394. float totalPulseTime;
  395. float stopwatch;
  396. };
  397. } // namespace rack_plugin_TheXOR