g_vumeter.c 23.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
64
extern int gfxstub_haveproperties(void *key);
void vu_check_height(t_vu *x, int h);
Miller Puckette's avatar
Miller Puckette committed
65
t_widgetbehavior vu_widgetbehavior;
66
t_class *vu_class;
Miller Puckette's avatar
Miller Puckette committed
67
68
69

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

77
78
        gui_vmess("gui_vumeter_update_rms", "xxiiiiii",
            glist_getcanvas(glist), x,
79
            quad1 + 1, off + 2, quad3 + 1, off + (x->x_led_size + 1) *
Jonathan Wilkes's avatar
Jonathan Wilkes committed
80
            (IEM_VU_STEPS - x->x_rms) + 2, x1, y1);
Miller Puckette's avatar
Miller Puckette committed
81
82
83
84
85
86
87
88
89
    }
}

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

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

94
        if (x->x_peak)
Miller Puckette's avatar
Miller Puckette committed
95
        {
96
            int i = iemgui_vu_col[x->x_peak];
97
            int j = y1 + (x->x_led_size + 1) * (IEM_VU_STEPS + 1 - x->x_peak)
98
                - (x->x_led_size + 1) / 2;
99
100
101
            sprintf(cbuf, "#%06x", iemgui_color_hex[i]);
            gui_vmess("gui_vumeter_update_peak", "xxsiiiiii",
                canvas, x, cbuf,
102
                x1 + 1, j + 2, x1 + x->x_gui.x_w + 2, j + 2, x1, y1);
Miller Puckette's avatar
Miller Puckette committed
103
104
105
        }
        else
        {
106
            int mid = x1 + x->x_gui.x_w / 2;
107
108
109
            sprintf(cbuf, "#%6.6x", x->x_gui.x_bcol);
            gui_vmess("gui_vumeter_update_peak", "xxsiiiiii",
                canvas, x, cbuf,
110
                mid+1, y1+22, mid+1, y1+22, x1, y1);
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
    char cbuf[8];
140
141
142
143
144

    /* vumeter is a special case because the base doesn't actually
       cover the entire bbox returned by vu_getrect.  Instead it is
       the bbox minus the width of the scale.  That means the call
       below is going to draw a base rectangle that is too wide... */
145
    iemgui_base_draw_new(&x->x_gui);
146

147
148
149
150
151
    /* ...as a quick and dirty bugfix, we just make another call
       and send the correct size */
    gui_vmess("gui_vumeter_border_size", "xxii",
        canvas, x, x->x_gui.x_w+2, x->x_gui.x_h+4);

152
153
154
    for(i = 1; i <= IEM_VU_STEPS+1; i++)
    {
        yyy = k4 + k1 * (k2-i);
155
        if((i&3)==1 && (x->x_scale))
Jonathan Wilkes's avatar
Jonathan Wilkes committed
156
        {
157
            sprintf(cbuf, "#%06x", x->x_gui.x_lcol);
Jonathan Wilkes's avatar
Jonathan Wilkes committed
158
            // not handling font size yet
159
            gui_vmess("gui_vumeter_draw_text", "xxsiisiiiis",
160
                canvas, x,
161
                cbuf, end+1, yyy+k3+2, iemgui_vu_scale_str[i/4],
162
                i, x1, y1 - 3,
Jonathan Wilkes's avatar
Jonathan Wilkes committed
163
164
                x->x_gui.x_fontsize,
                sys_fontweight);
Jonathan Wilkes's avatar
Jonathan Wilkes committed
165
        }
166
        led_col = iemgui_vu_col[i];
Jonathan Wilkes's avatar
Jonathan Wilkes committed
167
168
        if (i<=IEM_VU_STEPS)
        {
169
170
171
            sprintf(cbuf, "#%06x", iemgui_color_hex[led_col]);
            gui_vmess("gui_vumeter_create_steps", "xxsiiiiiiii",
                canvas, x, cbuf, quad1+1,
172
                yyy+2, quad3, yyy+2, x->x_led_size, x1, y1, i);
Jonathan Wilkes's avatar
Jonathan Wilkes committed
173
        }
174
    }
175
176
    sprintf(cbuf, "#%06x", x->x_gui.x_bcol);
    gui_vmess("gui_vumeter_draw_rect", "xxsiiiiii",
177
        canvas, x,
178
179
        cbuf, quad1+1, y1+1, quad3, y1+1 + k1*IEM_VU_STEPS, x1, y1);
    gui_vmess("gui_vumeter_draw_peak", "xxsiiiiiii",
180
        canvas, x,
181
        cbuf, mid+1, y1+12, mid+1, y1+12, x->x_led_size, x1, y1);
182
183
    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
184
185
186
187
188
}

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

