~ubuntu-branches/ubuntu/hoary/jamin/hoary

« back to all changes in this revision

Viewing changes to src/hdeq.c

  • Committer: Bazaar Package Importer
  • Author(s): Robert Jordens
  • Date: 2004-01-17 12:14:37 UTC
  • Revision ID: james.westby@ubuntu.com-20040117121437-3idr2e2m3k5jnm9n
Tags: upstream-0.8.0
ImportĀ upstreamĀ versionĀ 0.8.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *  hdeq.c -- Hand drawn EQ, crossover, and compressor graph interface for
 
3
 *            the JAMin (JACK Audio Mastering interface) program.
 
4
 *
 
5
 *  Copyright (C) 2003 Jan C. Depner.
 
6
 *  
 
7
 *  This program is free software; you can redistribute it and/or modify
 
8
 *  it under the terms of the GNU General Public License as published by
 
9
 *  the Free Software Foundation; either version 2 of the License, or
 
10
 *  (at your option) any later version.
 
11
 *
 
12
 *  This program is distributed in the hope that it will be useful,
 
13
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
15
 *  GNU General Public License for more details.
 
16
 *
 
17
 *  You should have received a copy of the GNU General Public License
 
18
 *  along with this program; if not, write to the Free Software
 
19
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
20
 */
 
21
 
 
22
 
 
23
#include <stdio.h>
 
24
#include <stdlib.h>
 
25
#include <unistd.h>
 
26
#include <time.h>
 
27
#include <sys/times.h>
 
28
#include <errno.h>
 
29
#include <math.h>
 
30
#include <string.h>
 
31
#include <gtk/gtk.h>
 
32
 
 
33
 
 
34
#include "hdeq.h"
 
35
#include "main.h"
 
36
#include "callbacks.h"
 
37
#include "geq.h"
 
38
#include "interface.h"
 
39
#include "support.h"
 
40
#include "process.h"
 
41
#include "intrim.h"
 
42
#include "compressor-ui.h"
 
43
#include "gtkmeter.h"
 
44
#include "gtkmeterscale.h"
 
45
#include "state.h"
 
46
#include "db.h"
 
47
#include "transport.h"
 
48
#include "scenes.h"
 
49
 
 
50
 
 
51
#define NINT(a) ((a)<0.0 ? (int) ((a) - 0.5) : (int) ((a) + 0.5))
 
52
 
 
53
 
 
54
#define EQ_INTERP                     (BINS / 2 - 1)
 
55
#define EQ_SPECTRUM_RANGE             90.0
 
56
#define XOVER_HANDLE_SIZE             10
 
57
#define XOVER_HANDLE_HALF_SIZE        (XOVER_HANDLE_SIZE / 2)
 
58
#define NOTCH_HANDLE_HEIGHT           14
 
59
#define NOTCH_HANDLE_HALF_HEIGHT      (NOTCH_HANDLE_HEIGHT / 2)
 
60
#define NOTCH_HANDLE_WIDTH            6
 
61
#define NOTCH_HANDLE_HALF_WIDTH       (NOTCH_HANDLE_WIDTH / 2)
 
62
#define NOTCHES                       5
 
63
#define NOTCH_INT                     ((int) ((EQ_INTERP + 1) / (NOTCHES - 1)))
 
64
#define MOTION_CLOCK_DIFF             ((int) (sysconf (_SC_CLK_TCK) * 0.05))
 
65
 
 
66
 
 
67
void interpolate (float, int, float, float, int *, float *, float *, float *, 
 
68
                  float *);
 
69
static void draw_EQ_curve ();
 
70
 
 
71
 
 
72
/* vi:set ts=8 sts=4 sw=4: */
 
73
 
 
74
static GtkHScale       *l_low2mid, *l_mid2high;
 
75
static GtkWidget       *l_comp[3];
 
76
static GtkLabel        *l_low2mid_lbl, *l_mid2high_lbl, *l_comp_lbl[3], 
 
77
                       *l_EQ_curve_lbl, *l_c_curve_lbl[3];
 
78
static GtkDrawingArea  *l_EQ_curve, *l_comp_curve[3];
 
79
static GdkDrawable     *EQ_drawable, *comp_drawable[3];
 
80
static GdkColormap     *colormap = NULL;
 
81
static GdkColor        white, black, comp_color[4], EQ_back_color, 
 
82
                       EQ_fore_color, EQ_spectrum_color, EQ_grid_color, 
 
83
                       EQ_notch_color;
 
84
static GdkGC           *EQ_gc, *comp_gc[3];
 
85
static PangoContext    *comp_pc[3], *EQ_pc;
 
86
static GtkAdjustment   *l_low2mid_adj;
 
87
static float           EQ_curve_range_x, EQ_curve_range_y, EQ_curve_width,
 
88
                       EQ_curve_height, EQ_xinterp[EQ_INTERP + 1], EQ_start, 
 
89
                       EQ_end, EQ_interval, EQ_yinterp[EQ_INTERP + 1], 
 
90
                       *EQ_xinput = NULL, *EQ_yinput = NULL, 
 
91
                       l_geq_freqs[EQ_BANDS], l_geq_gains[EQ_BANDS], 
 
92
                       comp_curve_range_x[3], comp_curve_range_y[3], 
 
93
                       comp_curve_width[3], comp_curve_height[3] , 
 
94
                       comp_start_x[3], comp_start_y[3], comp_end_x[3], 
 
95
                       comp_end_y[3], EQ_freq_xinterp[EQ_INTERP + 1],
 
96
                       EQ_freq_yinterp[EQ_INTERP + 1], 
 
97
                       EQ_notch_gain[NOTCHES] = {0.0, 0.0, 0.0, 0.0, 0.0},
 
98
                       EQ_x_notched[EQ_INTERP + 1], 
 
99
                       EQ_y_notched[EQ_INTERP + 1], EQ_gain_lower = -12.0, 
 
100
                       EQ_gain_upper = 12.0;
 
101
static int             EQ_mod = 1, EQ_drawing = 0, EQ_input_points = 0, 
 
102
                       EQ_length = 0, comp_realized[3] = {0, 0, 0}, 
 
103
                       EQ_cleared = 1, EQ_realized = 0, xover_active = 0,
 
104
                       xover_handle_fa, xover_handle_fb, EQ_drag_fa = 0,
 
105
                       EQ_drag_fb = 0, EQ_partial = 0, part_x[2], part_y[2],
 
106
                       EQ_notch_drag[NOTCHES] = {0, 0, 0, 0, 0}, 
 
107
                       EQ_notch_Q_drag[NOTCHES] = {0, 0, 0, 0, 0},
 
108
                       EQ_notch_handle[2][3][NOTCHES], 
 
109
                       EQ_notch_width[NOTCHES] = {0, 5, 5, 5, 0},
 
110
                       EQ_notch_index[NOTCHES] = {20, NOTCH_INT, 2 * NOTCH_INT,
 
111
                       3 * NOTCH_INT, EQ_INTERP - 20}, 
 
112
                       EQ_notch_flag[NOTCHES] = {0, 0, 0, 0, 0};
 
113
static guint           notebook1_page = 0;
 
114
static gboolean        hdeq_ready = FALSE;
 
115
 
 
116
 
 
117
 
 
118
/*  Clear out the hand drawn EQ curves on exit.  */
 
119
 
 
120
void clean_quit ()
 
121
{
 
122
    if (EQ_xinput) free (EQ_xinput);
 
123
    if (EQ_yinput) free (EQ_yinput);
 
124
 
 
125
    gtk_main_quit();
 
126
}
 
127
 
 
128
 
 
129
/*  Generic color setting.  */
 
130
 
 
131
static void set_color (GdkColor *color, unsigned short red, 
 
132
                       unsigned short green, unsigned short blue)
 
133
{
 
134
    if (colormap == NULL) colormap = gdk_colormap_get_system ();
 
135
 
 
136
    color->red = red;
 
137
    color->green = green;
 
138
    color->blue = blue;
 
139
 
 
140
    gdk_colormap_alloc_color (colormap, color, FALSE, TRUE);
 
141
}
 
142
 
 
143
 
 
144
/*  Setup widget bindings based on names from glade-2.  DON'T CHANGE WIDGET
 
145
    NAMES in glade-2 without checking first.  */
 
146
 
 
147
void bind_hdeq ()
 
148
{
 
149
    l_low2mid = GTK_HSCALE (lookup_widget (main_window, "low2mid"));
 
150
    l_mid2high = GTK_HSCALE (lookup_widget (main_window, "mid2high"));
 
151
    l_low2mid_lbl = GTK_LABEL (lookup_widget (main_window, "low2mid_lbl"));
 
152
    l_mid2high_lbl = GTK_LABEL (lookup_widget (main_window, "mid2high_lbl"));
 
153
 
 
154
    l_comp[0] = lookup_widget (main_window, "frame_l");
 
155
    l_comp[1] = lookup_widget (main_window, "frame_m");
 
156
    l_comp[2] = lookup_widget (main_window, "frame_h");
 
157
 
 
158
    l_comp_lbl[0] = GTK_LABEL (lookup_widget (main_window, "label_freq_l"));
 
159
    l_comp_lbl[1] = GTK_LABEL (lookup_widget (main_window, "label_freq_m"));
 
160
    l_comp_lbl[2] = GTK_LABEL (lookup_widget (main_window, "label_freq_h"));
 
161
 
 
162
    l_EQ_curve = GTK_DRAWING_AREA (lookup_widget (main_window, "EQ_curve"));
 
163
    l_EQ_curve_lbl = GTK_LABEL (lookup_widget (main_window, "EQ_curve_lbl"));
 
164
 
 
165
    l_comp_curve[0] = GTK_DRAWING_AREA (lookup_widget (main_window, 
 
166
                                                       "comp1_curve"));
 
167
    l_comp_curve[1] = GTK_DRAWING_AREA (lookup_widget (main_window, 
 
168
                                                       "comp2_curve"));
 
169
    l_comp_curve[2] = GTK_DRAWING_AREA (lookup_widget (main_window, 
 
170
                                                       "comp3_curve"));
 
171
 
 
172
    l_c_curve_lbl[0] = GTK_LABEL (lookup_widget (main_window, 
 
173
                                                 "low_curve_lbl"));
 
174
    l_c_curve_lbl[1] = GTK_LABEL (lookup_widget (main_window, 
 
175
                                                 "mid_curve_lbl"));
 
176
    l_c_curve_lbl[2] = GTK_LABEL (lookup_widget (main_window, 
 
177
                                                 "high_curve_lbl"));
 
178
 
 
179
 
 
180
    set_color (&white, 65535, 65535, 65535);
 
181
    set_color (&black, 0, 0, 0);
 
182
    set_color (&EQ_notch_color, 65535, 65535, 0);
 
183
    set_color (&comp_color[0], 60000, 0, 0);
 
184
    set_color (&comp_color[1], 0, 50000, 0);
 
185
    set_color (&comp_color[2], 0, 0, 60000);
 
186
    set_color (&comp_color[3], 0, 0, 0);
 
187
    set_color (&EQ_back_color, 0, 21611, 0);
 
188
    set_color (&EQ_fore_color, 65535, 65535, 65535);
 
189
    set_color (&EQ_grid_color, 0, 36611, 0);
 
190
    set_color (&EQ_spectrum_color, 32768, 32768, 32768);
 
191
}
 
192
 
 
193
 
 
194
/*  Setting the low to mid crossover.  Called from callbacks.c.  */
 
195
 
 
196
void hdeq_low2mid_set (GtkRange *range)
 
