g_vumeter.c 22.7 KB
Newer Older
Miller Puckette's avatar
Miller Puckette committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/* Copyright (c) 1997-1999 Miller Puckette.
 * For information on usage and redistribution, and for a DISCLAIMER OF ALL
 * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */

/* g_7_guis.c written by Thomas Musil (c) IEM KUG Graz Austria 2000-2001 */
/* thanks to Miller Puckette, Guenther Geiger and Krzystof Czaja */

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "m_pd.h"
#include "g_canvas.h"
#include "g_all_guis.h"
#include <math.h>

16
17
18
19
20
21
22
23
#define IEM_VU_DEFAULTSIZE 3
#define IEM_VU_LARGESMALL  2
#define IEM_VU_MINSIZE     2
#define IEM_VU_MAXSIZE     25
#define IEM_VU_STEPS       40
#define IEM_VU_MINDB    -99.9
#define IEM_VU_MAXDB    12.0
#define IEM_VU_OFFSET   100.0
Hans-Christoph Steiner's avatar
Hans-Christoph Steiner committed
24

25
26
27
char *iemgui_vu_scale_str[]={
    "<-99", "-50", "-30", "-20", "-12", "-6",
      "-2", "-0dB",  "+2",  "+6",">+12",  "",
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
};

int iemgui_vu_db2i[]=
{
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
    2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
    2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
    2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
    2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
    3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
    4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
    5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
    6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
    7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
    8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
    9, 9, 9, 9, 9,10,10,10,10,10,
    11,11,11,11,11,12,12,12,12,12,
    13,13,13,13,14,14,14,14,15,15,
    15,15,16,16,16,16,17,17,17,18,
    18,18,19,19,19,20,20,20,21,21,
    22,22,23,23,24,24,25,26,27,28,
    29,30,31,32,33,33,34,34,35,35,
    36,36,37,37,37,38,38,38,39,39,
    39,39,39,39,40,40
};

int iemgui_vu_col[]=
{
    0,17,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
    15,15,15,15,15,15,15,15,15,15,14,14,13,13,13,13,13,13,13,13,13,13,13,19,19,19
};

63
static t_class *scalehandle_class;
64
65
extern int gfxstub_haveproperties(void *key);
void vu_check_height(t_vu *x, int h);
Miller Puckette's avatar
Miller Puckette committed
66
t_widgetbehavior vu_widgetbehavior;
67
t_class *vu_class;
Miller Puckette's avatar
Miller Puckette committed
68
69
70

static void vu_update_rms(t_vu *x, t_glist *glist)
{
71
    if (glist_isvisible(glist))
Miller Puckette's avatar
Miller Puckette committed
72
    {
73
        int w4 = x->x_gui.x_w / 4, off=text_ypix(&x->x_gui.x_obj, glist) - 1;
74
75
        int x1 = text_xpix(&x->x_gui.x_obj, glist),
            quad1 = x1 + w4 + 1, quad3 = x1 + x->x_gui.x_w-w4 - 1;
Miller Puckette's avatar
Miller Puckette committed
76
77

        sys_vgui(".x%lx.c coords %lxRCOVER %d %d %d %d\n",
78
79
            glist_getcanvas(glist), x, quad1 + 1, off + 2, quad3 + 1,
            off + (x->x_led_size + 1) * (IEM_VU_STEPS - x->x_rms) + 2);
Miller Puckette's avatar
Miller Puckette committed
80
81
82
83
84
85
86
87
88
    }
}

static void vu_update_peak(t_vu *x, t_glist *glist)
{
    t_canvas *canvas=glist_getcanvas(glist);

    if(glist_isvisible(glist))
    {
89
90
        int x1 = text_xpix(&x->x_gui.x_obj, glist);
        int y1 = text_ypix(&x->x_gui.x_obj, glist);
Miller Puckette's avatar
Miller Puckette committed
91
92
93

        if(x->x_peak)
        {
94
            int i = iemgui_vu_col[x->x_peak];
95
            int j = y1 + (x->x_led_size + 1) * (IEM_VU_STEPS + 1 - x->x_peak)
96
97
98
                - (x->x_led_size + 1) / 2;

            sys_vgui(".x%lx.c coords %lxPLED %d %d %d %d\n",
99
                canvas, x, x1 + 1, j + 2, x1 + x->x_gui.x_w + 2, j + 2);
100
            sys_vgui(".x%lx.c itemconfigure %lxPLED -stroke #%6.6x\n",
101
                canvas, x, iemgui_color_hex[i]);
Miller Puckette's avatar
Miller Puckette committed
102
103
104
        }
        else
        {
105
            int mid = x1 + x->x_gui.x_w / 2;
Miller Puckette's avatar
Miller Puckette committed
106

107
            sys_vgui(".x%lx.c itemconfigure %lxPLED -stroke #%6.6x\n",
Miller Puckette's avatar
Miller Puckette committed
108
109
                     canvas, x, x->x_gui.x_bcol);
            sys_vgui(".x%lx.c coords %lxPLED %d %d %d %d\n",
110
                     canvas, x, mid+1, y1+22, mid+1, y1+22);
Miller Puckette's avatar
Miller Puckette committed
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
        }
    }
}

