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