191
192
193
194
195
    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;
196
    int k1=x->x_led_size+1, k2=IEM_VU_STEPS+1, k3=k1/2;
197
    int yyy, i, k4=y1-k3;
198

199
200
    iemgui_base_draw_move(&x->x_gui);

201
    gui_vmess("gui_vumeter_border_size", "xxii",
202
        canvas, x, x->x_gui.x_w+2, x->x_gui.x_h+4);
203
    for(i=1; i<=IEM_VU_STEPS; i++)
204
    {
205
        yyy = k4 + k1*(k2-i);
206
        gui_vmess("gui_vumeter_update_step_coords", "xxiiiiiii",
207
            canvas, x, i, quad1+1, yyy+2, quad3, yyy+2,
208
            x1, y1);
209
        //if(((i+2)&3) && (x->x_scale))
210
211
        if((i&3)==1 && (x->x_scale))
        {
212
213
            gui_vmess("gui_vumeter_text_coords", "xxiiiii",
                canvas, x, i,
214
215
                end+1, yyy+k3+2, x1, y1);
        }
Miller Puckette's avatar
Miller Puckette committed
216
217
218
    }
    if(x->x_scale)
    {
219
220
        i=IEM_VU_STEPS+1;
        yyy = k4 + k1*(k2-i);
221
222
        gui_vmess("gui_vumeter_text_coords", "xxiiiii",
            canvas, x, i,
223
            end+1, yyy+k3+2, x1, y1);
Miller Puckette's avatar
Miller Puckette committed
224
    }
225
226
    x->x_updaterms = x->x_updatepeak = 1;
    sys_queuegui(x, glist, vu_draw_update);
Miller Puckette's avatar
Miller Puckette committed
227
228
}

229
static void vu_draw_config(t_vu* x, t_glist* glist)
Miller Puckette's avatar
Miller Puckette committed
230
{
231
    int i;
Miller Puckette's avatar
Miller Puckette committed
232
    t_canvas *canvas=glist_getcanvas(glist);
233
234
    char cbuf[8];
    sprintf(cbuf, "#%6.6x", x->x_gui.x_lcol);
235
    for(i = 1; i <= IEM_VU_STEPS+1; i++)
236
    {
237
        if (i <= IEM_VU_STEPS)
238
        {
239
            gui_vmess("gui_vumeter_update_steps", "xxii",
240
                canvas, x, i, x->x_led_size);
241
242
243
244
245
246
        }
        //if((i&3)==1)
        if((i&3)==1)
        {
            int isselected = x->x_gui.x_selected == canvas &&
                x->x_gui.x_glist == canvas && x->x_scale;
247
            gui_vmess("gui_vumeter_update_text", "xxssixi",
248
                canvas, x, iemgui_vu_scale_str[i/4],
249
                iemgui_font(&x->x_gui), isselected, cbuf, i);
250
        }
251
    }
252
253
254
    sprintf(cbuf, "#%6.6x", x->x_gui.x_bcol);
    gui_vmess("gui_vumeter_update_rect", "xxs",
        canvas, x, cbuf);
255
    gui_vmess("gui_vumeter_update_peak_width", "xxi",
256
        canvas, x, x->x_led_size);
257
    iemgui_base_draw_config(&x->x_gui);
Miller Puckette's avatar
Miller Puckette committed
258
259
260
261
}

static void vu_draw_select(t_vu* x,t_glist* glist)
{
Jonathan Wilkes's avatar
Jonathan Wilkes committed
262
    /* Not needed anymore */
263
264
}