static void vu_draw_update(t_gobj *client, t_glist *glist)
{
    t_vu *x = (t_vu *)client;
    if (x->x_updaterms)
    {
        vu_update_rms(x, glist);
        x->x_updaterms = 0;
    }
    if (x->x_updatepeak)
    {
        vu_update_peak(x, glist);
        x->x_updatepeak = 0;
    }
}
129

Miller Puckette's avatar
Miller Puckette committed
130
131
132
static void vu_draw_new(t_vu *x, t_glist *glist)
{
    t_canvas *canvas=glist_getcanvas(glist);
133
    int x1=text_xpix(&x->x_gui.x_obj, glist), x2=x1+x->x_gui.x_w;
134
    int y1=text_ypix(&x->x_gui.x_obj, glist);
135
136
    int w4=x->x_gui.x_w/4, mid=x1+x->x_gui.x_w/2, quad1=x1+w4+1;
    int quad3=x2-w4, end=x2+4;
Miller Puckette's avatar
Miller Puckette committed
137
    int k1=x->x_led_size+1, k2=IEM_VU_STEPS+1, k3=k1/2;
138
    int led_col, yyy, i, k4=y1-k3;
139
    iemgui_base_draw_new(&x->x_gui, canvas);
140

141
142
143
    for(i = 1; i <= IEM_VU_STEPS+1; i++)
    {
        yyy = k4 + k1 * (k2-i);
144
        if((i&3)==1 && (x->x_scale))
145
            sys_vgui(".x%lx.c create text %d %d -text {%s} -anchor w "
146
                "-font {{%s} -%d %s} -fill #%6.6x "
147
                "-tags {%lxSCALEN %lxSCALE%d x%lx text iemgui}\n",
148
                canvas, end+1, yyy+k3+2, iemgui_vu_scale_str[i/4], 
149
                iemgui_font(&x->x_gui), x->x_gui.x_fontsize,
150
                sys_fontweight, x->x_gui.x_lcol, x, x, i, x);
151
152
153
154

        led_col = iemgui_vu_col[i];
        if (i<=IEM_VU_STEPS) sys_vgui(".x%lx.c create polyline %d %d %d %d "
            "-strokewidth %d -stroke #%6.6x "
155
            "-tags {%lxRLED%d x%lx text iemgui}\n",
156
            canvas, quad1+1, yyy+2, quad3, yyy+2,
157
            x->x_led_size, iemgui_color_hex[led_col], x, i, x);
158
159
    }
    sys_vgui(".x%lx.c create prect %d %d %d %d -fill #%6.6x "
160
        "-stroke #%6.6x -tags {%lxRCOVER x%lx text iemgui}\n",
161
        canvas, quad1+1, y1+1, quad3, y1+1 + k1*IEM_VU_STEPS,
162
        x->x_gui.x_bcol, x->x_gui.x_bcol, x, x);
163
164
    sys_vgui(".x%lx.c create polyline %d %d %d %d "
        "-strokewidth %d -fill #%6.6x "
165
        "-tags {%lxPLED x%lx text iemgui}\n",
166
        canvas, mid+1, y1+12,
167
        mid+1, y1+12, x->x_led_size, x->x_gui.x_bcol, x, x);
168
    iemgui_draw_io(&x->x_gui,glist,7);
169
170
    x->x_updaterms = x->x_updatepeak = 1;
    sys_queuegui(x, x->x_gui.x_glist, vu_draw_update);
Miller Puckette's avatar
Miller Puckette committed
171
172
173
174
175
}

