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.

256 lines
7.8KB

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