197
{
 
198
    double          value, other_value, lvalue, mvalue, hvalue;
 
199
    char            label[6];
 
200
 
 
201
 
 
202
    value = gtk_range_get_value (range);
 
203
    other_value = gtk_range_get_value ((GtkRange *) l_mid2high);
 
204
    s_set_value_ui(S_XOVER_FREQ(0), value);
 
205
 
 
206
 
 
207
    /*  Don't let the two sliders cross each other and desensitize the mid
 
208
        band compressor if they are the same value.  */
 
209
 
 
210
    if (value >= other_value)
 
211
      {
 
212
        s_suppress_push();
 
213
        gtk_range_set_value ((GtkRange *) l_mid2high, value);
 
214
        s_suppress_pop();
 
215
        gtk_widget_set_sensitive (l_comp[1], FALSE);
 
216
      }
 
217
    else
 
218
      {
 
219
        gtk_widget_set_sensitive (l_comp[1], TRUE);
 
220
      }
 
221
 
 
222
 
 
223
    /*  If the low slider is at the bottom of it's range, desensitize the low 
 
224
        band compressor.  */
 
225
 
 
226
    l_low2mid_adj = gtk_range_get_adjustment (range);
 
227
 
 
228
    if (value == l_low2mid_adj->lower)
 
229
      {
 
230
        gtk_widget_set_sensitive (l_comp[0], FALSE);
 
231
      }
 
232
    else
 
233
      {
 
234
        gtk_widget_set_sensitive (l_comp[0], TRUE);
 
235
      }
 
236
 
 
237
 
 
238
    /*  Set the label using log scale.  */
 
239
 
 
240
    lvalue = pow (10.0, value);
 
241
    sprintf (label, "%05d", NINT (lvalue));
 
242
    gtk_label_set_label (l_low2mid_lbl, label);
 
243
 
 
244
 
 
245
    /* Write value into DSP code */
 
246
 
 
247
    xover_fa = lvalue;
 
248
 
 
249
 
 
250
    /*  Set the compressor labels.  */
 
251
 
 
252
    hvalue = pow (10.0, other_value);
 
253
    sprintf (label, _("Mid : %d - %d"), NINT (lvalue), NINT (hvalue));
 
254
    gtk_label_set_label (l_comp_lbl[1], label);
 
255
 
 
256
    lvalue = pow (10.0, l_low2mid_adj->lower);
 
257
    mvalue = pow (10.0, value);
 
258
    sprintf (label, _("Low : %d - %d"), NINT (lvalue), NINT (mvalue));
 
259
    gtk_label_set_label (l_comp_lbl[0], label);
 
260
 
 
261
    draw_EQ_curve ();
 
262
}
 
263
 
 
264
 
 
265
/*  Setting the mid to high crossover.  Called from callbacks.c.  */
 
266
 
 
267
void hdeq_mid2high_set (GtkRange *range)
 
268
{
 
269
    double          value, other_value, lvalue, mvalue, hvalue;
 
270
    char            label[6];
 
271
 
 
272
 
 
273
    value = gtk_range_get_value (range);
 
274
    other_value = gtk_range_get_value ((GtkRange *) l_low2mid);
 
275
    s_set_value_ui(S_XOVER_FREQ(1), value);
 
276
 
 
277
 
 
278
    /*  Don't let the two sliders cross each other and desensitize the mid
 
279
        band compressor if they are the same value.  */
 
280
 
 
281
    if (value <= other_value)
 
282
      {
 
283
        s_suppress_push();
 
284
        gtk_range_set_value ((GtkRange *) l_low2mid, value);
 
285
        s_suppress_pop();
 
286
        gtk_widget_set_sensitive (l_comp[1], FALSE);
 
287
      }
 
288
    else
 
289
      {
 
290
        gtk_widget_set_sensitive (l_comp[1], TRUE);
 
291
      }
 
292
 
 
293
 
 
294
    /*  If the slider is at the top of it's range, desensitize the high band
 
295
        compressor.  */
 
296
 
 
297
 
 
298
    if (value == l_low2mid_adj->upper)
 
299
      {
 
300
        gtk_widget_set_sensitive (l_comp[2], FALSE);
 
301
      }
 
302
    else
 
303
      {
 
304
        gtk_widget_set_sensitive (l_comp[2], TRUE);
 
305
      }
 
306
 
 
307
 
 
308
    /*  Set the label using log scale.  */
 
309
 
 
310
    mvalue = pow (10.0, value);
 
311
    sprintf (label, "%05d", NINT (mvalue));
 
312
    gtk_label_set_label (l_mid2high_lbl, label);
 
313
 
 
314
 
 
315
    /* Write value into DSP code */
 
316
 
 
317
    xover_fb = mvalue;
 
318
 
 
319
 
 
320
    /*  Set the compressor labels.  */
 
321
 
 
322
    lvalue = pow (10.0, other_value);
 
323
    sprintf (label, _("Mid : %d - %d"), NINT (lvalue), NINT (mvalue));
 
324
    gtk_label_set_label (l_comp_lbl[1], label);
 
325
 
 
326
    hvalue = pow (10.0, l_low2mid_adj->upper);
 
327
    sprintf (label, _("High : %d - %d"), NINT (mvalue), NINT (hvalue));
 
328
    gtk_label_set_label (l_comp_lbl[2], label);
 
329
 
 
330
    draw_EQ_curve ();
 
331
}
 
332
 
 
333
 
 
334
/*  Someone has pressed the low to mid crossover button.  Called from 
 
335
    callbacks.c.  */
 
336
 
 
337
void hdeq_low2mid_button (int active)
 
338
{
 
339
    xover_active = active;
 
340
}
 
341
 
 
342
 
 
343
/*  Someone has pressed the mid to high crossover button.  Called from 
 
344
    callbacks.c.  */
 
345
 
 
346
void hdeq_mid2high_button (int active)
 
347
{
 
348
    xover_active = active;
 
349
}
 
350
 
 
351
 
 
352
/*  Initialize the low to mid crossover adjustment state.  */
 
353
 
 
354
void hdeq_low2mid_init ()
 
355
{
 
356
    s_set_adjustment(S_XOVER_FREQ(0), gtk_range_get_adjustment(GTK_RANGE(l_low2mid)));
 
357
}
 
358
 
 
359
 
 
360
/*  Initialize the mid to high crossover adjustment state.  */
 
361
 
 
362
void hdeq_mid2high_init ()
 
363
{
 
364
    s_set_adjustment(S_XOVER_FREQ(1), gtk_range_get_adjustment(GTK_RANGE(l_mid2high)));
 
365
}
 
366
 
 
367
 
 
368
/*  Set the low to mid and mid to high crossovers.  This is from the 
 
369
    window1_show callback so it only gets called once.  */
 
370
 
 
371
void crossover_init ()
 
372
{
 
373
    hdeq_low2mid_set ((GtkRange *) l_low2mid);
 
374
    hdeq_mid2high_set ((GtkRange *) l_mid2high);
 
375
}
 
376
 
 
377
 
 
378
/*  If we've modified the graphic EQ (geq) then we want to build the hand
 
379
    drawn EQ from the geq.  This flag will cause that to happen on the next
 
380
    redraw.  */
 
381
 
 
382
void hdeq_eqb_mod ()
 
383
{
 
384
    EQ_mod = 1;
 
385
}
 
386
 
 
387
 
 
388
/*  Convert log frequency to X pixels in the hdeq.  */
 
389
 
 
390
static void
 
391
logfreq2xpix (float log_freq, int *x)
 
392
{
 
393
    *x = NINT (((log_freq - l_low2mid_adj->lower) / EQ_curve_range_x) * 
 
394
        EQ_curve_width);
 
395
}
 
396
 
 
397
 
 
398
/*  Convert frequency to X pixels in the hdeq.  */
 
399
 
 
400
static void 
 
401
freq2xpix (float freq, int *x)
 
402
{
 
403
    float log_freq;
 
404
 
 
405
    log_freq = log10f (freq);
 
406
    logfreq2xpix (log_freq, x);
 
407
}
 
408
 
 
409
 
 
410
/*  Convert gain to Y pixels in the hdeq.  */
 
411
 
 
412
static void 
 
413
gain2ypix (float gain, int *y)
 
414
{
 
415
    *y = EQ_curve_height - NINT (((gain - EQ_gain_lower) / 
 
416
                EQ_curve_range_y) * EQ_curve_height);
 
417
}
 
418
 
 
419
 
 
420
/*  Convert log gain to Y pixels in the hdeq.  */
 
421
 
 
422
static void
 
423
loggain2ypix (float log_gain, int *y)
 
424
{
 
425
    float gain;
 
426
 
 
427
    gain = log_gain * 20.0;
 
428
    gain2ypix (gain, y);
 
429
}
 
430
 
 
431
 
 
432
/*  Draw the spectrum in the hdeq window.  This is called from spectrum update
 
433
    which is called based on the timer set up in main.c.  */
 
434
 
 
435
void draw_EQ_spectrum_curve (float single_levels[])
 
436
{
 
437
    static int     x[EQ_INTERP], y[EQ_INTERP];
 
438
    int            i;
 
439
    float          step, range, freq;
 
440
 
 
441
 
 
442
    /*  Don't update if we're drawing an EQ curve.  */
 
443
 
 
444
    if (!EQ_drawing && !xover_active)
 
445
      {
 
446
        /*  Plot the curve.  */
 
447
 
 
448
        gdk_gc_set_foreground (EQ_gc, &EQ_spectrum_color);
 
449
        gdk_gc_set_function (EQ_gc, GDK_XOR);
 
450
        gdk_gc_set_line_attributes (EQ_gc, 1, GDK_LINE_SOLID, GDK_CAP_BUTT,
 
451
                                    GDK_JOIN_MITER);
 
452
 
 
453
 
 
454
        /*  If we've just cleared (redrawn) the curve, don't erase the previous
 
455
            line.  */
 
456
 
 
457
        if (EQ_partial || !EQ_cleared)
 
458
          {
 
459
            for (i = 1 ; i < EQ_INTERP ; i++)
 
460
              {
 
461
                if (!EQ_partial || x[i] < part_x[0] || x[i] > part_x[1] ||
 
462
                    y[i] < part_y[0] || y[i] > part_y[1])
 
463
                  {
 
464
                    gdk_draw_line (EQ_drawable, EQ_gc, x[i - 1], y[i - 1], 
 
465
                                   x[i], y[i]);
 
466
                  }
 
467
              }
 
468
          }
 
469
        EQ_partial = 0;
 
470
 
 
471
 
 
472
        /*  Convert the single levels to db, plot, and save the pixel positions
 
473
            so that we can erase them on the next pass.  */
 
474
 
 
475
        range = l_geq_freqs[EQ_BANDS - 1] - l_geq_freqs[0];
 
476
        step = range / (float) EQ_INTERP;
 
477
 
 
478
        for (i = 0 ; i < EQ_INTERP ; i++)
 
479
          {
 
480
            freq = l_geq_freqs[0] + (float) i * step;
 
481
 
 
482
 
 
483
            freq2xpix (freq, &x[i]);
 
484
 
 
485
 
 
486
            /*  Most of the single_level values will be in the -90.0db to 
 
487
                -20.0db range.  We're using -90.0db to 0.0db as our range.  */
 
488
 
 
489
            y[i] = NINT (-(lin2db(single_levels[i]) / EQ_SPECTRUM_RANGE) * 
 
490
                EQ_curve_height);
 
491
 
 
492
            if (i) gdk_draw_line (EQ_drawable, EQ_gc, x[i - 1], y[i - 1], 
 
493
                x[i], y[i]);
 
494
          }
 
495
 
 
496
        gdk_gc_set_line_attributes (EQ_gc, 1, GDK_LINE_SOLID, GDK_CAP_BUTT,
 
497
                                    GDK_JOIN_MITER);
 
498
        gdk_gc_set_foreground (EQ_gc, &black);
 
499
        gdk_gc_set_function (EQ_gc, GDK_COPY);
 
500
 
 
501
        EQ_cleared = 0;
 
502
      }
 
503
}
 