static void vu_draw_move(t_vu *x, t_glist *glist)
{
    t_canvas *canvas=glist_getcanvas(glist);
176
    if (!glist_isvisible(canvas)) return;
Miller Puckette's avatar
Miller Puckette committed
177

178
179
180
181
182
    int x1=text_xpix(&x->x_gui.x_obj, glist);
    int y1=text_ypix(&x->x_gui.x_obj, glist);
    int w4=x->x_gui.x_w/4, quad1=x1+w4+1;
    int quad3=x1+x->x_gui.x_w-w4,
          end=x1+x->x_gui.x_w+4;
183
    int k1=x->x_led_size+1, k2=IEM_VU_STEPS+1, k3=k1/2;
184
    int yyy, i, k4=y1-k3;
185
    sys_vgui(".x%lx.c coords %lxBASE %d %d %d %d\n",
186
        canvas, x, x1, y1, x1+x->x_gui.x_w+2,y1+x->x_gui.x_h+4);
187
    for(i=1; i<=IEM_VU_STEPS; i++)
188
    {
189
190
191
192
        yyy = k4 + k1*(k2-i);
        sys_vgui(".x%lx.c coords %lxRLED%d %d %d %d %d\n",
            canvas, x, i, quad1+1, yyy+2, quad3, yyy+2);
        if(((i+2)&3) && (x->x_scale))
193
            sys_vgui(".x%lx.c coords %lxSCALE%d %d %d\n",
194
                canvas, x, i, end+1, yyy+k3+2);
Miller Puckette's avatar
Miller Puckette committed
195
196
197
    }
    if(x->x_scale)
    {
198
199
200
201
        i=IEM_VU_STEPS+1;
        yyy = k4 + k1*(k2-i);
        sys_vgui(".x%lx.c coords %lxSCALE%d %d %d\n",
            canvas, x, i, end+1, yyy+k3+2);
Miller Puckette's avatar
Miller Puckette committed
202
    }
203
204
    x->x_updaterms = x->x_updatepeak = 1;
    sys_queuegui(x, glist, vu_draw_update);
205
206
    iemgui_label_draw_move(&x->x_gui,canvas);
    iemgui_io_draw_move(&x->x_gui,canvas);
Miller Puckette's avatar
Miller Puckette committed
207
208
}

209
static void vu_draw_config(t_vu* x, t_glist* glist)
Miller Puckette's avatar
Miller Puckette committed
210
{
211
    int i;
Miller Puckette's avatar
Miller Puckette committed
212
    t_canvas *canvas=glist_getcanvas(glist);
213
214
    char lcol[8]; sprintf(lcol, "%6.6x", x->x_gui.x_lcol);
    for(i = 1; i <= IEM_VU_STEPS+1; i++)
215
    {
216
217
218
        if (i <= IEM_VU_STEPS)
            sys_vgui(".x%lx.c itemconfigure %lxRLED%d -strokewidth %d\n",
                canvas, x, i, x->x_led_size);
219
        if((i&3)==1) sys_vgui(".x%lx.c itemconfigure %lxSCALE%d -text {%s} "
220
            "-font {{%s} -%d %s} -fill %s\n",
221
            canvas, x, i, iemgui_vu_scale_str[i/4], iemgui_font(&x->x_gui), 
222
            x->x_gui.x_fontsize, sys_fontweight,
223
            (x->x_scale) ? selection_color : lcol);
224
    }
225
226
227
228
229
230
    iemgui_label_draw_config(&x->x_gui,canvas);
    sys_vgui(".x%lx.c itemconfigure %lxRCOVER -fill #%6.6x -stroke #%6.6x\n",
             canvas, x, x->x_gui.x_bcol, x->x_gui.x_bcol);
    sys_vgui(".x%lx.c itemconfigure %lxPLED -strokewidth %d\n",
             canvas, x, x->x_led_size);
    iemgui_base_draw_config(&x->x_gui,canvas);
Miller Puckette's avatar
Miller Puckette committed
231
232
233
234
235
}

static void vu_draw_select(t_vu* x,t_glist* glist)
{
    t_canvas *canvas=glist_getcanvas(glist);
236
237
    char lcol[8]; sprintf(lcol,"#%6.6x", x->x_gui.x_lcol);
    int issel = x->x_gui.x_selected && x->x_gui.x_glist==canvas;
238
239
    sys_vgui(".x%lx.c itemconfigure %lxSCALEN -fill %s\n",
        canvas, x, issel ? selection_color : lcol);
240
241
}

242
243
static void vu__clickhook(t_scalehandle *sh, t_floatarg f, t_floatarg xxx,
    t_floatarg yyy)
244
{
245
    t_vu *x = (t_vu *)(sh->h_master);
246
    int newstate = (int)f;
247
    if (sh->h_dragon && newstate == 0  && sh->h_scale)
Miller Puckette's avatar
Miller Puckette committed
248
    {
249
250
251
        canvas_apply_setundo(x->x_gui.x_glist, (t_gobj *)x);
        if (sh->h_dragx || sh->h_dragy)
        {
252
253
            x->x_gui.x_w += sh->h_dragx;
            x->x_gui.x_h += sh->h_dragy;
254
255
256
257
258
259
260
261
            canvas_dirty(x->x_gui.x_glist, 1);
        }
        if (glist_isvisible(x->x_gui.x_glist))
        {
            vu_check_height(x, x->x_gui.x_h);
            vu_draw_move(x, x->x_gui.x_glist);
            vu_draw_config(x, x->x_gui.x_glist);
            vu_draw_update((t_gobj *)x, x->x_gui.x_glist);
262
            scalehandle_unclick_scale(sh);
263
        }
Miller Puckette's avatar
Miller Puckette committed
264
    }
265
    iemgui__clickhook3(sh,newstate);
266
267
}