265
static void vu__clickhook(t_scalehandle *sh, int newstate)
266
{
267
    t_vu *x = (t_vu *)(sh->h_master);
268
    if (sh->h_scale)
Jonathan Wilkes's avatar
Jonathan Wilkes committed
269
    {
270
271
272
273
        sh->h_adjust_x = sh->h_offset_x -
            (((t_object *)x)->te_xpix + x->x_gui.x_w);
        sh->h_adjust_y = sh->h_offset_y -
            (((t_object *)x)->te_ypix + x->x_gui.x_h);
Jonathan Wilkes's avatar
Jonathan Wilkes committed
274
    }
275
276
277
    else
        scalehandle_click_label(sh);
    canvas_apply_setundo(x->x_gui.x_glist, (t_gobj *)x);
278
    sh->h_dragon = newstate;
279
280
}

Jonathan Wilkes's avatar
Jonathan Wilkes committed
281
static void vu__motionhook(t_scalehandle *sh, t_floatarg mouse_x, t_floatarg mouse_y)
282
{
Jonathan Wilkes's avatar
Jonathan Wilkes committed
283
    if (sh->h_scale)
284
    {
285
        t_vu *x = (t_vu *)(sh->h_master);
286
287
288
289
290
291
292
293
        int width = (sh->h_constrain == CURSOR_EDITMODE_RESIZE_Y) ?
            x->x_gui.x_w :
            (int)mouse_x - text_xpix(&x->x_gui.x_obj, x->x_gui.x_glist) -
                sh->h_adjust_x;
        int height = (sh->h_constrain == CURSOR_EDITMODE_RESIZE_X) ?
            x->x_gui.x_h :
            (int)mouse_y - text_ypix(&x->x_gui.x_obj, x->x_gui.x_glist) -
                sh->h_adjust_y;
Jonathan Wilkes's avatar
Jonathan Wilkes committed
294
295
296
297
298

        width = maxi(width, 8);

        sh->h_dragx = width - x->x_gui.x_w;

299
        scalehandle_drag_scale(sh);
300

Jonathan Wilkes's avatar
Jonathan Wilkes committed
301
        x->x_gui.x_w = width;
302
        vu_check_height(x, height);
Jonathan Wilkes's avatar
Jonathan Wilkes committed
303
304
305
306
307
308
309
310
311
312
        if (glist_isvisible(x->x_gui.x_glist))
        {
            /* draw_move doesn't seem to cut it for vu, so we
               just toggle visibility */
            //vu_draw_move(x, x->x_gui.x_glist);
            gobj_vis((t_gobj *)x, x->x_gui.x_glist, 0);
            gobj_vis((t_gobj *)x, x->x_gui.x_glist, 1);
            scalehandle_unclick_scale(sh);
        }

313
314
315
        int properties = gfxstub_haveproperties((void *)x);
        if (properties)
        {
Jonathan Wilkes's avatar
Jonathan Wilkes committed
316
            int new_w = width;
317
            int new_h = x->x_gui.x_h + sh->h_dragy;
318
319
            properties_set_field_int(properties,"width",new_w);
            properties_set_field_int(properties,"height",new_h);
320
        }
321
    }
322
    scalehandle_dragon_label(sh,mouse_x, mouse_y);
Miller Puckette's avatar
Miller Puckette committed
323
324
325
326
}

void vu_draw(t_vu *x, t_glist *glist, int mode)
{
327
328
329
330
331
    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
332
333
334
335
}

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