504
 
 
505
 
 
506
/*  Given the frequency this returns the nearest array index in the X direction
 
507
    in the hand drawn EQ curve.  This will be one of 1024 values.  */
 
508
 
 
509
static int nearest_x (float freq)
 
510
{
 
511
    int          i, j = 0;
 
512
    float        dist, ndist;
 
513
 
 
514
 
 
515
    dist = 99999999.0;
 
516
 
 
517
    for (i = 0 ; i < EQ_length ; i++)
 
518
      {
 
519
        ndist = log10f (freq);
 
520
        if (fabs (ndist - EQ_xinterp[i]) < dist)
 
521
          {
 
522
            dist = fabs (ndist - EQ_xinterp[i]);
 
523
            j = i;
 
524
          }
 
525
      }
 
526
 
 
527
  return (j);
 
528
}
 
529
 
 
530
 
 
531
/*  Set the graphic EQ (geq) sliders and the full set of EQ coefficients
 
532
    based on the hand drawn EQ curve.  */
 
533
 
 
534
static void set_EQ ()
 
535
{
 
536
    float    *x = NULL, *y = NULL, interval;
 
537
    int      i, size;
 
538
 
 
539
 
 
540
    /*  Make sure we have enough space.  */
 
541
 
 
542
    size = EQ_length * sizeof (float);
 
543
    x = (float *) realloc (x, size);
 
544
    y = (float *) realloc (y, size);
 
545
 
 
546
    if (y == NULL)
 
547
      {
 
548
        perror (_("Allocating y in callbacks.c"));
 
549
        clean_quit ();
 
550
      }
 
551
 
 
552
 
 
553
    /*  Recompute the splined curve in the freq domain for setting 
 
554
        the eq_coefs.  */
 
555
 
 
556
    for (i = 0 ; i < EQ_length ; i++)
 
557
        x[i] = pow (10.0, (double) EQ_x_notched[i]);
 
558
 
 
559
    interval = ((l_geq_freqs[EQ_BANDS - 1]) - l_geq_freqs[0]) / EQ_INTERP;
 
560
 
 
561
    interpolate (interval, EQ_length, l_geq_freqs[0], 
 
562
        l_geq_freqs[EQ_BANDS - 1], &EQ_length, x, EQ_y_notched, 
 
563
        EQ_freq_xinterp, EQ_freq_yinterp);
 
564
 
 
565
 
 
566
    if (x) free (x);
 
567
    if (y) free (y);
 
568
 
 
569
 
 
570
    /*  Set EQ coefficients based on the hand-drawn curve.  */
 
571
 
 
572
    geq_set_coefs (EQ_length, EQ_freq_xinterp, EQ_freq_yinterp);
 
573
 
 
574
 
 
575
    /*  Set the graphic EQ sliders based on the hand-drawn curve.  */
 
576
 
 
577
    geq_set_sliders (EQ_length, EQ_freq_xinterp, EQ_freq_yinterp);
 
578
 
 
579
    EQ_mod = 0;
 
580
}
 
581
 
 
582
 
 
583
/*  Place the sliding notch filters in the hand drawn EQ curve.  */
 
584
 
 
585
static void insert_notch ()
 
586
{
 
587
    int        i, j, ndx, left, right, length;
 
588
    float      x[5], y[5];
 
589
 
 
590
 
 
591
    for (i = 0 ; i < EQ_length ; i++)
 
592
      {
 
593
        EQ_x_notched[i] = EQ_xinterp[i];
 
594
        EQ_y_notched[i] = EQ_yinterp[i];
 
595
      }
 
596
 
 
597
 
 
598
    for (j = 0 ; j < NOTCHES ; j++)
 
599
      {
 
600
        if (EQ_notch_flag[j])
 
601
          {
 
602
            if (!j)
 
603
              {
 
604
                ndx = EQ_notch_index[j];
 
605
                for (i = 0 ; i < ndx - 10 ; i++)
 
606
                    EQ_y_notched[i] = EQ_notch_gain[j];
 
607
 
 
608
                x[0] = EQ_x_notched[ndx - 10];
 
609
                y[0] = EQ_notch_gain[j];
 
610
                x[1] = EQ_x_notched[ndx - 9];
 
611
                y[1] = EQ_notch_gain[j];
 
612
                x[2] = EQ_x_notched[ndx - 1];
 
613
                y[2] = EQ_y_notched[ndx - 1];
 
614
                x[3] = EQ_x_notched[ndx];
 
615
                y[3] = EQ_y_notched[ndx];
 
616
 
 
617
                interpolate (EQ_interval, 4, x[0], x[3], &length, x, 
 
618
                    y, &EQ_x_notched[ndx - 10], &EQ_y_notched[ndx - 10]);
 
619
              }
 
620
            else if (j == NOTCHES - 1)
 
621
              {
 
622
                ndx = EQ_notch_index[j];
 
623
                for (i = ndx + 10 ; i < EQ_length ; i++)
 
624
                    EQ_y_notched[i] = EQ_notch_gain[j];
 
625
 
 
626
                x[0] = EQ_x_notched[ndx];
 
627
                y[0] = EQ_y_notched[ndx];
 
628
                x[1] = EQ_x_notched[ndx + 1];
 
629
                y[1] = EQ_y_notched[ndx + 1];
 
630
                x[2] = EQ_x_notched[ndx + 9];
 
631
                y[2] = EQ_notch_gain[j];
 
632
                x[3] = EQ_x_notched[ndx + 10];
 
633
                y[3] = EQ_notch_gain[j];
 
634
 
 
635
                interpolate (EQ_interval, 4, x[0], x[3], &length, x, 
 
636
                    y, &EQ_x_notched[ndx], &EQ_y_notched[ndx]);
 
637
              }
 
638
            else
 
639
              {
 
640
                left = EQ_notch_index[j] - EQ_notch_width[j];
 
641
                right = EQ_notch_index[j] + EQ_notch_width[j];
 
642
 
 
643
                x[0] = EQ_x_notched[left];
 
644
                y[0] = EQ_y_notched[left];
 
645
                x[1] = EQ_x_notched[left + 1];
 
646
                y[1] = EQ_y_notched[left + 1];
 
647
                x[2] = EQ_x_notched[EQ_notch_index[j]];
 
648
                y[2] = EQ_notch_gain[j];
 
649
                x[3] = EQ_x_notched[right - 1];
 
650
                y[3] = EQ_y_notched[right - 1];
 
651
                x[4] = EQ_x_notched[right];
 
652
                y[4] = EQ_y_notched[right];
 
653
 
 
654
                interpolate (EQ_interval, 5, x[0], x[4], &length, x, 
 
655
                    y, &EQ_x_notched[left], &EQ_y_notched[left]);
 
656
              }
 
657
          }
 
658
      }
 
659
}
 
660
 
 
661
 
 
662
/*  Draw the EQ curve.  This may be from the graphic EQ sliders if they have
 
663
    been modified.  Usually from the hand drawn EQ though.  */
 
664
 
 
665
static void draw_EQ_curve ()
 