268
static void vu__motionhook(t_scalehandle *sh, t_floatarg f1, t_floatarg f2)
269
{
270
    if (sh->h_dragon && sh->h_scale)
271
    {
272
273
        t_vu *x = (t_vu *)(sh->h_master);
        int dx = (int)f1, dy = (int)f2;
274
275
        dx = maxi(dx, 8-x->x_gui.x_w);
        dy = maxi(dy,80-x->x_gui.x_h);        
276
277
        sh->h_dragx = dx;
        sh->h_dragy = dy;
278
        scalehandle_drag_scale(sh);
279
280
281
282

        int properties = gfxstub_haveproperties((void *)x);
        if (properties)
        {
283
284
            int new_w = x->x_gui.x_w + sh->h_dragx;
            int new_h = x->x_gui.x_h + sh->h_dragy;
285
286
            properties_set_field_int(properties,"dim.w_ent",new_w);
            properties_set_field_int(properties,"dim.h_ent",new_h);
287
        }
288
    }
289
    scalehandle_dragon_label(sh,f1,f2);
Miller Puckette's avatar
Miller Puckette committed
290
291
292
293
}

void vu_draw(t_vu *x, t_glist *glist, int mode)
{
294
295
296
297
298
    if(mode == IEM_GUI_DRAW_MODE_UPDATE)      sys_queuegui((t_gobj*)x, x->x_gui.x_glist, vu_draw_update);
    if(mode == IEM_GUI_DRAW_MODE_MOVE)        vu_draw_move(x, glist);
    else if(mode == IEM_GUI_DRAW_MODE_NEW)    vu_draw_new(x, glist);
    else if(mode == IEM_GUI_DRAW_MODE_SELECT) vu_draw_select(x, glist);
    else if(mode == IEM_GUI_DRAW_MODE_CONFIG) vu_draw_config(x, glist);
Miller Puckette's avatar
Miller Puckette committed
299
300
301
302
}

/* ------------------------ vu widgetbehaviour----------------------------- */

303
304
static void vu_scale_getrect(t_iemgui x_gui, t_glist *x, int *xp1, int *yp1,
    int *xp2, int *yp2, int scale_x, int scale_y)
305
{
306
307
308
309
310
311
312
313
314
315
316
    t_float width_multiplier;
    int scale_length;    
    int scale_x1;
    int scale_y1;
    int scale_x2;
    int scale_y2;
    int actual_fontsize; //seems tk does its own thing when it comes to rendering
    int actual_height;

    if (x->gl_isgraph && !glist_istoplevel(x))
    {
317
        switch(x_gui.x_font_style)
318
        {
319
320
321
            case 1:   width_multiplier = 0.83333; break;
            case 2:   width_multiplier = 0.735;   break;
            default:  width_multiplier = 1.0;     break;
322
        }
323
        actual_fontsize = x_gui.x_fontsize;
324
325
        actual_height = actual_fontsize;
        //exceptions
326
        if (x_gui.x_font_style == 0 &&
327
328
329
330
331
332
333
            (actual_fontsize == 8 || actual_fontsize == 13 ||
             actual_fontsize % 10 == 1 || actual_fontsize % 10 == 6 ||
             (actual_fontsize > 48 && actual_fontsize < 100 &&
              (actual_fontsize %10 == 4 || actual_fontsize %10 == 9))) )
        {
            actual_fontsize += 1;
        }
334
        else if (x_gui.x_font_style == 1 &&
335
336
337
338
339
340
            actual_fontsize >= 5 &&
            actual_fontsize < 13 &&
            actual_fontsize % 2 == 1)
        {
            actual_fontsize += 1;
        }
341
        else if (x_gui.x_font_style == 2 &&
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
            actual_fontsize >= 5 &&
            actual_fontsize % 2 == 1)
        {
            actual_fontsize += 1;
        }
        if (actual_height == 9)
            actual_height += 1;
        //done with exceptions

        width_multiplier = width_multiplier * (actual_fontsize * 0.6);

        scale_length = 4;
        scale_x1 = scale_x;
        scale_y1 = scale_y - actual_height/2;
        scale_x2 = scale_x1 + (scale_length * width_multiplier);
        scale_y2 = scale_y1 + actual_height*1.1;

        if (scale_x1 < *xp1) *xp1 = scale_x1;
        if (scale_x2 > *xp2) *xp2 = scale_x2;
        if (scale_y1 < *yp1) *yp1 = scale_y1;
        if (scale_y2 > *yp2) *yp2 = scale_y2;
    }
364
}
Miller Puckette's avatar
Miller Puckette committed
365
366