336
337
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)
338
{
339
340
341
342
343
344
345
346
347
348
349
    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))
    {
350
        switch(x_gui.x_font_style)
351
        {
352
353
354
            case 1:   width_multiplier = 0.83333; break;
            case 2:   width_multiplier = 0.735;   break;
            default:  width_multiplier = 1.0;     break;
355
        }
356
        actual_fontsize = x_gui.x_fontsize;
357
358
        actual_height = actual_fontsize;
        //exceptions
359
        if (x_gui.x_font_style == 0 &&
360
361
362
363
364
365
366
            (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;
        }
367
        else if (x_gui.x_font_style == 1 &&
368
369
370
371
372
373
            actual_fontsize >= 5 &&
            actual_fontsize < 13 &&
            actual_fontsize % 2 == 1)
        {
            actual_fontsize += 1;
        }
374
        else if (x_gui.x_font_style == 2 &&
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
            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;
    }
397
}
Miller Puckette's avatar
Miller Puckette committed
398
399

static void vu_getrect(t_gobj *z, t_glist *glist,
400
    int *xp1, int *yp1, int *xp2, int *yp2)
Miller Puckette's avatar
Miller Puckette committed
401
402
403
{
    t_vu* x = (t_vu*)z;

404
    int yyy, end;
405
406
407
    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;
408

409
    *xp1 = text_xpix(&x->x_gui.x_obj, glist);
410
    *yp1 = text_ypix(&x->x_gui.x_obj, glist);
411
    *xp2 = *xp1 + x->x_gui.x_w + 2;
412
    *yp2 = *yp1 + x->x_gui.x_h + 4;
413

414
    iemgui_label_getrect(x->x_gui, glist, xp1, yp1, xp2, yp2);
415

416
417
    /* In legacy mode we don't include the scale in the rect */
    if (x->x_scale && !sys_legacy)
418
419
    {
        //vu has custom scale all labels unlike other iemgui object
420
        end=x1+x->x_gui.x_w+4;
421
422
423
424
425
        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
426
427
428
429
430
}

static void vu_save(t_gobj *z, t_binbuf *b)
{
    t_vu *x = (t_vu *)z;
431
    t_symbol *bflcol[3];
Miller Puckette's avatar
Miller Puckette committed
432
433
    t_symbol *srl[3];
    iemgui_save(&x->x_gui, srl, bflcol);
434
    binbuf_addv(b, "ssiisiissiiiissii;", gensym("#X"),gensym("obj"),
435
436
437
438
439
440
        (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
441
442
443
444
}

void vu_check_height(t_vu *x, int h)
{
445
    int n = maxi(h / IEM_VU_STEPS, IEM_VU_MINSIZE);
Miller Puckette's avatar
Miller Puckette committed
446
447
448
449
450
451
452
    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;
453
    char cbuf[8];
Miller Puckette's avatar
Miller Puckette committed
454
455
456
457
458
459
460
461
462
463
464

    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++)
            {
465
466
467
                /* if((i+2)&3) */
                if((i&3)==1)
                {
468
                    gui_vmess("gui_vumeter_erase_text", "xxi",
469
                        canvas, x, i);
470
                }
Miller Puckette's avatar
Miller Puckette committed
471
472
            }
            i=IEM_VU_STEPS+1;
473
            gui_vmess("gui_vumeter_erase_text", "xxi",
474
                canvas, x, i);
Miller Puckette's avatar
Miller Puckette committed
475
476
477
478
        }
    }
    if(!x->x_scale && scale)
    {
Mathieu L Bouchard's avatar
Mathieu L Bouchard committed
479
        int end=text_xpix(&x->x_gui.x_obj,
480
            x->x_gui.x_glist)+x->x_gui.x_w+4;
Miller Puckette's avatar
Miller Puckette committed
481
482
483
484
485
486
487
        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))
        {
488
            sprintf(cbuf, "#%6.6x", x->x_gui.x_lcol);
Miller Puckette's avatar
Miller Puckette committed
489
490
491
            for(i=1; i<=IEM_VU_STEPS; i++)
            {
                yyy = k4 + k1*(k2-i);
492
                if((i&3)==1)
493
                {
494
                    gui_vmess("gui_vumeter_draw_text", "xxsiisiiiis",
495
                        canvas, x, cbuf,
496
                        end+1, yyy+k3+2, iemgui_vu_scale_str[i/4],
497
498
                        i, end, yyy, x->x_gui.x_fontsize,
                        sys_fontweight);
499
                }
Miller Puckette's avatar
Miller Puckette committed
500
            }
501
            i = IEM_VU_STEPS + 1;
Miller Puckette's avatar
Miller Puckette committed
502
            yyy = k4 + k1*(k2-i);
503
            gui_vmess("gui_vumeter_draw_text", "xxsiisiiiis",
504
                canvas, x, cbuf,
505
                end+1, yyy+k3+2, iemgui_vu_scale_str[i/4],
506
507
                i, end, yyy, x->x_gui.x_fontsize,
                sys_fontweight);
Miller Puckette's avatar
Miller Puckette committed
508
509
510
511
512
513
514
        }
    }
}

