DPF Plugin examples
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.

357 lines
9.6KB

  1. /*
  2. * Author: Harry van Haaren 2013
  3. * harryhaaren@gmail.com
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 2 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program; if not, write to the Free Software
  17. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
  18. * MA 02110-1301, USA.
  19. *
  20. */
  21. #ifndef AVTK_FILTERGRAPH_H
  22. #define AVTK_FILTERGRAPH_H
  23. #include <FL/Fl_Widget.H>
  24. #include <FL/Fl_Slider.H>
  25. #include <valarray>
  26. #include <string>
  27. namespace Avtk
  28. {
  29. class Filtergraph : public Fl_Slider
  30. {
  31. public:
  32. enum Type {
  33. FILTER_LOWPASS = 0,
  34. FILTER_HIGHPASS,
  35. FILTER_FLAT,
  36. };
  37. Filtergraph(int _x, int _y, int _w, int _h, const char *_label = 0, Type _type = FILTER_LOWPASS):
  38. Fl_Slider(_x, _y, _w, _h, _label)
  39. {
  40. graphType = _type;
  41. x = _x;
  42. y = _y;
  43. w = _w;
  44. h = _h;
  45. label = _label;
  46. mouseClickedX = 0;
  47. mouseClickedY = 0;
  48. mouseClicked = false;
  49. active = true;
  50. highlight = false;
  51. value( 0.5 );
  52. freq = value();
  53. gain = 0;
  54. bandwidth = 0;
  55. }
  56. void setGain(float g) {gain = g; redraw();}
  57. void setBandwidth(float b) {bandwidth = b; redraw();}
  58. float getGain() {return gain;}
  59. float getBandwidth() {return bandwidth;}
  60. void setType(Type t)
  61. {
  62. graphType = t;
  63. redraw();
  64. }
  65. void setActive(bool a)
  66. {
  67. active = a;
  68. redraw();
  69. }
  70. bool getActive()
  71. {
  72. return active;
  73. }
  74. Type graphType;
  75. bool active;
  76. bool highlight;
  77. int x, y, w, h;
  78. const char* label;
  79. int mouseClickedX;
  80. int mouseClickedY;
  81. bool mouseClicked;
  82. float freq;
  83. float gain;
  84. float bandwidth;
  85. void draw()
  86. {
  87. if (damage() & FL_DAMAGE_ALL)
  88. {
  89. cairo_t *cr = Fl::cairo_cc();
  90. cairo_save( cr );
  91. cairo_set_line_width(cr, 1.5);
  92. // fill background
  93. cairo_rectangle( cr, x, y, w, h);
  94. cairo_set_source_rgb( cr, 28 / 255.f, 28 / 255.f , 28 / 255.f );
  95. cairo_fill( cr );
  96. // set up dashed lines, 1 px off, 1 px on
  97. double dashes[1];
  98. dashes[0] = 2.0;
  99. cairo_set_dash ( cr, dashes, 1, 0.0);
  100. cairo_set_line_width( cr, 1.0);
  101. // loop over each 2nd line, drawing dots
  102. cairo_set_line_width(cr, 1.0);
  103. cairo_set_source_rgb(cr, 0.4,0.4,0.4);
  104. for ( int i = 0; i < 4; i++ )
  105. {
  106. cairo_move_to( cr, x + ((w / 4.f)*i), y );
  107. cairo_line_to( cr, x + ((w / 4.f)*i), y + h );
  108. }
  109. for ( int i = 0; i < 4; i++ )
  110. {
  111. cairo_move_to( cr, x , y + ((h / 4.f)*i) );
  112. cairo_line_to( cr, x + w, y + ((h / 4.f)*i) );
  113. }
  114. cairo_set_source_rgba( cr, 66 / 255.f, 66 / 255.f , 66 / 255.f , 0.5 );
  115. cairo_stroke(cr);
  116. cairo_set_dash ( cr, dashes, 0, 0.0);
  117. // change filter type (low|high) based on value:
  118. // 0 to < 0.5 = lowpass
  119. // 0.5 == no change
  120. // 0.5 < 1.0 == highpass
  121. if ( value() < 0.45 )
  122. {
  123. graphType = FILTER_LOWPASS;
  124. freq = value()*2.f;
  125. }
  126. else if ( value() > 0.55 )
  127. {
  128. graphType = FILTER_HIGHPASS;
  129. freq = (value()-0.5)*2.f;
  130. }
  131. else
  132. {
  133. graphType = FILTER_FLAT;
  134. }
  135. switch( graphType )
  136. {
  137. case FILTER_LOWPASS : drawLowpass(cr); break;
  138. case FILTER_HIGHPASS: drawHighpass(cr); break;
  139. case FILTER_FLAT : drawFlat(cr); break;
  140. default:
  141. cout << "Filtergraph: unknown filter type selected!" << endl;
  142. }
  143. // stroke outline
  144. cairo_rectangle(cr, x, y, w, h);
  145. cairo_set_source_rgba( cr, 126 / 255.f, 126 / 255.f , 126 / 255.f , 0.8 );
  146. cairo_set_line_width(cr, 1.9);
  147. cairo_stroke( cr );
  148. if ( !active )
  149. {
  150. // big grey X
  151. cairo_set_line_width(cr, 20.0);
  152. cairo_set_source_rgba(cr, 0.4,0.4,0.4, 0.7);
  153. cairo_move_to( cr, x + (3 * w / 4.f), y + ( h / 4.f ) );
  154. cairo_line_to( cr, x + (w / 4.f), y + ( 3 *h / 4.f ) );
  155. cairo_move_to( cr, x + (w / 4.f), y + ( h / 4.f ) );
  156. cairo_line_to( cr, x + (3 * w / 4.f), y + ( 3 *h / 4.f ) );
  157. cairo_set_line_cap ( cr, CAIRO_LINE_CAP_BUTT);
  158. cairo_stroke( cr );
  159. }
  160. cairo_restore( cr );
  161. }
  162. }
  163. void resize(int X, int Y, int W, int H)
  164. {
  165. Fl_Widget::resize(X,Y,W,H);
  166. x = X;
  167. y = Y;
  168. w = W;
  169. h = H;
  170. redraw();
  171. }
  172. int handle(int event)
  173. {
  174. switch(event)
  175. {
  176. case FL_PUSH:
  177. highlight = 0;
  178. if ( Fl::event_button() == FL_RIGHT_MOUSE )
  179. {
  180. active = !active;
  181. redraw();
  182. do_callback();
  183. }
  184. redraw();
  185. return 1;
  186. case FL_DRAG:
  187. {
  188. if ( Fl::event_state(FL_BUTTON1) )
  189. {
  190. if ( mouseClicked == false ) // catch the "click" event
  191. {
  192. mouseClickedX = Fl::event_x();
  193. mouseClickedY = Fl::event_y();
  194. mouseClicked = true;
  195. }
  196. float deltaX = mouseClickedX - Fl::event_x();
  197. float deltaY = mouseClickedY - Fl::event_y();
  198. float valX = value();
  199. valX -= deltaX / 100.f;
  200. float valY = gain;
  201. valY += deltaY / 100.f;
  202. if ( valX > 1.0 ) valX = 1.0;
  203. if ( valX < 0.0 ) valX = 0.0;
  204. if ( valY > 1.0 ) valY = 1.0;
  205. if ( valY < 0.0 ) valY = 0.0;
  206. //handle_drag( value + deltaY );
  207. set_value( valX );
  208. gain = valY;
  209. mouseClickedX = Fl::event_x();
  210. mouseClickedY = Fl::event_y();
  211. redraw();
  212. do_callback();
  213. }
  214. }
  215. return 1;
  216. case FL_RELEASE:
  217. if (highlight) {
  218. highlight = 0;
  219. redraw();
  220. do_callback();
  221. }
  222. mouseClicked = false;
  223. return 1;
  224. case FL_SHORTCUT:
  225. if ( test_shortcut() )
  226. {
  227. do_callback();
  228. return 1;
  229. }
  230. return 0;
  231. default:
  232. return Fl_Widget::handle(event);
  233. }
  234. }
  235. private:
  236. void drawLowpass(cairo_t* cr)
  237. {
  238. // draw the cutoff line:
  239. // move to bottom left, draw line to middle left
  240. cairo_move_to( cr, x , y + h );
  241. cairo_line_to( cr, x , y + (h*0.47));
  242. float cutoff = 0.1 + freq * 0.85;
  243. // Curve
  244. cairo_curve_to( cr, x + w * cutoff , y+(h*0.5) , // control point 1
  245. x + w * cutoff , y+(h * 0.3), // control point 2
  246. x + w * cutoff + 5, y+ h ); // end of curve 1
  247. cairo_close_path(cr);
  248. cairo_set_source_rgba( cr, 0 / 255.f, 153 / 255.f , 255 / 255.f , 0.21 );
  249. cairo_fill_preserve(cr);
  250. cairo_set_source_rgba( cr, 0 / 255.f, 153 / 255.f , 255 / 255.f , 1 );
  251. cairo_set_line_width(cr, 1.5);
  252. cairo_set_line_join( cr, CAIRO_LINE_JOIN_ROUND);
  253. cairo_set_line_cap ( cr, CAIRO_LINE_CAP_ROUND);
  254. cairo_stroke( cr );
  255. }
  256. void drawHighpass(cairo_t* cr)
  257. {
  258. // draw the cutoff line:
  259. float cutoff = 0.95 - (freq*0.8);
  260. // move to bottom right
  261. cairo_move_to( cr, x + w, y + h );
  262. cairo_line_to( cr, x + w, y + (h*0.47));
  263. // Curve
  264. cairo_curve_to( cr, x + w - (w*cutoff) , y+(h*0.5) , // control point 1
  265. x + w - (w*cutoff) , y+(h * 0.3), // control point 2
  266. x + w - (w*cutoff) - 5, y+ h ); // end of curve 1
  267. cairo_close_path(cr);
  268. // stroke
  269. cairo_set_source_rgba( cr, 0 / 255.f, 153 / 255.f , 255 / 255.f , 0.21 );
  270. cairo_fill_preserve(cr);
  271. cairo_set_source_rgba( cr, 0 / 255.f, 153 / 255.f , 255 / 255.f , 1 );
  272. cairo_set_line_width(cr, 1.5);
  273. cairo_set_line_join( cr, CAIRO_LINE_JOIN_ROUND);
  274. cairo_set_line_cap ( cr, CAIRO_LINE_CAP_ROUND);
  275. cairo_stroke( cr );
  276. }
  277. void drawFlat(cairo_t* cr)
  278. {
  279. // move to bottom right
  280. cairo_move_to( cr, x + w, y + h );
  281. cairo_line_to( cr, x + w, y + (h*0.47));
  282. cairo_line_to( cr, x , y + (h*0.47));
  283. cairo_line_to( cr, x , y + h );
  284. cairo_close_path(cr);
  285. // stroke
  286. cairo_set_source_rgba( cr, 0 / 255.f, 153 / 255.f , 255 / 255.f , 0.21 );
  287. cairo_fill_preserve(cr);
  288. cairo_set_source_rgba( cr, 0 / 255.f, 153 / 255.f , 255 / 255.f , 1 );
  289. cairo_set_line_width(cr, 1.5);
  290. cairo_set_line_join( cr, CAIRO_LINE_JOIN_ROUND);
  291. cairo_set_line_cap ( cr, CAIRO_LINE_CAP_ROUND);
  292. cairo_stroke( cr );
  293. }
  294. };
  295. } // Avtk
  296. #endif // AVTK_FILTERGRAPH_H