static void vu_getrect(t_gobj *z, t_glist *glist,
367
    int *xp1, int *yp1, int *xp2, int *yp2)
Miller Puckette's avatar
Miller Puckette committed
368
369
370
{
    t_vu* x = (t_vu*)z;

371
    int yyy, end;
372
373
374
    int x1=text_xpix(&x->x_gui.x_obj, glist);
    int y1=text_ypix(&x->x_gui.x_obj, glist);
    int k1=x->x_led_size+1, k2=IEM_VU_STEPS+1, k3=k1/2, k4=y1-k3;
375

376
    *xp1 = text_xpix(&x->x_gui.x_obj, glist);
377
    *yp1 = text_ypix(&x->x_gui.x_obj, glist);
378
    *xp2 = *xp1 + x->x_gui.x_w + 2;
379
    *yp2 = *yp1 + x->x_gui.x_h + 4;
380

381
    iemgui_label_getrect(x->x_gui, glist, xp1, yp1, xp2, yp2);
382

383
384
385
    if (x->x_scale)
    {
        //vu has custom scale all labels unlike other iemgui object
386
        end=x1+x->x_gui.x_w+4;
387
388
389
390
391
        yyy = k4 + k1*(k2-1);
        vu_scale_getrect(x->x_gui, glist, xp1, yp1, xp2, yp2, end+1, yyy+k3+2);
        yyy = k4;
        vu_scale_getrect(x->x_gui, glist, xp1, yp1, xp2, yp2, end+1, yyy+k3+2);
    }
Miller Puckette's avatar
Miller Puckette committed
392
393
394
395
396
397
398
399
}

static void vu_save(t_gobj *z, t_binbuf *b)
{
    t_vu *x = (t_vu *)z;
    int bflcol[3];
    t_symbol *srl[3];
    iemgui_save(&x->x_gui, srl, bflcol);
400
401
402
403
404
405
406
    binbuf_addv(b, "ssiisiissiiiiiiii;", gensym("#X"),gensym("obj"),
        (int)x->x_gui.x_obj.te_xpix, (int)x->x_gui.x_obj.te_ypix,
        gensym("vu"), x->x_gui.x_w, x->x_gui.x_h,
        srl[1], srl[2], x->x_gui.x_ldx, x->x_gui.x_ldy,
        iem_fstyletoint(&x->x_gui), x->x_gui.x_fontsize,
        bflcol[0], bflcol[2], x->x_scale,
        iem_symargstoint(&x->x_gui));
Miller Puckette's avatar
Miller Puckette committed
407
408
409
410
}

void vu_check_height(t_vu *x, int h)
{
411
    int n = maxi(h / IEM_VU_STEPS, IEM_VU_MINSIZE);
Miller Puckette's avatar
Miller Puckette committed
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
    x->x_led_size = n-1;
    x->x_gui.x_h = IEM_VU_STEPS * n;
}