666
{
 
667
    int            i, x0 = 0, y0 = 0, x1, y1, inc;
 
668
    float          x[EQ_BANDS], y[EQ_BANDS];
 
669
 
 
670
 
 
671
    /*  If we're not visible, go away.  */
 
672
 
 
673
    if (!EQ_realized) return;
 
674
 
 
675
 
 
676
    /*  Clear the curve drawing area.  */
 
677
 
 
678
    EQ_cleared = 1;
 
679
    gdk_gc_set_foreground (EQ_gc, &EQ_back_color);
 
680
    gdk_draw_rectangle (EQ_drawable, EQ_gc, TRUE, 0, 0, EQ_curve_width + 1, 
 
681
        EQ_curve_height + 1);
 
682
 
 
683
 
 
684
    /*  Draw the grid lines.  */
 
685
 
 
686
    geq_get_freqs_and_gains (l_geq_freqs, l_geq_gains);
 
687
 
 
688
 
 
689
    gdk_gc_set_foreground (EQ_gc, &EQ_grid_color);
 
690
 
 
691
 
 
692
    /*  Box around the area.  */
 
693
 
 
694
    gdk_gc_set_line_attributes (EQ_gc, 2, GDK_LINE_SOLID, GDK_CAP_BUTT,
 
695
        GDK_JOIN_MITER);
 
696
    gdk_draw_line (EQ_drawable, EQ_gc, 1, 1, 1, EQ_curve_height);
 
697
    gdk_draw_line (EQ_drawable, EQ_gc, 1, EQ_curve_height, EQ_curve_width, 
 
698
                   EQ_curve_height);
 
699
    gdk_draw_line (EQ_drawable, EQ_gc, EQ_curve_width, EQ_curve_height, 
 
700
                   EQ_curve_width, 1);
 
701
    gdk_draw_line (EQ_drawable, EQ_gc, EQ_curve_width, 1, 1, 1);
 
702
 
 
703
 
 
704
    /*  Frequency lines on log scale in X.  */
 
705
 
 
706
    gdk_gc_set_line_attributes (EQ_gc, 1, GDK_LINE_SOLID, GDK_CAP_BUTT,
 
707
        GDK_JOIN_MITER);
 
708
    i = ((int) (l_geq_freqs[0] + 10.0) / 10) * 10;
 
709
    inc = 10;
 
710
    while (i < l_geq_freqs[EQ_BANDS - 1])
 
711
      {
 
712
        for (x0 = i ; x0 <= inc * 10 ; x0 += inc)
 
713
          {
 
714
            freq2xpix ((float) x0, &x1);
 
715
 
 
716
            gdk_draw_line (EQ_drawable, EQ_gc, x1, 0, x1, EQ_curve_height);
 
717
          }
 
718
        i = inc * 10;
 
719
        inc *= 10;
 
720
      } 
 
721
        
 
722
 
 
723
    /*  Gain lines in Y.  */
 
724
 
 
725
    inc = 10;
 
726
    if (EQ_curve_range_y < 10.0) inc = 1;
 
727
    for (i = NINT (EQ_gain_lower) ; i < NINT (EQ_gain_upper) ; i++)
 
728
      {
 
729
        if (!(i % inc))
 
730
          {
 
731
            gain2ypix ((float) i, &y1);
 
732
 
 
733
            gdk_draw_line (EQ_drawable, EQ_gc, 0, y1, EQ_curve_width, y1);
 
734
          }
 
735
      }
 
736
 
 
737
 
 
738
    /*  Add the crossover bars.  */
 
739
 
 
740
    gdk_gc_set_line_attributes (EQ_gc, 2, GDK_LINE_SOLID, GDK_CAP_BUTT,
 
741
        GDK_JOIN_MITER);
 
742
 
 
743
    gdk_gc_set_foreground (EQ_gc, &comp_color[0]);
 
744
    freq2xpix (xover_fa, &x1);
 
745
    gdk_draw_line (EQ_drawable, EQ_gc, x1, 0, x1, EQ_curve_height);
 
746
    gdk_draw_rectangle (EQ_drawable, EQ_gc, TRUE, x1 - XOVER_HANDLE_HALF_SIZE,
 
747
        0, XOVER_HANDLE_SIZE, XOVER_HANDLE_SIZE);
 
748
    gdk_draw_rectangle (EQ_drawable, EQ_gc, TRUE, x1 - XOVER_HANDLE_HALF_SIZE, 
 
749
        EQ_curve_height - XOVER_HANDLE_SIZE, XOVER_HANDLE_SIZE, 
 
750
        XOVER_HANDLE_SIZE);
 
751
    gdk_gc_set_foreground (EQ_gc, &black);
 
752
    gdk_draw_rectangle (EQ_drawable, EQ_gc, FALSE, x1 - XOVER_HANDLE_HALF_SIZE,
 
753
        0, XOVER_HANDLE_SIZE, XOVER_HANDLE_SIZE);
 
754
    gdk_draw_rectangle (EQ_drawable, EQ_gc, FALSE, x1 - XOVER_HANDLE_HALF_SIZE,
 
755
        EQ_curve_height - XOVER_HANDLE_SIZE, XOVER_HANDLE_SIZE, 
 
756
        XOVER_HANDLE_SIZE);
 
757
 
 
758
    xover_handle_fa = x1;
 
759
 
 
760
 
 
761
    gdk_gc_set_foreground (EQ_gc, &comp_color[2]);
 
762
    freq2xpix (xover_fb, &x1);
 
763
    gdk_draw_line (EQ_drawable, EQ_gc, x1, 0, x1, EQ_curve_height);
 
764
    gdk_draw_rectangle (EQ_drawable, EQ_gc, TRUE, x1 - XOVER_HANDLE_HALF_SIZE,
 
765
        0, XOVER_HANDLE_SIZE, XOVER_HANDLE_SIZE);
 
766
    gdk_draw_rectangle (EQ_drawable, EQ_gc, TRUE, x1 - XOVER_HANDLE_HALF_SIZE,
 
767
        EQ_curve_height - XOVER_HANDLE_SIZE, XOVER_HANDLE_SIZE, 
 
768
        XOVER_HANDLE_SIZE);
 
769
    gdk_gc_set_foreground (EQ_gc, &black);
 
770
    gdk_draw_rectangle (EQ_drawable, EQ_gc, FALSE, x1 - XOVER_HANDLE_HALF_SIZE,
 
771
        0, XOVER_HANDLE_SIZE, XOVER_HANDLE_SIZE);
 
772
    gdk_draw_rectangle (EQ_drawable, EQ_gc, FALSE, x1 - XOVER_HANDLE_HALF_SIZE,
 
773
        EQ_curve_height - XOVER_HANDLE_SIZE, XOVER_HANDLE_SIZE, 
 
774
        XOVER_HANDLE_SIZE);
 
775
 
 
776
    xover_handle_fb = x1;
 
777
 
 
778
    
 
779
    /*  If we've messed with the graphics EQ sliders, recompute the splined 
 
780
        curve.  */
 
781
 
 
782
    if (EQ_mod) 
 
783
      {
 
784
        for (i = 0 ; i < EQ_BANDS ; i++)
 
785
          {
 
786
            x[i] = log10 (l_geq_freqs[i]);
 
787
            y[i] = log10 (l_geq_gains[i]);
 
788
          }
 
789
 
 
790
 
 
791
        interpolate (EQ_interval, EQ_BANDS, EQ_start, EQ_end, 
 
792
            &EQ_length, x, y, EQ_xinterp, EQ_yinterp);
 
793
 
 
794
 
 
795
        /*  Save state of the EQ curve.  */
 
796
 
 
797
        s_set_value_block (EQ_yinterp, S_EQ_GAIN(0), EQ_length);
 
798
 
 
799
 
 
800
        /*  Reset all of the shelves/notches.  */
 
801
 
 
802
        for (i = 0 ; i < NOTCHES ; i++)
 
803
          {
 
804
            EQ_notch_flag[i] = 0;
 
805
            EQ_notch_gain[i] = 0.0;
 
806
 
 
807
            if (!i || i == NOTCHES - 1)
 
808
              {
 
809
                EQ_notch_width[i] = 0;
 
810
              }
 
811
            else
 
812
              {
 
813
                EQ_notch_width[i] = 5;
 
814
              }
 
815
 
 
816
            s_set_description (S_NOTCH_GAIN (i) ,
 
817
                               g_strdup_printf("Reset notch %d", i));
 
818
            s_set_value_ns (S_NOTCH_GAIN (i), EQ_notch_gain[i]);
 
819
            s_set_value_ns (S_NOTCH_Q (i), (float) EQ_notch_width[i]);
 
820
            s_set_value_ns (S_NOTCH_FLAG (i), (float) EQ_notch_flag[i]);
 
821
          }
 
822
 
 
823
        insert_notch ();
 
824
      }
 
825
 
 
826
 
 
827
    /*  Plot the curve.  */
 
828
 
 
829
    gdk_gc_set_foreground (EQ_gc, &EQ_fore_color);
 
830
    for (i = 0 ; i < EQ_length ; i++)
 
831
      {
 
832
        logfreq2xpix (EQ_x_notched[i], &x1);
 
833
        loggain2ypix (EQ_y_notched[i], &y1);
 
834
 
 
835
        if (i) gdk_draw_line (EQ_drawable, EQ_gc, x0, y0, x1, y1);
 
836
 
 
837
        x0 = x1;
 
838
        y0 = y1;
 
839
      }
 
840
 
 
841
 
 
842
    /*  Add the notch handles.  */
 
843
 
 
844
    for (i = 0 ; i < NOTCHES ; i++)
 
845
      {
 
846
        gdk_gc_set_foreground (EQ_gc, &EQ_notch_color);
 
847
 
 
848
        logfreq2xpix (EQ_x_notched[EQ_notch_index[i]], &x1);
 
849
 
 
850
 
 
851
        /*  Make the shelf handles follow the shelf.  */
 
852
 
 
853
        if (EQ_notch_flag[i] && (!i || i == NOTCHES - 1))
 
854
          {
 
855
            loggain2ypix (EQ_notch_gain[i], &y1);
 
856
          }
 
857
        else
 
858
          {
 
859
            loggain2ypix (EQ_y_notched[EQ_notch_index[i]], &y1);
 
860
          }
 
861
 
 
862
        gdk_draw_rectangle (EQ_drawable, EQ_gc, TRUE, 
 
863
            x1 - NOTCH_HANDLE_HALF_WIDTH, y1 - NOTCH_HANDLE_HALF_HEIGHT, 
 
864
            NOTCH_HANDLE_WIDTH, NOTCH_HANDLE_HEIGHT);
 
865
        gdk_gc_set_foreground (EQ_gc, &black);
 
866
        gdk_draw_rectangle (EQ_drawable, EQ_gc, FALSE, 
 
867
            x1 - NOTCH_HANDLE_HALF_WIDTH, y1 - NOTCH_HANDLE_HALF_HEIGHT, 
 
868
            NOTCH_HANDLE_WIDTH, NOTCH_HANDLE_HEIGHT);
 
869
 
 
870
        EQ_notch_handle[0][0][i] = EQ_notch_handle[0][1][i] = 
 
871
            EQ_notch_handle[0][2][i]= x1;
 
872
        EQ_notch_handle[1][1][i] = y1;
 
873
 
 
874
        if (!i)
 
875
          {
 
876
            EQ_notch_handle[0][0][i] = 0;
 
877
          }
 
878
        else
 
879
          {
 
880
            EQ_notch_handle[0][2][i] = EQ_curve_width;
 
881
          }
 
882
 
 
883
 
 
884
        /*  Notch handles, not shelf.  */
 
885
 
 
886
        if (i && i < NOTCHES - 1)
 
887
          {
 
888
            gdk_gc_set_foreground (EQ_gc, &EQ_notch_color);
 
889
 
 
890
            x0 = EQ_notch_index[i] - EQ_notch_width[i];
 
891
 
 
892
            logfreq2xpix (EQ_x_notched[x0], &x1);
 
893
            loggain2ypix (EQ_y_notched[x0], &y1);
 
894
 
 
895
            if (EQ_notch_handle[0][1][i] - x1 < NOTCH_HANDLE_HALF_WIDTH) 
 
896
                x1 = EQ_notch_handle[0][1][i] - NOTCH_HANDLE_WIDTH;
 
897
 
 
898
            gdk_draw_arc (EQ_drawable, EQ_gc, TRUE, 
 
899
                x1 - NOTCH_HANDLE_WIDTH, y1 - NOTCH_HANDLE_HALF_HEIGHT, 
 
900
                NOTCH_HANDLE_WIDTH * 2, NOTCH_HANDLE_HEIGHT, 5760, 11520);
 
901
            gdk_gc_set_foreground (EQ_gc, &black);
 
902
            gdk_draw_arc (EQ_drawable, EQ_gc, FALSE, 
 
903
                x1 - NOTCH_HANDLE_WIDTH, y1 - NOTCH_HANDLE_HALF_HEIGHT, 
 
904
                NOTCH_HANDLE_WIDTH * 2, NOTCH_HANDLE_HEIGHT, 5760, 11520);
 
905
 
 
906
            EQ_notch_handle[0][0][i] = x1;
 
907
            EQ_notch_handle[1][0][i] = y1;
 
908
 
 
909
 
 
910
            gdk_gc_set_foreground (EQ_gc, &EQ_notch_color);
 
911
 
 
912
            x0 = EQ_notch_index[i] + EQ_notch_width[i];
 
913
 
 
914
            logfreq2xpix (EQ_x_notched[x0], &x1);
 
915
            loggain2ypix (EQ_y_notched[x0], &y1);
 
916
 
 
917
            if (x1 - EQ_notch_handle[0][1][i] < NOTCH_HANDLE_HALF_WIDTH) 
 
918
                x1 = EQ_notch_handle[0][1][i] + NOTCH_HANDLE_WIDTH;
 
919
 
 
920
            gdk_draw_arc (EQ_drawable, EQ_gc, TRUE, 
 
921
                x1 - NOTCH_HANDLE_WIDTH, y1 - NOTCH_HANDLE_HALF_HEIGHT, 
 
922
                NOTCH_HANDLE_WIDTH * 2, NOTCH_HANDLE_HEIGHT, 17280, 11520);
 
923
            gdk_gc_set_foreground (EQ_gc, &black);
 
924
            gdk_draw_arc (EQ_drawable, EQ_gc, FALSE, 
 
925
                x1 - NOTCH_HANDLE_WIDTH, y1 - NOTCH_HANDLE_HALF_HEIGHT, 
 
926
                NOTCH_HANDLE_WIDTH * 2, NOTCH_HANDLE_HEIGHT, 17280, 11520);
 
927
 
 
928
            EQ_notch_handle[0][2][i] = x1;
 
929
            EQ_notch_handle[1][2][i] = y1;
 
930
          }
 
931
      }
 
932
 
 
933
    gdk_gc_set_line_attributes (EQ_gc, 1, GDK_LINE_SOLID, GDK_CAP_BUTT,
 
934
        GDK_JOIN_MITER);
 
935
 
 
936
 
 
937
    EQ_mod = 0;
 
938
}
 
939
 
 
940
 
 
941
/*  Whenever the curve is exposed, which will happen on a resize, we need to
 
942
    get the current dimensions and redraw the curve.  */
 
943
 
 
944
void hdeq_curve_exposed (GtkWidget *widget, GdkEventExpose *event)
 
945
{
 
946
    l_low2mid_adj = gtk_range_get_adjustment ((GtkRange *) l_low2mid);
 
947
    EQ_curve_range_x = l_low2mid_adj->upper - l_low2mid_adj->lower;
 
948
 
 
949
    EQ_curve_range_y = EQ_gain_upper - EQ_gain_lower;
 
950
 
 
951
 
 
952
    /*  Since allocation width and height are inclusive we need to decrement
 
953
        for calculations.  */
 
954
 
 
955
    EQ_curve_width = widget->allocation.width - 1;
 
956
    EQ_curve_height = widget->allocation.height - 1;
 
957
 
 
958
 
 
959
    /*  If we only get part of the window exposed we don't want to redraw the
 
960
        entire spectrum.  */
 
961
 
 
962
    if (event->area.height != widget->allocation.height ||
 
963
        event->area.width != widget->allocation.width ||
 
964
        event->area.x != widget->allocation.x ||
 
965
        event->area.y != widget->allocation.y) EQ_partial = 1;
 
966
 
 
967
    part_x[0] = event->area.x;
 
968
    part_y[0] = event->area.y;
 
969
    part_x[1] = part_x[0] + event->area.width;
 
970
    part_y[1] = part_y[0] + event->area.height;
 
971
 
 
972
    draw_EQ_curve ();
 
973
 
 
974
    hdeq_ready = TRUE;
 
975
}
 
