Audio plugin host https://kx.studio/carla
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.

Fl_Osc_Dial.cpp 3.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. /*
  2. ZynAddSubFX - a software synthesizer
  3. Fl_Osc_Dial.cpp - OSC Controlled Dial
  4. Copyright (C) 2016 Mark McCurry
  5. This program is free software; you can redistribute it and/or
  6. modify it under the terms of the GNU General Public License
  7. as published by the Free Software Foundation; either version 2
  8. of the License, or (at your option) any later version.
  9. */
  10. #include <FL/Fl.H>
  11. #include "Fl_Osc_Dial.H"
  12. #include "Fl_Osc_Interface.h"
  13. #include "Fl_Osc_Pane.H"
  14. #include <cstdlib>
  15. #include <cstring>
  16. #include <cmath>
  17. #include <cassert>
  18. #include <sstream>
  19. static void callback_fn_dial(Fl_Widget *w, void *)
  20. {
  21. ((Fl_Osc_Dial*)w)->cb();
  22. }
  23. Fl_Osc_Pane *fetch_osc_pane(Fl_Widget *w)
  24. {
  25. if(!w)
  26. return NULL;
  27. Fl_Osc_Pane *pane = dynamic_cast<Fl_Osc_Pane*>(w->parent());
  28. if(pane)
  29. return pane;
  30. return fetch_osc_pane(w->parent());
  31. }
  32. Fl_Osc_Dial::Fl_Osc_Dial(int X, int Y, int W, int H, const char *label)
  33. :WidgetPDial(X,Y,W,H, label), Fl_Osc_Widget(this), alt_style(false), dead(false)
  34. {
  35. bounds(0.0, 127.0f);
  36. WidgetPDial::callback(callback_fn_dial);
  37. }
  38. void Fl_Osc_Dial::init(std::string path_)
  39. {
  40. assert(osc);
  41. ext = path_;
  42. oscRegister(path_.c_str());
  43. };
  44. void Fl_Osc_Dial::alt_init(std::string base, std::string path_)
  45. {
  46. Fl_Osc_Pane *pane = fetch_osc_pane(this);
  47. assert(pane);
  48. osc = pane->osc;
  49. assert(osc);
  50. loc = base;
  51. oscRegister(path_.c_str());
  52. ext = path_;
  53. alt_style = true;
  54. }
  55. Fl_Osc_Dial::~Fl_Osc_Dial(void)
  56. {}
  57. void Fl_Osc_Dial::callback(Fl_Callback *cb, void *p)
  58. {
  59. cb_data.first = cb;
  60. cb_data.second = p;
  61. }
  62. int Fl_Osc_Dial::handle(int ev)
  63. {
  64. bool middle_mouse = (ev == FL_PUSH && Fl::event_state(FL_BUTTON2) && !Fl::event_shift());
  65. bool ctl_click = (ev == FL_PUSH && Fl::event_state(FL_BUTTON3) && Fl::event_ctrl());
  66. bool shift_middle = (ev == FL_PUSH && Fl::event_state(FL_BUTTON2) && Fl::event_shift());
  67. if(middle_mouse || ctl_click) {
  68. printf("Trying to learn...\n");
  69. osc->write("/learn", "s", (loc+ext).c_str());
  70. return 1;
  71. } else if(shift_middle) {
  72. osc->write("/unlearn", "s", (loc+ext).c_str());
  73. return 1;
  74. }
  75. return WidgetPDial::handle(ev);
  76. }
  77. void Fl_Osc_Dial::OSC_value(int v)
  78. {
  79. value(v + value() - floorf(value()) +
  80. (minimum() == 64 ? 0 : minimum()));
  81. }
  82. void Fl_Osc_Dial::OSC_value(char v)
  83. {
  84. value(v + value() - floorf(value()) +
  85. minimum());
  86. }
  87. void Fl_Osc_Dial::update(void)
  88. {
  89. osc->requestValue(loc+ext);
  90. }
  91. void Fl_Osc_Dial::cb(void)
  92. {
  93. assert(osc);
  94. if(64 != (int)minimum())
  95. oscWrite(ext, "i", (int)(value()-minimum()));
  96. else
  97. oscWrite(ext, "i", (int)(value()));
  98. if(cb_data.first)
  99. cb_data.first(this, cb_data.second);
  100. }
  101. void Fl_Osc_Dial::mark_dead(void)
  102. {
  103. dead = true;
  104. }
  105. #define VEL_PFX "VelocityScale"
  106. void Fl_Osc_Dial::rebase(std::string new_base)
  107. {
  108. if(dead || loc == "/")
  109. return;
  110. if(!alt_style) {
  111. Fl_Osc_Widget::rebase(new_base);
  112. return;
  113. }
  114. //ok, for a simple hack here lets just assume that there is one branch
  115. //missing
  116. int depth = 0;
  117. for(int i=0; i<(int)loc.size(); ++i)
  118. depth += loc[i] == '/';
  119. int match_depth = 0;
  120. int match_pos = 0;
  121. for(int i=0; i<(int)new_base.size(); ++i) {
  122. match_depth += new_base[i] == '/';
  123. if(match_depth == depth) {
  124. match_pos = i;
  125. break;
  126. }
  127. }
  128. if(match_pos == 0) {
  129. //well, that didn't work
  130. assert(!"good enough hack");
  131. }
  132. std::string new_loc = new_base.substr(0, match_pos+1);
  133. if (!strncmp(ext.c_str(), VEL_PFX, sizeof(VEL_PFX)-1) &&
  134. strstr(loc.c_str(), "/VoicePar"))
  135. new_loc = new_loc + "PFilter";
  136. // printf("Moving '%s' to\n", (loc+ext).c_str());
  137. // printf(" '%s'\n", (new_loc+ext).c_str());
  138. // printf("Ext: %s\n", ext.c_str());
  139. oscMove(loc+ext, new_loc+ext);
  140. loc = new_loc;
  141. }