static void vu_scale(t_vu *x, t_floatarg fscale)
{
    int i, scale = (int)fscale;

    if(scale != 0) scale = 1;
    if(x->x_scale && !scale)
    {
        t_canvas *canvas=glist_getcanvas(x->x_gui.x_glist);

        x->x_scale = (int)scale;
        if(glist_isvisible(x->x_gui.x_glist))
        {
            for(i=1; i<=IEM_VU_STEPS; i++)
            {
                if((i+2)&3)
                    sys_vgui(".x%lx.c delete %lxSCALE%d\n", canvas, x, i);
            }
            i=IEM_VU_STEPS+1;
            sys_vgui(".x%lx.c delete %lxSCALE%d\n", canvas, x, i);
        }
    }
    if(!x->x_scale && scale)
    {
Mathieu L Bouchard's avatar
Mathieu L Bouchard committed
439
        int end=text_xpix(&x->x_gui.x_obj,
440
            x->x_gui.x_glist)+x->x_gui.x_w+4;
Miller Puckette's avatar
Miller Puckette committed
441
442
443
444
445
446
447
448
449
450
        int k1=x->x_led_size+1, k2=IEM_VU_STEPS+1, k3=k1/2;
        int yyy, k4=text_ypix(&x->x_gui.x_obj, x->x_gui.x_glist)-k3;
        t_canvas *canvas=glist_getcanvas(x->x_gui.x_glist);

        x->x_scale = (int)scale;
        if(glist_isvisible(x->x_gui.x_glist))
        {
            for(i=1; i<=IEM_VU_STEPS; i++)
            {
                yyy = k4 + k1*(k2-i);
451
                if((i&3)==1)
452
453
                    sys_vgui(".x%lx.c create text %d %d -text {%s} -anchor w "
                             "-font {{%s} -%d %s} -fill #%6.6x "
454
                             "-tags {%lxSCALE%d x%lx}\n",
455
                        canvas, end+1, yyy+k3+2, iemgui_vu_scale_str[i/4], 
456
                        iemgui_font(&x->x_gui), x->x_gui.x_fontsize,
457
                        sys_fontweight, x->x_gui.x_lcol, x, i, x);
Miller Puckette's avatar
Miller Puckette committed
458
            }
459
            i = IEM_VU_STEPS + 1;
Miller Puckette's avatar
Miller Puckette committed
460
            yyy = k4 + k1*(k2-i);
461
462
            sys_vgui(".x%lx.c create text %d %d -text {%s} -anchor w "
                     "-font {{%s} -%d %s} -fill #%6.6x "
463
                     "-tags {%lxSCALE%d x%lx}\n",
464
                canvas, end+1, yyy+k3+2, iemgui_vu_scale_str[i/4], 
465
                iemgui_font(&x->x_gui), x->x_gui.x_fontsize,
466
                sys_fontweight, x->x_gui.x_lcol, x, i, x);
Miller Puckette's avatar
Miller Puckette committed
467
468
469
470
471
472
473
474
475
476
477
        }
    }
}

static void vu_properties(t_gobj *z, t_glist *owner)
{
    t_vu *x = (t_vu *)z;
    char buf[800];
    t_symbol *srl[3];

    iemgui_properties(&x->x_gui, srl);
Miller Puckette's avatar
Miller Puckette committed
478
    sprintf(buf, "pdtk_iemgui_dialog %%s |vu| \
479
480
481
482
483
484
485
486
487
488
489
490
        --------dimensions(pix)(pix):-------- %d %d width: %d %d height: \
        empty 0.0 empty 0.0 empty %d %d no_scale scale %d %d empty %d \
        {%s} {%s} {%s} %d %d %d %d %d %d %d\n",
        x->x_gui.x_w, IEM_GUI_MINSIZE, x->x_gui.x_h,
        IEM_VU_STEPS*IEM_VU_MINSIZE,
        0,/*no_schedule*/
        x->x_scale, -1, -1, -1,/*no linlog, no init, no multi*/
        "nosndno", srl[1]->s_name,/*no send*/
        srl[2]->s_name, x->x_gui.x_ldx, x->x_gui.x_ldy,
        x->x_gui.x_font_style, x->x_gui.x_fontsize,
        0xffffff & x->x_gui.x_bcol, -1/*no front-color*/,
        0xffffff & x->x_gui.x_lcol);
Miller Puckette's avatar
Miller Puckette committed
491
492
493
494
495
    gfxstub_new(&x->x_gui.x_obj.ob_pd, x, buf);
}

static void vu_dialog(t_vu *x, t_symbol *s, int argc, t_atom *argv)
{
496
    canvas_apply_setundo(x->x_gui.x_glist, (t_gobj *)x);
Miller Puckette's avatar
Miller Puckette committed
497
    t_symbol *srl[3];
498
499
500
    int w = atom_getintarg(0, argc, argv);
    int h = atom_getintarg(1, argc, argv);
    int scale = !!atom_getintarg(4, argc, argv);
501
    srl[0] = s_empty;
502
    int sr_flags = iemgui_dialog(&x->x_gui, srl, argc, argv);
503
    x->x_gui.x_loadinit = 0;
Miller Puckette's avatar
Miller Puckette committed
504
505
    x->x_gui.x_w = iemgui_clip_size(w);
    vu_check_height(x, h);
506
    vu_scale(x, (t_float)scale);
507
508
    x->x_gui.x_draw(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_CONFIG);
    iemgui_draw_io(&x->x_gui, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_IO + sr_flags);
509
    iemgui_shouldvis(&x->x_gui, IEM_GUI_DRAW_MODE_MOVE);
510
    scalehandle_draw(&x->x_gui, x->x_gui.x_glist);
511
    scrollbar_update(x->x_gui.x_glist);
Miller Puckette's avatar
Miller Puckette committed
512
513
514
515
516
517
518
519
520
}

