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.

245 lines
7.5KB

  1. #include <FL/Fl.H>
  2. #include "Fl_Osc_Slider.H"
  3. #include "Fl_Osc_Interface.h"
  4. #include "Fl_Osc_Pane.H"
  5. #include <cstdlib>
  6. #include <cstring>
  7. #include <cmath>
  8. #include <cassert>
  9. #include <sstream>
  10. #include "../Misc/Util.h"
  11. static double min__(double a, double b)
  12. {
  13. return a<b?a:b;
  14. }
  15. Fl_Osc_Slider::Fl_Osc_Slider(int X, int Y, int W, int H, const char *label)
  16. :Fl_Slider(X,Y,W,H,label), Fl_Osc_Widget(this), reset_value(0),
  17. cb_data(NULL, NULL), just_pushed(true)
  18. {
  19. //bounds(0.0f,1.0f);
  20. Fl_Slider::callback(Fl_Osc_Slider::_cb);
  21. }
  22. void Fl_Osc_Slider::init(std::string path_, char type_)
  23. {
  24. osc_type = type_;
  25. ext = path_;
  26. oscRegister(ext.c_str());
  27. }
  28. Fl_Osc_Slider::~Fl_Osc_Slider(void)
  29. {}
  30. void Fl_Osc_Slider::OSC_value(int v)
  31. {
  32. const float min_ = min__(minimum(), maximum());//flipped sliders
  33. Fl_Slider::value(v+min_+value()-floorf(value()));
  34. }
  35. void Fl_Osc_Slider::OSC_value(float v)
  36. {
  37. const float min_ = min__(minimum(), maximum());//flipped sliders
  38. Fl_Slider::value(v+min_);
  39. }
  40. void Fl_Osc_Slider::OSC_value(char v)
  41. {
  42. const float min_ = min__(minimum(), maximum());//flipped sliders
  43. Fl_Slider::value(v+min_+value()-floorf(value()));
  44. }
  45. void Fl_Osc_Slider::cb(void)
  46. {
  47. const float min_ = min__(minimum(), maximum());//flipped sliders
  48. const float val = Fl_Slider::value();
  49. if(osc_type == 'f')
  50. oscWrite(ext, "f", val-min_);
  51. else if(osc_type == 'i')
  52. oscWrite(ext, "i", (int)(val-min_));
  53. else {
  54. fprintf(stderr, "invalid `c' from slider %s%s, using `i'\n", loc.c_str(), ext.c_str());
  55. oscWrite(ext, "i", (int)(val-min_));
  56. }
  57. //OSC_value(val);
  58. if(cb_data.first)
  59. cb_data.first(this, cb_data.second);
  60. }
  61. void Fl_Osc_Slider::callback(Fl_Callback *cb, void *p)
  62. {
  63. cb_data.first = cb;
  64. cb_data.second = p;
  65. }
  66. #define MOD_MASK (FL_CTRL | FL_SHIFT)
  67. int Fl_Osc_Slider::handle(int ev, int X, int Y, int W, int H)
  68. {
  69. bool middle_mouse = (ev == FL_PUSH && Fl::event_state(FL_BUTTON2) && !Fl::event_shift());
  70. bool ctl_click = (ev == FL_PUSH && Fl::event_state(FL_BUTTON3) && Fl::event_ctrl());
  71. bool shift_middle = (ev == FL_PUSH && Fl::event_state(FL_BUTTON2) && Fl::event_shift());
  72. if(middle_mouse || ctl_click) {
  73. printf("Trying to learn...\n");
  74. osc->write("/learn", "s", (loc+ext).c_str());
  75. return 1;
  76. } else if(shift_middle) {
  77. osc->write("/unlearn", "s", (loc+ext).c_str());
  78. return 1;
  79. }
  80. int handled;
  81. float rounded;
  82. const float range = maximum() - minimum();
  83. const float absrange = (range > 0 ? range : -range)+1;
  84. int old_mod_state;
  85. const float normal_step = range / W;
  86. switch (ev) {
  87. case FL_PUSH:
  88. just_pushed = true;
  89. mod_state = Fl::event_state() & MOD_MASK;
  90. slow_state = 0;
  91. start_pos = horizontal() ? Fl::event_x() : Fl::event_y();
  92. handled = mod_state ? 1 : Fl_Slider::handle(ev, X, Y, W, H);
  93. break;
  94. case FL_MOUSEWHEEL:
  95. mod_state = Fl::event_state() & MOD_MASK;
  96. if (Fl::event_buttons())
  97. return 1;
  98. if (this == Fl::belowmouse() && Fl::e_dy != 0) {
  99. int step_ = 1, divisor = 16;
  100. switch (mod_state) {
  101. case FL_SHIFT:
  102. if (absrange > divisor * 8)
  103. step_ = 8;
  104. case FL_SHIFT | FL_CTRL:
  105. break;
  106. case FL_CTRL:
  107. divisor = 128;
  108. default:
  109. step_ = absrange / divisor;
  110. if (step_ < 1)
  111. step_ = 1;
  112. }
  113. int dy = minimum() <= maximum() ? -Fl::e_dy : Fl::e_dy;
  114. // Flip sense for vertical sliders.
  115. dy = this->horizontal() ? dy : -dy;
  116. handle_drag(clamp(value() + step_ * dy));
  117. }
  118. return 1;
  119. case FL_RELEASE:
  120. handled = Fl_Slider::handle(ev, X, Y, W, H);
  121. if (Fl::event_clicks() == 1) {
  122. Fl::event_clicks(0);
  123. value(reset_value);
  124. } else {
  125. rounded = floorf(value() + 0.5);
  126. value(clamp(rounded));
  127. }
  128. value_damage();
  129. do_callback();
  130. break;
  131. case FL_DRAG: {
  132. old_mod_state = mod_state;
  133. mod_state = Fl::event_state() & MOD_MASK;
  134. if (slow_state == 0 && mod_state == 0) {
  135. int delta = (horizontal() ? Fl::event_x() : Fl::event_y())
  136. - start_pos;
  137. if (delta < -1 || delta > 1)
  138. Fl::event_clicks(0);
  139. return Fl_Slider::handle(ev, X, Y, W, H);
  140. }
  141. if (mod_state != 0) {
  142. slow_state = 1;
  143. } else if (slow_state == 1)
  144. slow_state = 2;
  145. if (just_pushed || old_mod_state != mod_state) {
  146. just_pushed = false;
  147. old_value = value();
  148. start_pos = horizontal() ? Fl::event_x() : Fl::event_y();
  149. if (slow_state == 1) {
  150. denominator = 2.0;
  151. float step_ = step();
  152. if (step_ == 0) step_ = 1;
  153. if (absrange / W / step_ > 32)
  154. switch (mod_state) {
  155. case FL_CTRL:
  156. denominator = 0.15;
  157. break;
  158. case FL_SHIFT:
  159. denominator = 0.7;
  160. break;
  161. case MOD_MASK:
  162. denominator = 3.0;
  163. break;
  164. }
  165. else if (mod_state & FL_SHIFT)
  166. denominator = 5.0;
  167. if (range < 0)
  168. denominator *= -1;
  169. }
  170. }
  171. int delta = (horizontal() ? Fl::event_x() : Fl::event_y())
  172. - start_pos;
  173. if (delta < -1 || delta > 1)
  174. Fl::event_clicks(0);
  175. float new_value;
  176. if (slow_state == 1) {
  177. new_value = old_value + delta / denominator;
  178. } else {
  179. new_value = old_value + delta * normal_step;
  180. }
  181. const float clamped_value = clamp(new_value);
  182. rounded = floor(clamped_value + 0.5);
  183. if (new_value != clamped_value) {
  184. start_pos = horizontal() ? Fl::event_x() : Fl::event_y();
  185. old_value = rounded;
  186. if (slow_state == 2 &&
  187. ((horizontal() &&
  188. (Fl::event_x() < X || Fl::event_x() > X + W)) ||
  189. (!horizontal() &&
  190. (Fl::event_y() < Y || Fl::event_y() > Y + H))))
  191. slow_state = 0;
  192. }
  193. value(rounded);
  194. value_damage();
  195. do_callback();
  196. handled = 1;
  197. break;
  198. }
  199. default:
  200. handled = Fl_Slider::handle(ev, X, Y, W, H);
  201. }
  202. return handled;
  203. }
  204. int Fl_Osc_Slider::handle(int ev) {
  205. return handle(ev,
  206. x()+Fl::box_dx(box()),
  207. y()+Fl::box_dy(box()),
  208. w()-Fl::box_dw(box()),
  209. h()-Fl::box_dh(box()));
  210. }
  211. void Fl_Osc_Slider::update(void)
  212. {
  213. oscWrite(ext, "");
  214. }
  215. void Fl_Osc_Slider::_cb(Fl_Widget *w, void *)
  216. {
  217. static_cast<Fl_Osc_Slider*>(w)->cb();
  218. }