976
 
 
977
 
 
978
/*  Initialize the hdeq.  This comes from the realize callback for the hdeq
 
979
    drawing area.  Called from callbacks.c.  */
 
980
 
 
981
void hdeq_curve_init (GtkWidget *widget)
 
982
{
 
983
    EQ_drawable = widget->window;
 
984
 
 
985
    EQ_gc = widget->style->fg_gc[GTK_WIDGET_STATE (widget)];
 
986
 
 
987
    EQ_pc = gtk_widget_get_pango_context (widget);
 
988
 
 
989
    geq_get_freqs_and_gains (l_geq_freqs, l_geq_gains);
 
990
 
 
991
    EQ_start = log10 (l_geq_freqs[0]);
 
992
    EQ_end = log10 (l_geq_freqs[EQ_BANDS - 1]);
 
993
    EQ_interval = (EQ_end - EQ_start) / EQ_INTERP;
 
994
 
 
995
    s_set_callback(S_NOTCH_GAIN(0), set_EQ_curve_values);
 
996
 
 
997
    EQ_realized = 1;
 
998
}
 
999
 
 
1000
 
 
1001
/*  Don't let the notches overlap.  */
 
1002
 
 
1003
static int check_notch (int notch, int new, int q)
 
1004
{
 
1005
    int         j, k, left, right, width, ret;
 
1006
 
 
1007
 
 
1008
    ret = 1;
 
1009
 
 
1010
 
 
1011
    /*  Left shelf.  */
 
1012
 
 
1013
    if (!notch)
 
1014
      {
 
1015
        j = EQ_notch_index[notch + 1] - EQ_notch_width[notch + 1];
 
1016
        if (new >= j || new < 10) ret = 0;
 
1017
      }
 
1018
 
 
1019
 
 
1020
    /*  Right shelf.  */
 
1021
 
 
1022
    else if (notch == NOTCHES - 1)
 
1023
      {
 
1024
        k = EQ_notch_index[notch - 1] + EQ_notch_width[notch - 1];
 
1025
        if (new <= k || new > EQ_length - 10) ret = 0;
 
1026
      }
 
1027
 
 
1028
 
 
1029
    /*  Notches.  */
 
1030
 
 
1031
    else
 
1032
      {
 
1033
        j = EQ_notch_index[notch - 1] + EQ_notch_width[notch - 1];
 
1034
        k = EQ_notch_index[notch + 1] - EQ_notch_width[notch + 1];
 
1035
        if (q == 1)
 
1036
          {
 
1037
            left = new;
 
1038
            width = EQ_notch_index[notch] - left;
 
1039
            right = left + 2 * width;
 
1040
 
 
1041
            if (EQ_notch_index[notch] - left < 5) ret = 0;
 
1042
          }
 
1043
        else if (q == 2)
 
1044
          {
 
1045
            right = new;
 
1046
            width = right - EQ_notch_index[notch];
 
1047
            left = right - 2 * width;
 
1048
 
 
1049
            if (right - EQ_notch_index[notch] < 5) ret = 0;
 
1050
          }
 
1051
        else
 
1052
          {
 
1053
            left = new - EQ_notch_width[notch];
 
1054
            right = new + EQ_notch_width[notch];
 
1055
          }
 
1056
        if (left <= j || right >= k) ret = 0;
 
1057
      }
 
1058
 
 
1059
    return (ret);
 
1060
}
 
1061
 
 
1062
 
 
1063
/*  This comes from the hdeq drawing area motion callback (actually the event
 
1064
    box).  There are about a million things going on here.  This is basically
 
1065
    the engine for the hdeq interface.  The rest of it happens in the button
 
1066
    press and release handlers.  Take a look at the comments in the function 
 
1067
    to see what's actually happening.  */
 
1068
 
 
1069
void hdeq_curve_motion (GdkEventMotion *event)
 