static void vu_size(t_vu *x, t_symbol *s, int ac, t_atom *av)
{
    x->x_gui.x_w = iemgui_clip_size((int)atom_getintarg(0, ac, av));
    if(ac > 1)
        vu_check_height(x, (int)atom_getintarg(1, ac, av));
    if(glist_isvisible(x->x_gui.x_glist))
    {
521
522
        x->x_gui.x_draw(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_MOVE);
        x->x_gui.x_draw(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_CONFIG);
Miller Puckette's avatar
Miller Puckette committed
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
        canvas_fixlinesfor(glist_getcanvas(x->x_gui.x_glist), (t_text*)x);
    }
}

static void vu_float(t_vu *x, t_floatarg rms)
{
    int i;

    if(rms <= IEM_VU_MINDB)
        x->x_rms = 0;
    else if(rms >= IEM_VU_MAXDB)
        x->x_rms = IEM_VU_STEPS;
    else
    {
        int i = (int)(2.0*(rms + IEM_VU_OFFSET));
        x->x_rms = iemgui_vu_db2i[i];
    }
    i = (int)(100.0*rms + 10000.5);
541
    rms = 0.01*(t_float)(i - 10000);
Miller Puckette's avatar
Miller Puckette committed
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
    x->x_fr = rms;
    outlet_float(x->x_out_rms, rms);
    x->x_updaterms = 1;
    sys_queuegui(x, x->x_gui.x_glist, vu_draw_update);
}

static void vu_ft1(t_vu *x, t_floatarg peak)
{
    int i;

    if(peak <= IEM_VU_MINDB)
        x->x_peak = 0;
    else if(peak >= IEM_VU_MAXDB)
        x->x_peak = IEM_VU_STEPS;
    else
    {
        int i = (int)(2.0*(peak + IEM_VU_OFFSET));
        x->x_peak = iemgui_vu_db2i[i];
    }
    i = (int)(100.0*peak + 10000.5);
562
    peak = 0.01*(t_float)(i - 10000);
Miller Puckette's avatar
Miller Puckette committed
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
    x->x_fp = peak;
    x->x_updatepeak = 1;
    sys_queuegui(x, x->x_gui.x_glist, vu_draw_update);
    outlet_float(x->x_out_peak, peak);
}

static void vu_bang(t_vu *x)
{
    outlet_float(x->x_out_peak, x->x_fp);
    outlet_float(x->x_out_rms, x->x_fr);
    x->x_updaterms = x->x_updatepeak = 1;
    sys_queuegui(x, x->x_gui.x_glist, vu_draw_update);
}

static void *vu_new(t_symbol *s, int argc, t_atom *argv)
{
    t_vu *x = (t_vu *)pd_new(vu_class);
580
581
    int bflcol[] = {-66577, -1, -1};
    int w = IEM_GUI_DEFAULTSIZE, h = IEM_VU_STEPS*IEM_VU_DEFAULTSIZE;
Mathieu L Bouchard's avatar
Mathieu L Bouchard committed
582
    int ldx = -1, ldy = -8, fs = 10, scale = 1;
Miller Puckette's avatar
Miller Puckette committed
583

584
585
    iem_inttosymargs(&x->x_gui, 0);
    iem_inttofstyle(&x->x_gui, 0);
Miller Puckette's avatar
Miller Puckette committed
586
587
588
589
590
591
592
593

    if((argc >= 11)&&IS_A_FLOAT(argv,0)&&IS_A_FLOAT(argv,1)
       &&(IS_A_SYMBOL(argv,2)||IS_A_FLOAT(argv,2))
       &&(IS_A_SYMBOL(argv,3)||IS_A_FLOAT(argv,3))
       &&IS_A_FLOAT(argv,4)&&IS_A_FLOAT(argv,5)
       &&IS_A_FLOAT(argv,6)&&IS_A_FLOAT(argv,7)
       &&IS_A_FLOAT(argv,8)&&IS_A_FLOAT(argv,9)&&IS_A_FLOAT(argv,10))
    {
594
595
        w = atom_getintarg(0, argc, argv);
        h = atom_getintarg(1, argc, argv);
Miller Puckette's avatar
Miller Puckette committed
596
        iemgui_new_getnames(&x->x_gui, 1, argv);
597
598
        ldx = atom_getintarg(4, argc, argv);
        ldy = atom_getintarg(5, argc, argv);
599
        iem_inttofstyle(&x->x_gui, atom_getintarg(6, argc, argv));
600
601
602
603
        fs = maxi(atom_getintarg(7, argc, argv),4);
        bflcol[0] = atom_getintarg(8, argc, argv);
        bflcol[2] = atom_getintarg(9, argc, argv);
        scale = !!atom_getintarg(10, argc, argv);
Miller Puckette's avatar
Miller Puckette committed
604
605
606
    }
    else iemgui_new_getnames(&x->x_gui, 1, 0);
    if((argc == 12)&&IS_A_FLOAT(argv,11))
607
        iem_inttosymargs(&x->x_gui, atom_getintarg(11, argc, argv));
Miller Puckette's avatar
Miller Puckette committed
608
609
610
    x->x_gui.x_draw = (t_iemfunptr)vu_draw;

    x->x_gui.x_glist = (t_glist *)canvas_getcurrent();
611
612
    if (x->x_gui.x_font_style<0 || x->x_gui.x_font_style>2) x->x_gui.x_font_style=0;
    if(iemgui_has_rcv(&x->x_gui))
Miller Puckette's avatar
Miller Puckette committed
613
614
615
        pd_bind(&x->x_gui.x_obj.ob_pd, x->x_gui.x_rcv);
    x->x_gui.x_ldx = ldx;
    x->x_gui.x_ldy = ldy;
616
    x->x_gui.x_snd = s_empty;
Miller Puckette's avatar
Miller Puckette committed
617
618
619
620
621
622
623
624
625
626
627
628
629
    x->x_gui.x_fontsize = fs;
    x->x_gui.x_w = iemgui_clip_size(w);
    vu_check_height(x, h);
    iemgui_all_colfromload(&x->x_gui, bflcol);
    x->x_scale = scale;
    x->x_peak = 0;
    x->x_rms = 0;
    x->x_fp = -101.0;
    x->x_fr = -101.0;
    iemgui_verify_snd_ne_rcv(&x->x_gui);
    inlet_new(&x->x_gui.x_obj, &x->x_gui.x_obj.ob_pd, &s_float, gensym("ft1"));
    x->x_out_rms = outlet_new(&x->x_gui.x_obj, &s_float);
    x->x_out_peak = outlet_new(&x->x_gui.x_obj, &s_float);
630

631
632
    x->x_gui. x_handle = scalehandle_new(scalehandle_class,(t_iemgui *)x,1);
    x->x_gui.x_lhandle = scalehandle_new(scalehandle_class,(t_iemgui *)x,0);
633
    x->x_gui.x_obj.te_iemgui = 1;
634

Miller Puckette's avatar
Miller Puckette committed
635
636
637
638
639
    return (x);
}