static void vu_properties(t_gobj *z, t_glist *owner)
{
    t_vu *x = (t_vu *)z;
515
    char buf[800], *gfx_tag;
Miller Puckette's avatar
Miller Puckette committed
516
517
518
    t_symbol *srl[3];

    iemgui_properties(&x->x_gui, srl);
Miller Puckette's avatar
Miller Puckette committed
519
    sprintf(buf, "pdtk_iemgui_dialog %%s |vu| \
520
521
522
523
524
525
526
527
528
529
530
531
        --------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);
532
533
534
535
536
537
538
539
540
541
542
543
544
    //gfxstub_new(&x->x_gui.x_obj.ob_pd, x, buf);
    gfx_tag = gfxstub_new2(&x->x_gui.x_obj.ob_pd, x);

    gui_start_vmess("gui_iemgui_dialog", "s", gfx_tag);

    gui_start_array();

    gui_s("type");
    gui_s("vu");

    gui_s("width"); gui_i(x->x_gui.x_w);
    gui_s("height"); gui_i(x->x_gui.x_h);
    
545
    gui_s("vu_scale"); gui_i(x->x_scale);
546

547
    gui_s("minimum_size"); gui_i(IEM_GUI_MINSIZE);
548
    
549
    gui_s("range_schedule"); // no idea what this is...
550
551
    gui_i(2);

552
    gui_s("receive_symbol");   gui_s(srl[1]->s_name);
553
    gui_s("label");            gui_s(srl[2]->s_name);
554
555
556
557
558
559
    gui_s("x_offset");         gui_i(x->x_gui.x_ldx);
    gui_s("y_offset");         gui_i(x->x_gui.x_ldy);
    gui_s("font_style");       gui_i(x->x_gui.x_font_style);
    gui_s("font_size");        gui_i(x->x_gui.x_fontsize);
    gui_s("background_color"); gui_i(0xffffff & x->x_gui.x_bcol);
    gui_s("label_color");      gui_i(0xffffff & x->x_gui.x_lcol);
560
561
562
    
    gui_end_array();
    gui_end_vmess();
Miller Puckette's avatar
Miller Puckette committed
563
564
565
566
}

static void vu_dialog(t_vu *x, t_symbol *s, int argc, t_atom *argv)
{
567
568
    if (atom_getintarg(19, argc, argv))
        canvas_apply_setundo(x->x_gui.x_glist, (t_gobj *)x);
569
570
    int w = atom_getintarg(0, argc, argv);
    int h = atom_getintarg(1, argc, argv);
571

572
    int scale = !!atom_getintarg(4, argc, argv);
Mathieu L Bouchard's avatar
Mathieu L Bouchard committed
573
    int sr_flags = iemgui_dialog(&x->x_gui, argc, argv);
574
    x->x_gui.x_loadinit = 0;
Miller Puckette's avatar
Miller Puckette committed
575
576
    x->x_gui.x_w = iemgui_clip_size(w);
    vu_check_height(x, h);
577
    vu_scale(x, (t_float)scale);
578
579
    iemgui_draw_config(&x->x_gui);
    iemgui_draw_io(&x->x_gui, sr_flags);
580
    iemgui_shouldvis(&x->x_gui, IEM_GUI_DRAW_MODE_MOVE);
581
    scalehandle_draw(&x->x_gui);
582
    scrollbar_update(x->x_gui.x_glist);
Miller Puckette's avatar
Miller Puckette committed
583
584
585
586
587
588
589
590
591
}

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))
    {
592
593
        iemgui_draw_move(&x->x_gui);
        iemgui_draw_config(&x->x_gui);
Miller Puckette's avatar
Miller Puckette committed
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
        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);
612
    rms = 0.01*(t_float)(i - 10000);
Miller Puckette's avatar
Miller Puckette committed
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
    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);
633
    peak = 0.01*(t_float)(i - 10000);
Miller Puckette's avatar
Miller Puckette committed
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
    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);
651
    int w = IEM_GUI_DEFAULTSIZE, h = IEM_VU_STEPS*IEM_VU_DEFAULTSIZE;
Mathieu L Bouchard's avatar
Mathieu L Bouchard committed
652
    int ldx = -1, ldy = -8, fs = 10, scale = 1;
Miller Puckette's avatar
Miller Puckette committed
653

654
655
    iem_inttosymargs(&x->x_gui, 0);
    iem_inttofstyle(&x->x_gui, 0);
Miller Puckette's avatar
Miller Puckette committed
656

657
658
659
660
    x->x_gui.x_bcol = 0x404040;
    x->x_gui.x_fcol = 0x00;
    x->x_gui.x_lcol = 0x00;