1070
{
 
1071
    static int     prev_x = -1, prev_y = -1, current_cursor = -1;
 
1072
    int            i, j, x, y, size, diffx_fa, diffx_fb, diff_notch[2], 
 
1073
                   cursor, drag, notch_flag = -1, lo, hi, clock_diff;
 
1074
    float          freq, gain, s_gain;
 
1075
    char           coords[20];
 
1076
    clock_t        new_clock;
 
1077
    static clock_t old_clock = -1;
 
1078
    struct tms     buf;
 
1079
 
 
1080
 
 
1081
    /*  We don't want motion events until the window is ready. */
 
1082
 
 
1083
    if (!hdeq_ready) return;
 
1084
 
 
1085
 
 
1086
    /*  Timing delay so we don't get five bazillion calls.  */
 
1087
 
 
1088
    new_clock = times (&buf);
 
1089
    clock_diff = abs (new_clock - old_clock);
 
1090
 
 
1091
    if (clock_diff < MOTION_CLOCK_DIFF) return;
 
1092
 
 
1093
    old_clock = new_clock;
 
1094
 
 
1095
 
 
1096
    x = NINT (event->x);
 
1097
    y = NINT (event->y);
 
1098
    drag = 0;
 
1099
 
 
1100
 
 
1101
    /*  We only want to update things if we've actually moved the cursor.  */
 
1102
 
 
1103
    if (x != prev_x || y != prev_y)
 
1104
      {
 
1105
        freq = pow (10.0, (l_low2mid_adj->lower + (((double) x / 
 
1106
            (double) EQ_curve_width) * EQ_curve_range_x)));
 
1107
 
 
1108
 
 
1109
        gain = ((((double) EQ_curve_height - (double) y) / 
 
1110
            (double) EQ_curve_height) * EQ_curve_range_y) + 
 
1111
            EQ_gain_lower;
 
1112
 
 
1113
        s_gain = -(EQ_SPECTRUM_RANGE - (((((double) EQ_curve_height - 
 
1114
            (double) y) / (double) EQ_curve_height) * EQ_SPECTRUM_RANGE)));
 
1115
 
 
1116
        sprintf (coords, _("%dHz , EQ : %ddb , Spectrum : %ddb"), NINT (freq),
 
1117
            NINT (gain), NINT (s_gain));
 
1118
        gtk_label_set_text (l_EQ_curve_lbl, coords);
 
1119
 
 
1120
 
 
1121
        /*  If we're in the midst of drawing the curve...  */
 
1122
 
 
1123
        if (EQ_drawing)
 
1124
          {
 
1125
            /*  Only allow the user to draw in the positive direction.  */
 
1126
 
 
1127
            if (!EQ_input_points || x > EQ_xinput[EQ_input_points - 1])
 
1128
              {
 
1129
                gdk_gc_set_foreground (EQ_gc, &EQ_fore_color);
 
1130
                if (EQ_input_points) gdk_draw_line (EQ_drawable, EQ_gc, 
 
1131
                    NINT (EQ_xinput[EQ_input_points - 1]), 
 
1132
                    NINT (EQ_yinput[EQ_input_points - 1]), x, y);
 
1133
 
 
1134
                size = (EQ_input_points + 1) * sizeof (float);
 
1135
                EQ_xinput = (float *) realloc (EQ_xinput, size);
 
1136
                EQ_yinput = (float *) realloc (EQ_yinput, size);
 
1137
 
 
1138
                if (EQ_yinput == NULL)
 
1139
                  {
 
1140
                    perror (_("Allocating EQ_yinput in callbacks.c"));
 
1141
                    clean_quit ();
 
1142
                  }
 
1143
 
 
1144
                EQ_xinput[EQ_input_points] = (float) x;
 
1145
                EQ_yinput[EQ_input_points] = (float) y;
 
1146
                EQ_input_points++;
 
1147
              }
 
1148
          }
 
1149
        else if (EQ_drag_fa)
 
1150
          {
 
1151
            freq = log10f (freq);
 
1152
            gtk_range_set_value ((GtkRange *) l_low2mid, freq);
 
1153
          }
 
1154
        else if (EQ_drag_fb)
 
1155
          {
 
1156
            freq = log10f (freq);
 
1157
            gtk_range_set_value ((GtkRange *) l_mid2high, freq);
 
1158
          }
 
1159
        else
 
1160
          {
 
1161
            notch_flag = -1;
 
1162
 
 
1163
 
 
1164
            /*  Check for notch drag.  */
 
1165
 
 
1166
            for (i = 0 ; i < NOTCHES ; i++)
 
1167
              {
 
1168
                if (EQ_notch_drag[i])
 
1169
                  {
 
1170
                    /*  If we're shifted we're raising or lowering notch 
 
1171
                        gain only.  */
 
1172
 
 
1173
                    if (event->state & GDK_SHIFT_MASK)
 
1174
                      {
 
1175
                        if (y >= 0 && y <= EQ_curve_height)
 
1176
                          {
 
1177
                            EQ_notch_gain[i] = (((((double) EQ_curve_height - 
 
1178
                                (double) y) / (double) EQ_curve_height) * 
 
1179
                                EQ_curve_range_y) + EQ_gain_lower) * 0.05;
 
1180
 
 
1181
                            drag = 1;
 
1182
                            notch_flag = i;
 
1183
                            EQ_notch_flag[i] = 1;
 
1184
 
 
1185
                            s_set_description (S_NOTCH_GAIN (i) ,
 
1186
                               g_strdup_printf("Move notch %d", i));
 
1187
                            s_set_value_ns (S_NOTCH_GAIN (i), 
 
1188
                                EQ_notch_gain[i]);
 
1189
                            s_set_value_ns (S_NOTCH_FLAG (i), 
 
1190
                                (float) EQ_notch_flag[i]);
 
1191
 
 
1192
                            break;
 
1193
                          }
 
1194
                      }
 
1195
                    else
 
1196
                      {
 
1197
                        if (x >= 0 && x <= EQ_curve_width && y >= 0 && 
 
1198
                            y <= EQ_curve_height)
 
1199
                          {
 
1200
                            j = nearest_x (freq);
 
1201
                            if (check_notch (i, j, 0))
 
1202
                              {
 
1203
                                EQ_notch_index[i] = nearest_x (freq);
 
1204
 
 
1205
                                EQ_notch_gain[i] = 
 
1206
                                    (((((double) EQ_curve_height - 
 
1207
                                    (double) y) / (double) EQ_curve_height) * 
 
1208
                                    EQ_curve_range_y) + EQ_gain_lower) * 
 
1209
                                    0.05;
 
1210
                                EQ_notch_flag[i] = 1;
 
1211
 
 
1212
                                drag = 1;
 
1213
                                notch_flag = i;
 
1214
 
 
1215
                                s_set_description (S_NOTCH_GAIN (i) ,
 
1216
                                    g_strdup_printf("Move notch %d", i));
 
1217
                                s_set_value_ns (S_NOTCH_GAIN (i), 
 
1218
                                    EQ_notch_gain[i]);
 
1219
                                s_set_value_ns (S_NOTCH_FREQ (i), freq);
 
1220
                                s_set_value_ns (S_NOTCH_FLAG (i), 
 
1221
                                    (float) EQ_notch_flag[i]);
 
1222
                              }
 
1223
                            break;
 
1224
                          }
 
1225
                      }
 
1226
                  }
 
1227
 
 
1228
 
 
1229
                /*  Dragging the Q/width handles for the notch filters.  */
 
1230
 
 
1231
                if (EQ_notch_Q_drag[i])
 
1232
                  {
 
1233
                    if (x >= 0 && x <= EQ_curve_width)
 
1234
                      {
 
1235
                        j = nearest_x (freq);
 
1236
                        if (check_notch (i, j, EQ_notch_Q_drag[i]))
 
1237
                          {
 
1238
                            /*  Left bracket is 1, right bracket is 2.  */
 
1239
 
 
1240
                            if (EQ_notch_Q_drag[i] == 1)
 
1241
                              {
 
1242
                                EQ_notch_width[i] = EQ_notch_index[i] - j;
 
1243
                              }
 
1244
                            else
 
1245
                              {
 
1246
                                EQ_notch_width[i] = j - EQ_notch_index[i];
 
1247
                              }
 
1248
 
 
1249
                            drag = 1;
 
1250
                            notch_flag = i;
 
1251
 
 
1252
                            s_set_description (S_NOTCH_GAIN (i) ,
 
1253
                               g_strdup_printf("Move notch %d", i));
 
1254
                            s_set_value_ns (S_NOTCH_GAIN (i), 
 
1255
                                    EQ_notch_gain[i]);
 
1256
                            s_set_value_ns (S_NOTCH_Q (i), 
 
1257
                                (float) EQ_notch_width[i]);
 
1258
                          }
 
1259
                        break;
 
1260
                      }
 
1261
                  }
 
1262
              }
 
1263
 
 
1264
 
 
1265
            /*  If we're dragging a notch filter...  */
 
1266
 
 
1267
            if (drag)
 
1268
              {
 
1269
                insert_notch ();
 
1270
                set_EQ ();
 
1271
                draw_EQ_curve ();
 
1272
              }
 
1273
            else
 
1274
              {
 
1275
                /*  If we pass over any of the handles we want to change the
 
1276
                    cursor.  */
 
1277
 
 
1278
                cursor = GDK_PENCIL;
 
1279
 
 
1280
                if (EQ_drag_fa || EQ_drag_fb) cursor = GDK_SB_H_DOUBLE_ARROW;
 
1281
 
 
1282
                diffx_fa = abs (x - xover_handle_fa);
 
1283
                diffx_fb = abs (x - xover_handle_fb);
 
1284
 
 
1285
                if ((diffx_fa <= XOVER_HANDLE_HALF_SIZE ||
 
1286
                    diffx_fb <= XOVER_HANDLE_HALF_SIZE) &&
 
1287
                    (y <= XOVER_HANDLE_SIZE ||
 
1288
                    y >= EQ_curve_height - XOVER_HANDLE_SIZE)) 
 
1289
                    cursor = GDK_SB_H_DOUBLE_ARROW;
 
1290
 
 
1291
 
 
1292
                /*  No point in checking all these if we're already passing 
 
1293
                    over one of the xover bars.  */
 
1294
 
 
1295
                if (cursor != GDK_SB_H_DOUBLE_ARROW)
 
1296
                  {
 
1297
                    for (i = 0 ; i < NOTCHES ; i++)
 
1298
                      {
 
1299
 
 
1300
                        if (EQ_notch_drag[i] || EQ_notch_Q_drag[i])
 
1301
                          {
 
1302
                            if (event->state & GDK_SHIFT_MASK)
 
1303
                              {
 
1304
                                cursor = GDK_SB_V_DOUBLE_ARROW;
 
1305
                              }
 
1306
                            else
 
1307
                              {
 
1308
                                if (EQ_notch_drag[i])
 
1309
                                  {
 
1310
                                    cursor = GDK_CROSS;
 
1311
                                  }
 
1312
                                else
 
1313
                                  {
 
1314
                                    cursor = GDK_SB_H_DOUBLE_ARROW;
 
1315
                                  }
 
1316
                              }
 
1317
                            notch_flag = i;
 
1318
                            break;
 
1319
                          }
 
1320
 
 
1321
                        diff_notch[0] = abs (x - EQ_notch_handle[0][1][i]);
 
1322
                        diff_notch[1] = abs (y - EQ_notch_handle[1][1][i]);
 
1323
 
 
1324
                        if (diff_notch[0] <= NOTCH_HANDLE_HALF_WIDTH &&
 
1325
                            diff_notch[1] <= NOTCH_HANDLE_HALF_HEIGHT)
 
1326
                          {
 
1327
                            if (event->state & GDK_SHIFT_MASK)
 
1328
                              {
 
1329
                                cursor = GDK_SB_V_DOUBLE_ARROW;
 
1330
                              }
 
1331
                            else
 
1332
                              {
 
1333
                                cursor = GDK_CROSS;
 
1334
                              }
 
1335
                            notch_flag = i;
 
1336
                            break;
 
1337
                          }
 
1338
 
 
1339
                        if (i && i < NOTCHES - 1)
 
1340
                          {
 
1341
                            diff_notch[0] = abs (x - EQ_notch_handle[0][0][i]);
 
1342
                            diff_notch[1] = abs (y - EQ_notch_handle[1][0][i]);
 
1343
 
 
1344
                            if (diff_notch[0] <= NOTCH_HANDLE_HALF_WIDTH &&
 
1345
                                diff_notch[1] <= NOTCH_HANDLE_HALF_HEIGHT)
 
1346
                              {
 
1347
                                cursor = GDK_SB_H_DOUBLE_ARROW;
 
1348
                                notch_flag = i;
 
1349
                                break;
 
1350
                              }
 
1351
 
 
1352
 
 
1353
                            diff_notch[0] = abs (x - EQ_notch_handle[0][2][i]);
 
1354
                            diff_notch[1] = abs (y - EQ_notch_handle[1][2][i]);
 
1355
 
 
1356
                            if (diff_notch[0] <= NOTCH_HANDLE_HALF_WIDTH &&
 
1357
                                diff_notch[1] <= NOTCH_HANDLE_HALF_HEIGHT)
 
1358
                              {
 
1359
                                cursor = GDK_SB_H_DOUBLE_ARROW;
 
1360
                                notch_flag = i;
 
1361
                                break;
 
1362
                              }
 
1363
                          }
 
1364
                      }
 
1365
                  }
 
1366
 
 
1367
 
 
1368
                if (current_cursor != cursor)
 
1369
                  {
 
1370
                    current_cursor = cursor;
 
1371
                    gdk_window_set_cursor (EQ_drawable, 
 
1372
                        gdk_cursor_new (cursor));
 
1373
                  }
 
1374
              }
 
1375
 
 
1376
 
 
1377
            if (notch_flag != -1)
 
1378
              {
 
1379
                i = EQ_notch_index[notch_flag] - EQ_notch_width[notch_flag];
 
1380
                if (i < 0 || notch_flag == 0) i = 0;
 
1381
                j = EQ_notch_index[notch_flag] + EQ_notch_width[notch_flag];
 
1382
                if (j >= EQ_length || notch_flag == NOTCHES - 1) 
 
1383
                    j = EQ_length - 1;
 
1384
                lo = NINT (pow (10.0, EQ_xinterp[i]));
 
1385
                hi = NINT (pow (10.0, EQ_xinterp[j]));
 
1386
 
 
1387
                sprintf (coords, _("%ddb , %dHz - %dHz"), NINT (gain), lo, 
 
1388
                    hi);
 
1389
                gtk_label_set_text (l_EQ_curve_lbl, coords);
 
1390
              }
 
1391
          }
 
1392
 
 
1393
 
 
1394
        prev_x = x;
 
1395
        prev_y = y;
 
1396
 
 
1397
      }
 
1398
}
 
1399
 
 
1400
 
 
1401
/*  This comes from the hdeq drawing area button press callback (actually the 
 
1402
    event box).  Again, many things happening here depending on the location
 
1403
    of the cursor when the button is pressed.  Take a look at the comments in 
 
1404
    the function to see what's actually happening.  */
 
1405
 
 
1406
void hdeq_curve_button_press (GdkEventButton *event)
 
