Mixer: Panner: Don't mangle line-style.
[nondaw.git] / mixer / src / Panner.C
blob5d63258a2f91c22b188d220f1ffad26d3b329195
2 /*******************************************************************************/
3 /* Copyright (C) 2008 Jonathan Moore Liles                                     */
4 /*                                                                             */
5 /* This program is free software; you can redistribute it and/or modify it     */
6 /* under the terms of the GNU General Public License as published by the       */
7 /* Free Software Foundation; either version 2 of the License, or (at your      */
8 /* option) any later version.                                                  */
9 /*                                                                             */
10 /* This program is distributed in the hope that it will be useful, but WITHOUT */
11 /* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       */
12 /* FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for   */
13 /* more details.                                                               */
14 /*                                                                             */
15 /* You should have received a copy of the GNU General Public License along     */
16 /* with This program; see the file COPYING.  If not,write to the Free Software */
17 /* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
18 /*******************************************************************************/
20 #include "Panner.H"
21 #include <FL/x.H>
22 #include <FL/Fl.H>
23 #include <stdio.h>
24 #include <math.h>
25 // #include <FL/fl_draw.H>
27 /* 2D Panner widget. Supports various multichannel configurations. */
29 Panner::Point *Panner::drag;
31 /* multichannel layouts, in degrees */
32 int Panner::_configs[][12] =
34     /* none, error condition? */
35     { NONE },
36     /* mono, panner disabled */
37     { NONE },
38     /* stereo */
39     { L, R },
40     /* stereo + mono */
41     { L, R, C },
42     /* quad */
43     { FL, FR, RL, RR },
44     /* 5.1 */
45     { FL, FR, RL, RR, C },
46     /* no such config */
47     { NONE },
48     /* 7.1 */
49     { FL, FR, RL, RR, C, L, R },
53 /* speaker symbol */
54 #define BP fl_begin_polygon()
55 #define EP fl_end_polygon()
56 #define BCP fl_begin_complex_polygon()
57 #define ECP fl_end_complex_polygon()
58 #define BL fl_begin_line()
59 #define EL fl_end_line()
60 #define BC fl_begin_loop()
61 #define EC fl_end_loop()
62 #define vv(x,y) fl_vertex(x,y)
64 static void draw_speaker ( Fl_Color col )
66     fl_color(col);
68     BP; vv(0.2,0.4); vv(0.6,0.4); vv(0.6,-0.4); vv(0.2,-0.4); EP;
69     BP; vv(-0.6,0.8); vv(0.2,0.0); vv(-0.6,-0.8); EP;
71     fl_color( fl_darker( col ) );
73     BC; vv(0.2,0.4); vv(0.6,0.4); vv(0.6,-0.4); vv(0.2,-0.4); EC;
74     BC; vv(-0.6,0.8); vv(0.2,0.0); vv(-0.6,-0.8); EC;
78 /** set X, Y, W, and H to the bounding box of point /p/ in screen coords */
79 void
80 Panner::point_bbox ( const Point *p, int *X, int *Y, int *W, int *H ) const
82     int tx, ty, tw, th;
84     bbox( tx, ty, tw, th );
86     const float PW = pw(); 
87     const float PH = ph();
89     tw -= PW;
90     th -= PH;
92     float px, py;
94     p->axes( &px, &py );
96     *X = tx + ((tw / 2) * px + (tw / 2));
97     *Y = ty + ((th / 2) * py + (th / 2));
99     *W = PW;
100     *H = PH;
103 Panner::Point *
104 Panner::event_point ( void )
106     for ( int i = _ins; i--; )
107     {
108         int px, py, pw, ph;
110         Point *p = &_points[ i ];
112         point_bbox( p, &px, &py, &pw, &ph );
114 //        printf( "%d, %d -- %d %d %d %d\n", Fl::event_x(), Fl::event_y(),  px, py, pw, ph );
116         if ( Fl::event_inside( px, py, pw, ph ) )
117             return p;
118     }
120     return NULL;
124 void
125 Panner::draw_the_box ( int tx, int ty, int tw, int th )
127     draw_box();
129     fl_line_style( FL_SOLID, 2 );
131     /* draw perimeter */
132     {
133         Fl_Color c1, c2;
134         int iter;
136         if ( Fl::belowmouse() == this )
137         {
138             iter = 12;
139             c1 = fl_darker( fl_darker( FL_RED ) );
140             c2 = FL_BLACK;
141         }
142         else
143         {
144             iter = 6;
145             c1 = FL_GRAY;
146             c2 = FL_BLACK;
147         }
149         Fl_Color c = c1;
151         for ( int i = iter; i--; )
152         {
153             fl_color( c );
155             fl_arc( tx + (i * (tw / iter)) / 2, ty + (i * (th / iter)) / 2, tw - (i * (tw / iter)), th - (i * ( th / iter )), 0, 360 );
157             /* fl_arc( cr, */
158             /*               tx + tw / 2, */
159             /*               ty + th / 2, */
160             /*               ((float)tw / iter) / 2, */
161             /*               0, 360 ); */
163             c = fl_color_average( c1, c2, (float)i / iter);
164         }
165     }
167     fl_line_style( FL_SOLID, 0 );
171 void
172 Panner::draw ( void )
174     int tw, th, tx, ty;
176     bbox( tx, ty, tw, th );
178     fl_push_clip( tx, ty, tw, th );
181     const int b = 10;
183 //    draw_box();
184     draw_label();
186     if ( _bypassed )
187     {
188         draw_box();
189         fl_color( 0 );
190         fl_font( FL_HELVETICA, 12 );
191         fl_draw( "(bypass)", x(), y(), w(), h(), FL_ALIGN_CENTER );
192         goto done;
193     }
194    
196     tx += b;
197     ty += b;
198     tw -= b * 2;
199     th -= b * 2;
201     if ( damage() & FL_DAMAGE_ALL )
202         draw_the_box( tx, ty, tw, th );
204     fl_line_style( FL_SOLID, 2 );
206 //    fl_color( FL_RED );
208     fl_color( FL_WHITE );
210 /*     fl_arc( tx, ty, tw, th, 0, 360 ); */
212     if ( _configs[ _outs ][0] >= 0 )
213     {
214         for ( int i = _outs; i--; )
215         {
216             int a = _configs[ _outs ][ i ];
218             Point p( 1.2f, (float)a );
220             float px, py;
222             p.axes( &px, &py );
224             fl_push_matrix();
226             const int bx = tx + ((tw / 2) * px + (tw / 2));
227             const int by = ty + ((th / 2) * py + (th / 2));
229             fl_translate( bx, by );
231             fl_scale( 5, 5 );
233             a = 90 - a;
235             fl_rotate( a );
237             draw_speaker( FL_WHITE );
239             fl_rotate( -a );
241             fl_pop_matrix();
243         }
244     }
246     /* ensure that points are drawn *inside* the circle */
248     for ( int i = _ins; i--; )
249     {
250         Point *p = &_points[ i ];
252         Fl_Color c = (Fl_Color)(10 + i);
254         int px, py, pw, ph;
255         point_bbox( p, &px, &py, &pw, &ph );
259         {
261             const float S = ( 0.5 + ( 1.0f - p->d ) );
263             float po = 5 * S;
265             fl_push_clip( px - ( po * 12 ), 
266                           py - ( po * 12 ),
267                           pw + ( po * 24 ), ph + (po * 24 ));
269             if ( damage() & FL_DAMAGE_EXPOSE )
270                 draw_the_box( tx, ty, tw, th );
272             fl_color( FL_WHITE );
273             
274             /* draw point */
275             if ( p != drag )
276                 fl_color( c );
277             
278             fl_pie( px, py, pw, ph, 0, 360 );
279             
280             /* draw echo */
281             fl_color( c = fl_darker( c ) );
282 //            fl_color_alpha( c = fl_darker( c ), 0.5 );
283         
284 //            fl_arc( cr, px, py, pw + po * 1, 0, 360 );
285             fl_arc( px - po, py - po, pw + ( po * 2 ), ph + ( po * 2 ), 0, 360 );
287             if ( Fl::belowmouse() == this )
288             {
289                 fl_color( c = fl_darker( c ) );
290             
291 //                fl_color_alpha( c = fl_darker( c ), 0.5 );
292                 fl_arc( px - ( po * 2 ), py - ( po * 2 ), pw + ( po * 4 ), ph + ( po * 4 ), 0, 360 );
293                 /* fl_arc( cr, px, py, pw + po * 1, 0, 360 ); */
295             fl_color( c = fl_darker( c ) );
297 //                fl_color_alpha( c = fl_darker( c ), 0.5 );
298                 fl_arc( px - ( po * 4 ), py - ( po * 4 ), pw + ( po * 8 ), ph + (po * 8 ), 0, 360 );
299                 /* fl_arc( cr, px, py, pw + po * 1, 0, 360 ); */
300             }
302             fl_pop_clip();
303         }
305         /* draw number */
306         char pat[4];
307         snprintf( pat, 4, "%d", i + 1 );
309         fl_color( FL_BLACK );
310         fl_font( FL_HELVETICA, ph + 2 );
311         fl_draw( pat, px + 1, py + 1, pw - 1, ph - 1, FL_ALIGN_CENTER );
313         /* draw line */
315 /*         fl_color( FL_WHITE ); */
316 /*         fl_line( bx + pw() / 2, by + ph() / 2, tx + (tw / 2), ty + (th / 2) ); */
318     }
319 done:
321     fl_line_style( FL_SOLID, 0 );
323     fl_pop_clip();
326 /* return the current gain setting for the path in/out  */
327 Panner::Point *
328 Panner::point( int i )
330     return &_points[ i ];
334 Panner::handle ( int m )
336     int r = Fl_Widget::handle( m );
338     switch ( m )
339     {
340         case FL_ENTER:
341         case FL_LEAVE:
342             redraw();
343             return 1;
344         case FL_PUSH:
345         {
346             if ( Fl::event_button2() )
347             {
348                 _bypassed = ! _bypassed;
349                 redraw();
350                 return 1;
351             }
353             if ( Fl::event_button1() )
354                 drag = event_point();
356             return 1;
357         }
358         case FL_RELEASE:
359             if ( Fl::event_button1() && drag )
360             {
361                 drag = NULL;
362                 do_callback();
363                 redraw();
364                 return 1;
365             }
366             else
367                 return 0;
368         case FL_MOUSEWHEEL:
369         {
370             /* TODO: place point on opposite face of sphere */
371         }
372         case FL_DRAG:
373         {
374             if ( ! drag )
375                 return 0;
377             /* else if ( Fl::event_button1() && ( drag = event_point() ) ) */
378             /*     return 1; */
379             /* else */
381             float X = Fl::event_x() - x();
382             float Y = Fl::event_y() - y();
384             int tx, ty, tw, th;
385             bbox( tx, ty, tw, th );
387 /*             if ( _outs < 3 ) */
388 /*                 drag->angle( (float)(X / (tw / 2)) - 1.0f, 0.0f ); */
389 /*             else */
390             drag->angle( (float)(X / (tw / 2)) - 1.0f, (float)(Y / (th / 2)) - 1.0f );
392             if ( when() & FL_WHEN_CHANGED )
393                 do_callback();
395             damage(FL_DAMAGE_EXPOSE);
397             return 1;
398         }
400     }
402     return r;
404 //    return 0;