Miller Puckette's avatar
Miller Puckette committed
661
662
663
664
665
    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)
666
       &&IS_A_FLOAT(argv,10))
Miller Puckette's avatar
Miller Puckette committed
667
    {
668
669
        w = atom_getintarg(0, argc, argv);
        h = atom_getintarg(1, argc, argv);
Miller Puckette's avatar
Miller Puckette committed
670
        iemgui_new_getnames(&x->x_gui, 1, argv);
671
672
        ldx = atom_getintarg(4, argc, argv);
        ldy = atom_getintarg(5, argc, argv);
673
        iem_inttofstyle(&x->x_gui, atom_getintarg(6, argc, argv));
674
        fs = maxi(atom_getintarg(7, argc, argv),4);
675
        iemgui_all_loadcolors(&x->x_gui, argv+8, NULL, argv+9);
676
        scale = !!atom_getintarg(10, argc, argv);
Miller Puckette's avatar
Miller Puckette committed
677
678
679
    }
    else iemgui_new_getnames(&x->x_gui, 1, 0);
    if((argc == 12)&&IS_A_FLOAT(argv,11))
680
        iem_inttosymargs(&x->x_gui, atom_getintarg(11, argc, argv));
Miller Puckette's avatar
Miller Puckette committed
681
682
683
    x->x_gui.x_draw = (t_iemfunptr)vu_draw;

    x->x_gui.x_glist = (t_glist *)canvas_getcurrent();
684
685
    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
686
687
688
        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;
689
    x->x_gui.x_snd = s_empty;
Miller Puckette's avatar
Miller Puckette committed
690
691
692
693
694
695
696
697
    x->x_gui.x_fontsize = fs;
    x->x_gui.x_w = iemgui_clip_size(w);
    vu_check_height(x, h);
    x->x_scale = scale;
    x->x_peak = 0;
    x->x_rms = 0;
    x->x_fp = -101.0;
    x->x_fr = -101.0;
Mathieu L Bouchard's avatar
Mathieu L Bouchard committed
698
    iemgui_verify_snd_ne_rcv(&x->x_gui); // makes no sense, because snd is unused
Miller Puckette's avatar
Miller Puckette committed
699
700
701
    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);
702

703
    x->x_gui.x_handle = scalehandle_new((t_object *)x,x->x_gui.x_glist,1,vu__clickhook,vu__motionhook);
704
    x->x_gui.x_lhandle = scalehandle_new((t_object *)x,x->x_gui.x_glist,0,vu__clickhook,vu__motionhook);
705
    x->x_gui.x_obj.te_iemgui = 1;
706

707
    x->x_gui.legacy_x = -1;
708
    x->x_gui.legacy_y = -1;
709

Miller Puckette's avatar
Miller Puckette committed
710
711
712
713
714
    return (x);
}

static void vu_free(t_vu *x)
{
715
    if(iemgui_has_rcv(&x->x_gui))
Miller Puckette's avatar
Miller Puckette committed
716
717
        pd_unbind(&x->x_gui.x_obj.ob_pd, x->x_gui.x_rcv);
    gfxstub_deleteforkey(x);
718

719
720
    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
721
722
723
724
725
}

void g_vumeter_setup(void)
{
    vu_class = class_new(gensym("vu"), (t_newmethod)vu_new, (t_method)vu_free,
726
        sizeof(t_vu), 0, A_GIMME, 0);
Miller Puckette's avatar
Miller Puckette committed
727
728
729
730
    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"),
731
        A_GIMME, 0);
Miller Puckette's avatar
Miller Puckette committed
732
    class_addmethod(vu_class, (t_method)vu_size, gensym("size"), A_GIMME, 0);
733
734
    class_addmethod(vu_class, (t_method)vu_scale,
        gensym("scale"), A_DEFFLOAT, 0);
735
    iemgui_class_addmethods(vu_class);
736

737
    wb_init(&vu_widgetbehavior,vu_getrect,0);
Miller Puckette's avatar
Miller Puckette committed
738
739
740
741
742
    class_setwidget(vu_class,&vu_widgetbehavior);
    class_sethelpsymbol(vu_class, gensym("vu"));
    class_setsavefn(vu_class, vu_save);
    class_setpropertiesfn(vu_class, vu_properties);
}