1407
{
 
1408
    float               *x = NULL, *y = NULL;
 
1409
    int                 diffx_fa, diffx_fb, diff_notch[2], i, j, i_start = 0, 
 
1410
                        i_end = 0, size, ex, ey;
 
1411
    static int          interp_pad = 5;
 
1412
 
 
1413
 
 
1414
    ex = event->x;
 
1415
    ey = event->y;
 
1416
 
 
1417
    switch (event->button)
 
1418
      {
 
1419
 
 
1420
        /*  Button 1 - start drawing or end drawing unless we're over a notch
 
1421
            or xover handle in which case we will be grabbing and sliding the
 
1422
            handle in the X direction.  <Shift> button 1 is for grabbing and 
 
1423
            sliding in the Y direction (notch/shelf filters only - look at the
 
1424
            motion callback).  <Ctrl> button 1 will reset shelf and notch
 
1425
            values to 0.0.  */
 
1426
 
 
1427
      case 1:
 
1428
 
 
1429
        /*  Start drawing.  */
 
1430
 
 
1431
        if (!EQ_drawing)
 
1432
          {
 
1433
            /*  Checking for position over xover bar or notch handles.  */
 
1434
 
 
1435
            diffx_fa = abs (ex - xover_handle_fa);
 
1436
            diffx_fb = abs (ex - xover_handle_fb);
 
1437
            if (diffx_fa <= XOVER_HANDLE_HALF_SIZE && 
 
1438
                (ey <= XOVER_HANDLE_SIZE ||
 
1439
                ey >= EQ_curve_height - XOVER_HANDLE_SIZE))
 
1440
              {
 
1441
                EQ_drag_fa = 1;
 
1442
                xover_active = 1;
 
1443
              }
 
1444
            else if (diffx_fb <= XOVER_HANDLE_HALF_SIZE && 
 
1445
                (ey <= XOVER_HANDLE_SIZE || 
 
1446
                ey >= EQ_curve_height - XOVER_HANDLE_SIZE))
 
1447
              {
 
1448
                EQ_drag_fb = 1;
 
1449
                xover_active = 1;
 
1450
              }
 
1451
            else
 
1452
              {
 
1453
                for (i = 0 ; i < NOTCHES ; i++)
 
1454
                  {
 
1455
                    diff_notch[0] = abs (ex - EQ_notch_handle[0][1][i]);
 
1456
                    diff_notch[1] = abs (ey - EQ_notch_handle[1][1][i]);
 
1457
 
 
1458
                    if (diff_notch[0] <= NOTCH_HANDLE_HALF_WIDTH &&
 
1459
                        diff_notch[1] <= NOTCH_HANDLE_HALF_HEIGHT)
 
1460
                      {
 
1461
                        /*  Reset if <Ctrl> is pressed.  */
 
1462
 
 
1463
                        xover_active = 1;
 
1464
                        if (event->state & GDK_CONTROL_MASK)
 
1465
                          {
 
1466
                            EQ_notch_flag[i] = 0;
 
1467
                            EQ_notch_gain[i] = 0.0;
 
1468
 
 
1469
                            if (!i || i == NOTCHES - 1)
 
1470
                              {
 
1471
                                EQ_notch_width[i] = 0;
 
1472
                              }
 
1473
                            else
 
1474
                              {
 
1475
                                EQ_notch_width[i] = 5;
 
1476
                              }
 
1477
 
 
1478
                            s_set_description (S_NOTCH_GAIN (i) ,
 
1479
                               g_strdup_printf("Reset notch %d", i));
 
1480
                            s_set_value_ns (S_NOTCH_GAIN (i), 
 
1481
                                EQ_notch_gain[i]);
 
1482
                            s_set_value_ns (S_NOTCH_Q (i), 
 
1483
                                (float) EQ_notch_width[i]);
 
1484
                            s_set_value_ns (S_NOTCH_FLAG (i), 
 
1485
                                (float) EQ_notch_flag[i]);
 
1486
 
 
1487
                            insert_notch ();
 
1488
                            set_EQ ();
 
1489
                            draw_EQ_curve ();
 
1490
                          }
 
1491
                        else
 
1492
                          {
 
1493
                            EQ_notch_drag[i] = 1;
 
1494
                          }
 
1495
                        break;
 
1496
                      }
 
1497
 
 
1498
 
 
1499
                    if (i && i < NOTCHES - 1)
 
1500
                      {
 
1501
                        diff_notch[0] = abs (ex - EQ_notch_handle[0][0][i]);
 
1502
                        diff_notch[1] = abs (ey - EQ_notch_handle[1][0][i]);
 
1503
 
 
1504
                        if (diff_notch[0] <= NOTCH_HANDLE_HALF_WIDTH &&
 
1505
                            diff_notch[1] <= NOTCH_HANDLE_HALF_HEIGHT)
 
1506
                          {
 
1507
                            /*  Left bracket is a 1.  */
 
1508
 
 
1509
                            EQ_notch_Q_drag[i] = 1;
 
1510
                            xover_active = 1;
 
1511
 
 
1512
                            break;
 
1513
                          }
 
1514
 
 
1515
 
 
1516
                        diff_notch[0] = abs (ex - EQ_notch_handle[0][2][i]);
 
1517
                        diff_notch[1] = abs (ey - EQ_notch_handle[1][2][i]);
 
1518
 
 
1519
                        if (diff_notch[0] <= NOTCH_HANDLE_HALF_WIDTH &&
 
1520
                            diff_notch[1] <= NOTCH_HANDLE_HALF_HEIGHT)
 
1521
                          {
 
1522
                            /*  Right bracket is a 2.  */
 
1523
 
 
1524
                            EQ_notch_Q_drag[i] = 2;
 
1525
                            xover_active = 1;
 
1526
 
 
1527
                            break;
 
1528
                          }
 
1529
                      }
 
1530
                  }
 
1531
 
 
1532
 
 
1533
                /*  If we aren't over a handle we must be starting to draw 
 
1534
                    the curve so mark the starting point.  */
 
1535
 
 
1536
                if (!xover_active)
 
1537
                  {
 
1538
                    /*  Save the first point so we can do real narrow EQ 
 
1539
                        changes.  */
 
1540
 
 
1541
                    size = (EQ_input_points + 1) * sizeof (float);
 
1542
                    EQ_xinput = (float *) realloc (EQ_xinput, size);
 
1543
                    EQ_yinput = (float *) realloc (EQ_yinput, size);
 
1544
 
 
1545
                    if (EQ_yinput == NULL)
 
1546
                      {
 
1547
                        perror (_("Allocating EQ_yinput in callbacks.c"));
 
1548
                        clean_quit ();
 
1549
                      }
 
1550
 
 
1551
                    EQ_xinput[EQ_input_points] = (float) ex;
 
1552
                    EQ_yinput[EQ_input_points] = (float) ey;
 
1553
                    EQ_input_points++;
 
1554
 
 
1555
                    EQ_drawing = 1;
 
1556
                  }
 
1557
              }
 
1558
          }
 
1559
 
 
1560
 
 
1561
        /*  End drawing - combine the drawn data with any parts of the 
 
1562
            previous that haven't been superceded by what was drawn.  Use 
 
1563
            an "interp_pad" cushion on either side of the drawn section 
 
1564
            so it will merge nicely with the old data.  */
 
1565
 
 
1566
        else
 
1567
          {
 
1568
            /*  Convert the x and y input positions to "real" values.  */
 
1569
 
 
1570
            for (i = 0 ; i < EQ_input_points ; i++)
 
1571
              {
 
1572
                EQ_xinput[i] = l_low2mid_adj->lower + (((double) EQ_xinput[i] /
 
1573
                    (double) EQ_curve_width) * EQ_curve_range_x);
 
1574
 
 
1575
 
 
1576
                EQ_yinput[i] = (((((double) EQ_curve_height - 
 
1577
                    (double) EQ_yinput[i]) / (double) EQ_curve_height) * 
 
1578
                    EQ_curve_range_y) + EQ_gain_lower) * 0.05;
 
1579
              }
 
1580
 
 
1581
 
 
1582
            /*  Merge the drawn section with the old curve.  */
 
1583
 
 
1584
            for (i = 0 ; i < EQ_length ; i++)
 
1585
              {
 
1586
                if (EQ_xinterp[i] >= EQ_xinput[0])
 
1587
                  {
 
1588
                    i_start = i - interp_pad;
 
1589
                    break;
 
1590
                  }
 
1591
              }
 
1592
 
 
1593
            for (i = EQ_length - 1 ; i >= 0 ; i--)
 
1594
              {
 
1595
                if (EQ_xinterp[i] <= EQ_xinput[EQ_input_points - 1])
 
1596
                  {
 
1597
                    i_end = i + interp_pad;
 
1598
                    break;
 
1599
                  }
 
1600
              }
 
1601
 
 
1602
 
 
1603
            j = 0;
 
1604
            for (i = 0 ; i < i_start ; i++)
 
1605
              {
 
1606
                size = (j + 1) * sizeof (float);
 
1607
                x = (float *) realloc (x, size);
 
1608
                y = (float *) realloc (y, size);
 
1609
 
 
1610
                if (y == NULL)
 
1611
                  {
 
1612
                    perror (_("Allocating y in callbacks.c"));
 
1613
                    clean_quit ();
 
1614
                  }
 
1615
 
 
1616
                x[j] = EQ_xinterp[i];
 
1617
                y[j] = EQ_yinterp[i];
 
1618
                j++;
 
1619
              }
 
1620
 
 
1621
            for (i = 0 ; i < EQ_input_points ; i++)
 
1622
              {
 
1623
                size = (j + 1) * sizeof (float);
 
1624
                x = (float *) realloc (x, size);
 
1625
                y = (float *) realloc (y, size);
 
1626
 
 
1627
                if (y == NULL)
 
1628
                  {
 
1629
                    perror (_("Allocating y in callbacks.c"));
 
1630
                    clean_quit ();
 
1631
                  }
 
1632
 
 
1633
                x[j] = EQ_xinput[i];
 
1634
                y[j] = EQ_yinput[i];
 
1635
                j++;
 
1636
              }
 
1637
 
 
1638
            for (i = i_end ; i < EQ_length ; i++)
 
1639
              {
 
1640
                size = (j + 1) * sizeof (float);
 
1641
                x = (float *) realloc (x, size);
 
1642
                y = (float *) realloc (y, size);
 
1643
 
 
1644
                x[j] = EQ_xinterp[i];
 
1645
                y[j] = EQ_yinterp[i];
 
1646
                j++;
 
1647
              }
 
1648
 
 
1649
 
 
1650
            /*  Recompute the splined curve in the log(freq) domain for
 
1651
                plotting the EQ.  */
 
1652
 
 
1653
            interpolate (EQ_interval, j, EQ_start, EQ_end, &EQ_length, x, 
 
1654
                y, EQ_xinterp, EQ_yinterp);
 
1655
 
 
1656
 
 
1657
            if (x) free (x);
 
1658
            if (y) free (y);
 
1659
 
 
1660
 
 
1661
            /*  Save state of the EQ curve.  */
 
1662
 
 
1663
            s_set_value_block (EQ_yinterp, S_EQ_GAIN(0), EQ_length);
 
1664
 
 
1665
 
 
1666
            EQ_input_points = 0;
 
1667
 
 
1668
 
 
1669
            /*  Replace shelf and notch areas.  */
 
1670
 
 
1671
            insert_notch ();
 
1672
 
 
1673
 
 
1674
            /*  Set the GEQ faders and the EQ coefs.  */
 
1675
 
 
1676
            set_EQ ();
 
1677
 
 
1678
 
 
1679
            EQ_mod = 0;
 
1680
 
 
1681
 
 
1682
            /*  Redraw the curve.  */
 
1683
 
 
1684
            draw_EQ_curve ();
 
1685
          }
 
1686
        break;
 
1687
 
 
1688
 
 
1689
      default:
 
1690
        break;
 
1691
      }
 
1692
}
 
1693
 
 
1694
 
 
1695
/*  This comes from the hdeq drawing area button release callback (actually 
 
1696
    the event box).  Not as much going on here.  Mostly just resetting
 
1697
    whatever was done in the motion and button press functions.  */
 
1698
 
 
1699
void hdeq_curve_button_release (GdkEventButton  *event)
 
1700
{
 
1701
    int           i;
 
1702
 
 
1703
 
 
1704
    switch (event->button)
 
1705
      {
 
1706
      case 1:
 
1707
        if (EQ_drawing == 1)
 
1708
          {
 
1709
            EQ_drawing = 2;
 
1710
          }
 
1711
        else if (EQ_drawing == 2)
 
1712
          {
 
1713
            EQ_drawing = 0;
 
1714
          }
 
1715
 
 
1716
 
 
1717
        /*  Set the graphic EQ sliders based on the hand-drawn curve.  */
 
1718
 
 
1719
        geq_set_sliders (EQ_length, EQ_freq_xinterp, EQ_freq_yinterp);
 
1720
 
 
1721
        EQ_mod = 0;
 
1722
 
 
1723
        break;
 
1724
 
 
1725
 
 
1726
        /*  Button 2 or 3 - discard the drawn curve.  */
 
1727
 
 
1728
      case 2:
 
1729
      case 3:
 
1730
        EQ_drawing = 0;
 
1731
 
 
1732
        EQ_input_points = 0;
 
1733
 
 
1734
        draw_EQ_curve ();
 
1735
        
 
1736
        break;
 
1737
      }
 
1738
 
 
1739
 
 
1740
    xover_active = 0;
 
1741
    EQ_drag_fa = 0;
 
1742
    EQ_drag_fb = 0;
 
1743
    for (i = 0 ; i < NOTCHES ; i++) 
 
1744
      {
 
1745
        EQ_notch_drag[i] = 0;
 
1746
        EQ_notch_Q_drag[i] = 0;
 
1747
      }
 
1748
 
 
1749
 
 
1750
    set_scene_warning_button ();
 
1751
}
 
1752
 
 
1753
 
 
1754
/*  Set the label in the hdeq.  */
 
1755
 
 
1756
void hdeq_curve_set_label (char *string)
 
1757
{
 
1758
    gtk_label_set_text (l_EQ_curve_lbl, string);
 
1759
}
 
1760
 
 
1761
 
 
1762
/*  Gets the gain values from the state functions and sets up everything.  */
 
1763
 
 
1764
void set_EQ_curve_values (int id, float value)
 
1765
{
 
1766
    int i;
 
1767
 
 
1768
 
 
1769
    for (i = 0 ; i < EQ_INTERP ; i++)
 
1770
      {
 
1771
        EQ_yinterp[i] = s_get_value (S_EQ_GAIN (0) + i);
 
1772
      }
 
1773
 
 
1774
 
 
1775
    for (i = 0 ; i < NOTCHES ; i++)
 
1776
      {
 
1777
        EQ_notch_flag[i] = NINT (s_get_value (S_NOTCH_FLAG (i)));
 
1778
        if (EQ_notch_flag[i])
 
1779
          {
 
1780
            EQ_notch_width[i] = NINT (s_get_value (S_NOTCH_Q (i)));
 
1781
            EQ_notch_index[i] = nearest_x (s_get_value (S_NOTCH_FREQ (i)));
 
1782
            EQ_notch_gain[i] = s_get_value (S_NOTCH_GAIN (i));
 
1783
          }
 
1784
      }
 
1785
 
 
1786
 
 
1787
    /*  Replace shelf and notch areas.  */
 
1788
 
 
1789
    insert_notch ();
 
1790
 
 
1791
 
 
1792
    /*  Set the GEQ coefs and faders.  */
 
1793
 
 
1794
    set_EQ ();
 
1795
 
 
1796
 
 
1797
    EQ_mod = 0;
 
1798
 
 
1799
 
 
1800
    /*  Redraw the curve.  */
 
1801
 
 
1802
    draw_EQ_curve ();
 
1803
}
 