static void vu_free(t_vu *x)
{
640
    if(iemgui_has_rcv(&x->x_gui))
Miller Puckette's avatar
Miller Puckette committed
641
642
        pd_unbind(&x->x_gui.x_obj.ob_pd, x->x_gui.x_rcv);
    gfxstub_deleteforkey(x);
643

644
645
    if (x->x_gui. x_handle) scalehandle_free(x->x_gui. x_handle);
    if (x->x_gui.x_lhandle) scalehandle_free(x->x_gui.x_lhandle);
Miller Puckette's avatar
Miller Puckette committed
646
647
648
649
650
}

void g_vumeter_setup(void)
{
    vu_class = class_new(gensym("vu"), (t_newmethod)vu_new, (t_method)vu_free,
651
        sizeof(t_vu), 0, A_GIMME, 0);
Miller Puckette's avatar
Miller Puckette committed
652
653
654
655
    class_addbang(vu_class,vu_bang);
    class_addfloat(vu_class,vu_float);
    class_addmethod(vu_class, (t_method)vu_ft1, gensym("ft1"), A_FLOAT, 0);
    class_addmethod(vu_class, (t_method)vu_dialog, gensym("dialog"),
656
        A_GIMME, 0);
Miller Puckette's avatar
Miller Puckette committed
657
    class_addmethod(vu_class, (t_method)vu_size, gensym("size"), A_GIMME, 0);
658
659
    class_addmethod(vu_class, (t_method)vu_scale,
        gensym("scale"), A_DEFFLOAT, 0);
660
    iemgui_class_addmethods(vu_class);
661
    scalehandle_class = class_new(gensym("_scalehandle"), 0, 0,
662
                  sizeof(t_scalehandle), CLASS_PD, 0);
663
    class_addmethod(scalehandle_class, (t_method)vu__clickhook,
664
            gensym("_click"), A_FLOAT, A_FLOAT, A_FLOAT, 0);
665
    class_addmethod(scalehandle_class, (t_method)vu__motionhook,
666
            gensym("_motion"), A_FLOAT, A_FLOAT, 0);
667

668
    wb_init(&vu_widgetbehavior,vu_getrect,0);
Miller Puckette's avatar
Miller Puckette committed
669
670
671
672
673
    class_setwidget(vu_class,&vu_widgetbehavior);
    class_sethelpsymbol(vu_class, gensym("vu"));
    class_setsavefn(vu_class, vu_save);
    class_setpropertiesfn(vu_class, vu_properties);
}