1804
 
 
1805
 
 
1806
/*  Reset the crossovers.  */
 
1807
 
 
1808
void hdeq_set_xover ()
 
1809
{
 
1810
    xover_fa = pow (10.0, s_get_value (S_XOVER_FREQ(0)));
 
1811
    xover_fb = pow (10.0, s_get_value (S_XOVER_FREQ(1)));
 
1812
    
 
1813
    hdeq_low2mid_init ();
 
1814
    hdeq_mid2high_init ();
 
1815
}
 
1816
 
 
1817
 
 
1818
/*  Set the lower gain limit for the hdeq and the geq.  */
 
1819
 
 
1820
void hdeq_set_lower_gain (float gain)
 
1821
{
 
1822
  EQ_gain_lower = gain;
 
1823
 
 
1824
  set_scene_warning_button ();
 
1825
}
 
1826
 
 
1827
 
 
1828
/*  Set the upper gain limit for the hdeq and the geq.  */
 
1829
 
 
1830
void hdeq_set_upper_gain (float gain)
 
1831
{
 
1832
  EQ_gain_upper = gain;
 
1833
 
 
1834
  set_scene_warning_button ();
 
1835
}
 
1836
 
 
1837
 
 
1838
/*  Write the annotation for the compressor curves when you move the cursor in
 
1839
    the curve box.  */
 
1840
 
 
1841
static void comp_write_annotation (int i, char *string)
 
1842
{
 
1843
    PangoLayout    *pl;
 
1844
    PangoRectangle ink_rect;
 
1845
 
 
1846
 
 
1847
    /*  Clear the annotation area.  */
 
1848
 
 
1849
    pl = pango_layout_new (comp_pc[i]);  
 
1850
    pango_layout_set_text (pl, "-99 , -99", -1);
 
1851
    pango_layout_get_pixel_extents (pl, &ink_rect, NULL);
 
1852
 
 
1853
    gdk_window_clear_area (comp_drawable[i], 3, 3, ink_rect.width + 5,
 
1854
                    ink_rect.height + 5);
 
1855
    gdk_gc_set_foreground (comp_gc[i], &black);
 
1856
 
 
1857
    pl = pango_layout_new (comp_pc[i]);  
 
1858
    pango_layout_set_text (pl, string, -1);
 
1859
 
 
1860
 
 
1861
    gdk_draw_layout (comp_drawable[i], comp_gc[i], 5, 5, pl);
 
1862
}
 
1863
 
 
1864
 
 
1865
/*  Draw the compressor curve (0-2).  */
 
1866
 
 
1867
void draw_comp_curve (int i)
 
1868
{
 
1869
    int              j, x0, y0 = 0.0, x1 = 0.0, y1 = 0.0;
 
1870
    float            x, y;
 
1871
    comp_settings    comp;
 
1872
 
 
1873
 
 
1874
    if (!comp_realized[i]) return;
 
1875
 
 
1876
 
 
1877
    /*  Clear the curve drawing area.  */
 
1878
 
 
1879
    gdk_window_clear_area (comp_drawable[i], 0, 0, comp_curve_width[i], 
 
1880
        comp_curve_height[i]);
 
1881
    gdk_gc_set_line_attributes (comp_gc[i], 1, GDK_LINE_SOLID, GDK_CAP_BUTT, 
 
1882
        GDK_JOIN_MITER);
 
1883
 
 
1884
 
 
1885
    /*  Plot the grid lines.  */
 
1886
 
 
1887
    for (j = NINT (comp_start_x[i]) ; j <= NINT (comp_end_x[i]) ; j++)
 
1888
      {
 
1889
        if (!(j % 10))
 
1890
          {
 
1891
            x1 = NINT (((float) (j - comp_start_x[i]) / 
 
1892
                comp_curve_range_x[i]) * comp_curve_width[i]);
 
1893
 
 
1894
            gdk_draw_line (comp_drawable[i], comp_gc[i], x1, 0, x1, 
 
1895
                comp_curve_height[i]);
 
1896
          }
 
1897
      }
 
1898
 
 
1899
    for (j = NINT (comp_start_y[i]) ; j <= NINT (comp_end_y[i]) ; j++)
 
1900
      {
 
1901
        if (!(j % 10))
 
1902
          {
 
1903
            if (!j)
 
1904
              {
 
1905
                gdk_gc_set_line_attributes (comp_gc[i], 2, GDK_LINE_SOLID, 
 
1906
                    GDK_CAP_BUTT, GDK_JOIN_MITER);
 
1907
              }
 
1908
            else
 
1909
              {
 
1910
                gdk_gc_set_line_attributes (comp_gc[i], 1, GDK_LINE_SOLID, 
 
1911
                    GDK_CAP_BUTT, GDK_JOIN_MITER);
 
1912
              }
 
1913
 
 
1914
            y1 = comp_curve_height[i] - NINT (((float) (j - comp_start_y[i]) / 
 
1915
                comp_curve_range_y[i]) * comp_curve_height[i]);
 
1916
 
 
1917
            gdk_draw_line (comp_drawable[i], comp_gc[i], 0, y1, 
 
1918
                comp_curve_width[i], y1);
 
1919
          }
 
1920
      }
 
1921
 
 
1922
 
 
1923
    /*  Plot the curves.  */
 
1924
 
 
1925
    gdk_gc_set_line_attributes (comp_gc[i], 2, GDK_LINE_SOLID, GDK_CAP_BUTT,
 
1926
        GDK_JOIN_MITER);
 
1927
    gdk_gc_set_foreground (comp_gc[i], &comp_color[i]);
 
1928
 
 
1929
 
 
1930
    comp = comp_get_settings (i);
 
1931
 
 
1932
    x0 = 999.0;
 
1933
    for (x = comp_start_x[i] ; x <= comp_end_x[i] ; x += 0.5f) 
 
1934
      {
 
1935
        x1 = NINT (((x - comp_start_x[i]) / comp_curve_range_x[i]) * 
 
1936
            comp_curve_width[i]);
 
1937
 
 
1938
        y = eval_comp (comp.threshold, comp.ratio, comp.knee, x) +
 
1939
            comp.makeup_gain;
 
1940
 
 
1941
        y1 = comp_curve_height[i] - NINT (((y - comp_start_y[i]) / 
 
1942
            comp_curve_range_y[i]) * comp_curve_height[i]);
 
1943
 
 
1944
        if (x0 != 999.0) 
 
1945
            gdk_draw_line (comp_drawable[i], comp_gc[i], x0, y0, x1, y1);
 
1946
 
 
1947
        x0 = x1;
 
1948
        y0 = y1;
 
1949
      }
 
1950
    gdk_gc_set_line_attributes (comp_gc[i], 1, GDK_LINE_SOLID, GDK_CAP_BUTT,
 
1951
        GDK_JOIN_MITER);
 
1952
    gdk_gc_set_foreground (comp_gc[i], &black);
 
1953
}
 
1954
 
 
1955
 
 
1956
/*  The compressor curve expose/resize callback (0-2).  */
 
1957
 
 
1958
void comp_curve_expose (GtkWidget *widget, int i)
 
1959
{
 
1960
    /*  Since we're doing inclusive plots on the compressor curves we'll
 
1961
        not decrement the width and height.  */
 
1962
 
 
1963
    comp_curve_width[i] = widget->allocation.width;
 
1964
    comp_curve_height[i] = widget->allocation.height;
 
1965
 
 
1966
    draw_comp_curve (i);
 
1967
}
 
1968
 
 
1969
 
 
1970
/*  The compressor curve realize callback (0-2).  */
 
1971
 
 
1972
void comp_curve_realize (GtkWidget *widget, int i)
 
1973
{
 
1974
    comp_drawable[i] = widget->window;
 
1975
 
 
1976
    comp_start_x[i] = -60.0;
 
1977
    comp_end_x[i] = 0.0;
 
1978
    comp_start_y[i] = -60.0;
 
1979
    comp_end_y[i] = 30.0;
 
1980
 
 
1981
    comp_curve_range_x[i] = comp_end_x[i] - comp_start_x[i];
 
1982
    comp_curve_range_y[i] = comp_end_y[i] - comp_start_y[i];
 
1983
 
 
1984
    comp_gc[i] = widget->style->fg_gc[GTK_WIDGET_STATE (widget)];
 
1985
 
 
1986
 
 
1987
    comp_pc[i] = gtk_widget_get_pango_context (widget);
 
1988
 
 
1989
 
 
1990
    comp_realized[i] = 1;
 
1991
}
 
1992
 
 
1993
 
 
1994
/*  The compressor curve drawing area motion callback (0-2).  */
 
1995
 
 
1996
void comp_curve_box_motion (int i, GdkEventMotion  *event)
 
1997
{
 
1998
    float          x, y;
 
1999
    char           coords[20];
 
2000
 
 
2001
 
 
2002
    x = comp_start_x[i] + (((float) event->x / 
 
2003
        (float) comp_curve_width[i]) * comp_curve_range_x[i]);
 
2004
 
 
2005
 
 
2006
    y = comp_start_y[i] + ((((float) comp_curve_height[i] - (float) event->y) /
 
2007
        (float) comp_curve_height[i]) * comp_curve_range_y[i]);
 
2008
 
 
2009
 
 
2010
    sprintf (coords, "%d , %d    ", NINT (x), NINT (y));
 
2011
    comp_write_annotation (i, coords);
 
2012
}
 
2013
 
 
2014
 
 
2015
/*  Leaving the box/curve, turn off highlights in the labels of the box and 
 
2016
    curve.  */
 
2017
 
 
2018
void comp_box_leave (int i)
 
2019
{
 
2020
    gtk_widget_modify_fg ((GtkWidget *) l_comp_lbl[i], GTK_STATE_NORMAL, 
 
2021
                          &comp_color[3]);
 
2022
    gtk_widget_modify_fg ((GtkWidget *) l_c_curve_lbl[i], GTK_STATE_NORMAL, 
 
2023
                          &comp_color[3]);
 
2024
}
 
2025
 
 
2026
 
 
2027
/*  Entering the box/curve, turn on highlights in the labels of the box and 
 
2028
    curve.  */
 
2029
 
 
2030
void comp_box_enter (int i)
 
2031
{
 
2032
    gtk_widget_modify_fg ((GtkWidget *) l_comp_lbl[i], GTK_STATE_NORMAL, 
 
2033
                          &comp_color[i]);
 
2034
    gtk_widget_modify_fg ((GtkWidget *) l_c_curve_lbl[i], GTK_STATE_NORMAL, 
 
2035
                          &comp_color[i]);
 
2036
}
 
2037
 
 
2038
 
 
2039
/*  Saving the current notebook page on a switch, see callbacks.c.  This saves
 
2040
    us querying the GUI 10 times per second from spectrum_update.  */
 
2041
 
 
2042
void hdeq_notebook1_set_page (guint page_num)
 
2043
{
 
2044
    notebook1_page = page_num;
 
2045
}
 
2046
 
 
2047
 
 
2048
/*  Return the current notebook page - 0 = hdeq, 1 = geq, 2 = spectrum,
 
2049
    3 = options.  */
 
2050
 
 
2051
int get_current_notebook1_page ()
 
2052
{
 
2053
    return (notebook1_page);
 
2054
}