~ubuntu-branches/ubuntu/utopic/glame/utopic

« back to all changes in this revision

Viewing changes to src/plugins/normalize.c

  • Committer: Bazaar Package Importer
  • Author(s): Daniel Kobras
  • Date: 2002-04-09 17:14:12 UTC
  • Revision ID: james.westby@ubuntu.com-20020409171412-jzpnov7mbz2w6zsr
Tags: upstream-0.6.2
ImportĀ upstreamĀ versionĀ 0.6.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * normalize.c
 
3
 * $Id: normalize.c,v 1.9.2.1 2002/01/23 20:23:54 richi Exp $
 
4
 *
 
5
 * Copyright (C) 2001 Alexander Ehlert
 
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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
20
 *
 
21
 */
 
22
 
 
23
#ifdef HAVE_CONFIG_H
 
24
#include <config.h>
 
25
#endif
 
26
 
 
27
#include <sys/types.h>
 
28
#include <unistd.h>
 
29
#include <stdlib.h>
 
30
#include <gtk/gtk.h>
 
31
#include <gnome.h>
 
32
#include "filter.h"
 
33
#include "util.h"
 
34
#include "glplugin.h"
 
35
#include "math.h"
 
36
#include "gpsm.h"
 
37
#include "util/glame_gui_utils.h"
 
38
#include "network_utils.h"
 
39
 
 
40
PLUGIN(normalize)
 
41
 
 
42
typedef struct task_entry task_entry_t;
 
43
 
 
44
struct task_entry {
 
45
        struct glame_list_head list;
 
46
        float rms;
 
47
        gpsm_item_t* item;
 
48
};
 
49
 
 
50
struct normalize_s {
 
51
        GtkWidget *dialog, *appbar, *text, *spin_db, *spin_abs, *spin_freq;
 
52
        GtkWidget *analyze_button, /* *simulate_button,*/ *ok_button;
 
53
        task_entry_t *head;
 
54
        gpsm_item_t *grp;
 
55
        long total_size, start, length;
 
56
        int mode;
 
57
        float ampl_abs, ampl_db, maxrms;
 
58
        int freq;       
 
59
        int running;
 
60
        int changed;
 
61
};
 
62
 
 
63
 
 
64
 
 
65
static void cleanup_task_list(struct normalize_s *ns) {
 
66
        task_entry_t *task, *last, *next;
 
67
 
 
68
        if (ns->head==NULL)
 
69
                return;
 
70
 
 
71
        last = task = ns->head;
 
72
        do {
 
73
                next = glame_list_getnext(&task->list, task, task_entry_t, list);
 
74
                free(task);
 
75
                task=next;
 
76
        } while ( (task!=last) && (task!=NULL));
 
77
        ns->head = NULL;
 
78
}
 
79
 
 
80
static gint normmode_cb(GtkMenu *menu, struct normalize_s* ns)
 
81
{
 
82
        int oldmode = ns->mode;
 
83
        ns->mode =  glame_menu_get_active_index(menu);
 
84
        DPRINTF("Selected normalize mode %d\n", ns->mode);
 
85
        switch (ns->mode) {
 
86
        case 0 : 
 
87
                gtk_widget_set_sensitive(ns->spin_abs, FALSE);
 
88
                gtk_widget_set_sensitive(ns->spin_db, FALSE);
 
89
                gtk_widget_set_sensitive(ns->spin_freq, FALSE);
 
90
                ns->ampl_abs = 1.0;
 
91
                ns->ampl_db = 0.0;
 
92
                if (oldmode==2)
 
93
                        ns->changed=1;
 
94
                break;
 
95
        case 1:
 
96
                gtk_widget_set_sensitive(ns->spin_abs, TRUE);
 
97
                gtk_widget_set_sensitive(ns->spin_db, TRUE);
 
98
                gtk_widget_set_sensitive(ns->spin_freq, FALSE);
 
99
                break;
 
100
        case 2:
 
101
                gtk_widget_set_sensitive(ns->spin_abs, TRUE);
 
102
                gtk_widget_set_sensitive(ns->spin_db, TRUE);
 
103
                gtk_widget_set_sensitive(ns->spin_freq, TRUE);
 
104
                if (oldmode!=2)
 
105
                        ns->changed=1;
 
106
        }
 
107
 
 
108
        return TRUE;
 
109
}
 
110
 
 
111
 
 
112
static gint ampl_abs_cb(GtkSpinButton *button, struct normalize_s* ns) {
 
113
        ns->ampl_abs = gtk_spin_button_get_value_as_float(button);
 
114
        ns->ampl_db = GAIN2DB(ns->ampl_abs);
 
115
        gtk_spin_button_set_value(GTK_SPIN_BUTTON(ns->spin_db), ns->ampl_db);
 
116
        return TRUE;
 
117
}
 
118
 
 
119
static gint ampl_db_cb(GtkSpinButton *button, struct normalize_s* ns) {
 
120
        ns->ampl_db = gtk_spin_button_get_value_as_float(button);
 
121
        ns->ampl_abs = DB2GAIN(ns->ampl_db);
 
122
        gtk_spin_button_set_value(GTK_SPIN_BUTTON(ns->spin_abs), ns->ampl_abs);
 
123
        return TRUE;
 
124
}
 
125
 
 
126
static gint norm_freq_cb(GtkSpinButton *button, struct normalize_s* ns) {
 
127
        ns->freq = gtk_spin_button_get_value_as_int(button); 
 
128
        ns->changed = 1;
 
129
        return TRUE;
 
130
}
 
131
 
 
132
static gint cancel_cb(GtkWidget *button, struct normalize_s* ns) {
 
133
        if (ns->running==1)
 
134
                ns->running = 0;
 
135
        gtk_widget_destroy(ns->dialog);
 
136
        return TRUE;
 
137
}
 
138
 
 
139
static gint paranoia_cb(GtkWidget *bla, struct normalize_s* ns) {
 
140
        if (ns->running==1)
 
141
                ns->running = 0;
 
142
        return TRUE;
 
143
}
 
144
 
 
145
/* static void simulate_cb(GtkWidget *, struct normalize_s*); */
 
146
static void analyze_cb(GtkWidget *, struct normalize_s*);
 
147
static void normalize_cb(GtkWidget *, struct normalize_s*);
 
148
 
 
149
void normalize_dialog(struct normalize_s* norms)
 
150
{
 
151
  GtkWidget *dialog1;
 
152
  GtkWidget *dialog_vbox1;
 
153
  GtkWidget *frame1;
 
154
  GtkWidget *vbox1, *hbox1;
 
155
  GtkWidget *table1;
 
156
  GtkWidget *label3;
 
157
  GtkWidget *label2;
 
158
  GtkWidget *table2;
 
159
  GtkWidget *label5;
 
160
  GtkWidget *label6;
 
161
  GtkObject *spinbutton1_adj;
 
162
  GtkWidget *spinbutton1;
 
163
  GtkObject *spinbutton2_adj;
 
164
  GtkWidget *spinbutton2;
 
165
  GtkWidget *optionmenu1;
 
166
  GtkWidget *optionmenu1_menu;
 
167
  GtkWidget *glade_menuitem;
 
168
  GtkWidget *label7;
 
169
  GtkObject *spinbutton3_adj;
 
170
  GtkWidget *spinbutton3;
 
171
  GtkWidget *frame2;
 
172
  GtkWidget *scrolledwindow1;
 
173
  GtkWidget *text1;
 
174
  GtkWidget /* *button4,*/ *button5;
 
175
  GtkWidget *appbar1;
 
176
  GtkWidget *dialog_action_area1;
 
177
  GtkWidget *button1;
 
178
  GtkWidget *button3;
 
179
 
 
180
  norms->dialog = dialog1 = gnome_dialog_new (NULL, NULL);
 
181
  gtk_object_set_data (GTK_OBJECT (dialog1), "dialog1", dialog1);
 
182
  gtk_window_set_policy (GTK_WINDOW (dialog1), FALSE, FALSE, FALSE);
 
183
 
 
184
  dialog_vbox1 = GNOME_DIALOG (dialog1)->vbox;
 
185
  gtk_object_set_data (GTK_OBJECT (dialog1), "dialog_vbox1", dialog_vbox1);
 
186
  gtk_widget_show (dialog_vbox1);
 
187
 
 
188
  frame1 = gtk_frame_new (_("Normalize"));
 
189
  gtk_widget_ref (frame1);
 
190
  gtk_object_set_data_full (GTK_OBJECT (dialog1), "frame1", frame1,
 
191
                            (GtkDestroyNotify) gtk_widget_unref);
 
192
  gtk_widget_show (frame1);
 
193
  gtk_box_pack_start (GTK_BOX (dialog_vbox1), frame1, TRUE, TRUE, 0);
 
194
  gtk_container_set_border_width (GTK_CONTAINER (frame1), 3);
 
195
 
 
196
  vbox1 = gtk_vbox_new (FALSE, 6);
 
197
  gtk_widget_ref (vbox1);
 
198
  gtk_object_set_data_full (GTK_OBJECT (dialog1), "vbox1", vbox1,
 
199
                            (GtkDestroyNotify) gtk_widget_unref);
 
200
  gtk_widget_show (vbox1);
 
201
  gtk_container_add (GTK_CONTAINER (frame1), vbox1);
 
202
  gtk_container_set_border_width (GTK_CONTAINER (vbox1), 3);
 
203
 
 
204
  table1 = gtk_table_new (3, 2, FALSE);
 
205
  gtk_widget_ref (table1);
 
206
  gtk_object_set_data_full (GTK_OBJECT (dialog1), "table1", table1,
 
207
                            (GtkDestroyNotify) gtk_widget_unref);
 
208
  gtk_widget_show (table1);
 
209
  gtk_box_pack_start (GTK_BOX (vbox1), table1, TRUE, TRUE, 0);
 
210
  gtk_container_set_border_width (GTK_CONTAINER (table1), 4);
 
211
  gtk_table_set_row_spacings (GTK_TABLE (table1), 8);
 
212
 
 
213
  label3 = gtk_label_new (_("Volume:"));
 
214
  gtk_widget_ref (label3);
 
215
  gtk_object_set_data_full (GTK_OBJECT (dialog1), "label3", label3,
 
216
                            (GtkDestroyNotify) gtk_widget_unref);
 
217
  gtk_widget_show (label3);
 
218
  gtk_table_attach (GTK_TABLE (table1), label3, 0, 1, 1, 2,
 
219
                    (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
 
220
                    (GtkAttachOptions) (0), 0, 0);
 
221
  gtk_misc_set_alignment (GTK_MISC (label3), 0, 0.5);
 
222
 
 
223
  label2 = gtk_label_new (_("Mode:"));
 
224
  gtk_widget_ref (label2);
 
225
  gtk_object_set_data_full (GTK_OBJECT (dialog1), "label2", label2,
 
226
                            (GtkDestroyNotify) gtk_widget_unref);
 
227
  gtk_widget_show (label2);
 
228
  gtk_table_attach (GTK_TABLE (table1), label2, 0, 1, 0, 1,
 
229
                    (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
 
230
                    (GtkAttachOptions) (0), 0, 0);
 
231
  gtk_misc_set_alignment (GTK_MISC (label2), 0, 0.5);
 
232
 
 
233
  table2 = gtk_table_new (2, 2, FALSE);
 
234
  gtk_widget_ref (table2);
 
235
  gtk_object_set_data_full (GTK_OBJECT (dialog1), "table2", table2,
 
236
                            (GtkDestroyNotify) gtk_widget_unref);
 
237
  gtk_widget_show (table2);
 
238
  gtk_table_attach (GTK_TABLE (table1), table2, 1, 2, 1, 2,
 
239
                    (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
 
240
                    (GtkAttachOptions) (GTK_FILL), 0, 0);
 
241
 
 
242
  label5 = gtk_label_new (_("Abs"));
 
243
  gtk_widget_ref (label5);
 
244
  gtk_object_set_data_full (GTK_OBJECT (dialog1), "label5", label5,
 
245
                            (GtkDestroyNotify) gtk_widget_unref);
 
246
  gtk_widget_show (label5);
 
247
  gtk_table_attach (GTK_TABLE (table2), label5, 0, 1, 0, 1,
 
248
                    (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
 
249
                    (GtkAttachOptions) (0), 0, 0);
 
250
  gtk_misc_set_alignment (GTK_MISC (label5), 0, 0.5);
 
251
 
 
252
  label6 = gtk_label_new (_("dB"));
 
253
  gtk_widget_ref (label6);
 
254
  gtk_object_set_data_full (GTK_OBJECT (dialog1), "label6", label6,
 
255
                            (GtkDestroyNotify) gtk_widget_unref);
 
256
  gtk_widget_show (label6);
 
257
  gtk_table_attach (GTK_TABLE (table2), label6, 0, 1, 1, 2,
 
258
                    (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
 
259
                    (GtkAttachOptions) (0), 0, 0);
 
260
  gtk_misc_set_alignment (GTK_MISC (label6), 0, 0.5);
 
261
 
 
262
  spinbutton1_adj = gtk_adjustment_new (1.0, 0.0, 1.0, 0.01, 0.1, 0.0);
 
263
  norms->spin_abs = spinbutton1 = gtk_spin_button_new (GTK_ADJUSTMENT (spinbutton1_adj), 1, 2);
 
264
  gtk_widget_ref (spinbutton1);
 
265
  gtk_object_set_data_full (GTK_OBJECT (dialog1), "spinbutton1", spinbutton1,
 
266
                            (GtkDestroyNotify) gtk_widget_unref);
 
267
  gtk_widget_show (spinbutton1);
 
268
  gtk_table_attach (GTK_TABLE (table2), spinbutton1, 1, 2, 0, 1,
 
269
                    (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
 
270
                    (GtkAttachOptions) (0), 0, 0);
 
271
  
 
272
  gtk_widget_set_sensitive(spinbutton1, FALSE);
 
273
 
 
274
  gtk_signal_connect(GTK_OBJECT(spinbutton1),
 
275
                     "changed",
 
276
                     (GtkSignalFunc)ampl_abs_cb, norms);
 
277
 
 
278
  spinbutton2_adj = gtk_adjustment_new (0.0, -100.0, 0.0, 0.1, 0.5, 0.0);
 
279
  norms->spin_db = spinbutton2 = gtk_spin_button_new (GTK_ADJUSTMENT (spinbutton2_adj), 1, 2);
 
280
  gtk_widget_ref (spinbutton2);
 
281
  gtk_object_set_data_full (GTK_OBJECT (dialog1), "spinbutton2", spinbutton2,
 
282
                            (GtkDestroyNotify) gtk_widget_unref);
 
283
  gtk_widget_show (spinbutton2);
 
284
  gtk_table_attach (GTK_TABLE (table2), spinbutton2, 1, 2, 1, 2,
 
285
                    (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
 
286
                    (GtkAttachOptions) (0), 0, 0);
 
287
  gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (spinbutton2), TRUE);
 
288
 
 
289
  gtk_widget_set_sensitive(spinbutton2, FALSE);
 
290
  gtk_signal_connect(GTK_OBJECT(spinbutton2),
 
291
                     "changed",
 
292
                     (GtkSignalFunc)ampl_db_cb, norms);
 
293
 
 
294
  optionmenu1 = gtk_option_menu_new ();
 
295
  gtk_widget_ref (optionmenu1);
 
296
  gtk_object_set_data_full (GTK_OBJECT (dialog1), "optionmenu1", optionmenu1,
 
297
                            (GtkDestroyNotify) gtk_widget_unref);
 
298
  gtk_widget_show (optionmenu1);
 
299
  gtk_table_attach (GTK_TABLE (table1), optionmenu1, 1, 2, 0, 1,
 
300
                    (GtkAttachOptions) (GTK_FILL),
 
301
                    (GtkAttachOptions) (0), 0, 0);
 
302
  optionmenu1_menu = gtk_menu_new ();
 
303
  glade_menuitem = gtk_menu_item_new_with_label (_("Peak"));
 
304
  gtk_widget_show (glade_menuitem);
 
305
  gtk_menu_append (GTK_MENU (optionmenu1_menu), glade_menuitem);
 
306
  glade_menuitem = gtk_menu_item_new_with_label (_("Volume"));
 
307
  gtk_widget_show (glade_menuitem);
 
308
  gtk_menu_append (GTK_MENU (optionmenu1_menu), glade_menuitem);
 
309
  glade_menuitem = gtk_menu_item_new_with_label (_("Volume/Frequency"));
 
310
  gtk_widget_show (glade_menuitem);
 
311
  gtk_menu_append (GTK_MENU (optionmenu1_menu), glade_menuitem);
 
312
  gtk_option_menu_set_menu (GTK_OPTION_MENU (optionmenu1), optionmenu1_menu);
 
313
 
 
314
  gtk_signal_connect(GTK_OBJECT(optionmenu1_menu),
 
315
                     "selection_done",
 
316
                     (GtkSignalFunc)normmode_cb, norms);
 
317
 
 
318
  norms->mode = 0;
 
319
 
 
320
  label7 = gtk_label_new (_("Frequency:"));
 
321
  gtk_widget_ref (label7);
 
322
  gtk_object_set_data_full (GTK_OBJECT (dialog1), "label7", label7,
 
323
                            (GtkDestroyNotify) gtk_widget_unref);
 
324
  gtk_widget_show (label7);
 
325
  gtk_table_attach (GTK_TABLE (table1), label7, 0, 1, 2, 3,
 
326
                    (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
 
327
                    (GtkAttachOptions) (0), 0, 0);
 
328
  gtk_label_set_justify (GTK_LABEL (label7), GTK_JUSTIFY_LEFT);
 
329
  gtk_misc_set_alignment (GTK_MISC (label7), 0, 0.5);
 
330
 
 
331
  spinbutton3_adj = gtk_adjustment_new (1000, 1, 96000, 1, 100, 10);
 
332
  norms->spin_freq = spinbutton3 = gtk_spin_button_new (GTK_ADJUSTMENT (spinbutton3_adj), 1, 2);
 
333
  gtk_widget_ref (spinbutton3);
 
334
  gtk_object_set_data_full (GTK_OBJECT (dialog1), "spinbutton3", spinbutton3,
 
335
                            (GtkDestroyNotify) gtk_widget_unref);
 
336
  gtk_widget_show (spinbutton3);
 
337
  gtk_table_attach (GTK_TABLE (table1), spinbutton3, 1, 2, 2, 3,
 
338
                    (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
 
339
                    (GtkAttachOptions) (0), 0, 0);
 
340
  gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (spinbutton3), TRUE);
 
341
  gtk_widget_set_sensitive(norms->spin_freq, FALSE);
 
342
 
 
343
  gtk_signal_connect(GTK_OBJECT(spinbutton3),
 
344
                     "changed",
 
345
                     (GtkSignalFunc)norm_freq_cb, norms);
 
346
 
 
347
  norms->freq = 1000;
 
348
 
 
349
  frame2 = gtk_frame_new (_("Operation Stats"));
 
350
  gtk_widget_ref (frame2);
 
351
  gtk_object_set_data_full (GTK_OBJECT (dialog1), "frame2", frame2,
 
352
                            (GtkDestroyNotify) gtk_widget_unref);
 
353
  gtk_widget_show (frame2);
 
354
  gtk_box_pack_start (GTK_BOX (vbox1), frame2, TRUE, TRUE, 0);
 
355
 
 
356
  scrolledwindow1 = gtk_scrolled_window_new (NULL, NULL);
 
357
  gtk_widget_ref (scrolledwindow1);
 
358
  gtk_object_set_data_full (GTK_OBJECT (dialog1), "scrolledwindow1", scrolledwindow1,
 
359
                            (GtkDestroyNotify) gtk_widget_unref);
 
360
  gtk_widget_show (scrolledwindow1);
 
361
  gtk_container_add (GTK_CONTAINER (frame2), scrolledwindow1);
 
362
  gtk_widget_set_usize (scrolledwindow1, 400, 150);
 
363
  gtk_container_set_border_width (GTK_CONTAINER (scrolledwindow1), 3);
 
364
  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow1), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
 
365
 
 
366
  norms->text = text1 = gtk_text_new (NULL, NULL);
 
367
  gtk_widget_ref (text1);
 
368
  gtk_object_set_data_full (GTK_OBJECT (dialog1), "text1", text1,
 
369
                            (GtkDestroyNotify) gtk_widget_unref);
 
370
  gtk_widget_show (text1);
 
371
  gtk_container_add (GTK_CONTAINER (scrolledwindow1), text1);
 
372
 
 
373
  hbox1 = gtk_hbox_new(TRUE, 2);
 
374
  gtk_widget_show(hbox1);
 
375
  gtk_box_pack_start (GTK_BOX (vbox1), hbox1, FALSE, FALSE, 0);
 
376
 
 
377
  norms->analyze_button = button5 = gtk_button_new_with_label (_("Analyze"));
 
378
  gtk_widget_ref (button5);
 
379
  gtk_object_set_data_full (GTK_OBJECT (dialog1), "button5", button5,
 
380
                            (GtkDestroyNotify) gtk_widget_unref);
 
381
  gtk_widget_show (button5);
 
382
  gtk_box_pack_start (GTK_BOX (hbox1), button5, TRUE, TRUE, 0);
 
383
 
 
384
  gtk_signal_connect(GTK_OBJECT(button5), "clicked",
 
385
                     (GtkSignalFunc)analyze_cb, norms);
 
386
 
 
387
  /*
 
388
  norms->simulate_button = button4 = gtk_button_new_with_label (_("Simulate"));
 
389
  gtk_widget_ref (button4);
 
390
  gtk_object_set_data_full (GTK_OBJECT (dialog1), "button4", button4,
 
391
                            (GtkDestroyNotify) gtk_widget_unref);
 
392
  gtk_widget_show (button4);
 
393
  gtk_box_pack_start (GTK_BOX (hbox1), button4, TRUE, TRUE, 0);
 
394
 
 
395
  gtk_signal_connect(GTK_OBJECT(button4), "clicked",
 
396
                     (GtkSignalFunc)simulate_cb, norms);
 
397
  */
 
398
  norms->appbar = appbar1 = gnome_appbar_new (TRUE, TRUE, GNOME_PREFERENCES_NEVER);
 
399
  gtk_widget_ref (appbar1);
 
400
  gtk_object_set_data_full (GTK_OBJECT (dialog1), "appbar1", appbar1,
 
401
                            (GtkDestroyNotify) gtk_widget_unref);
 
402
  gtk_widget_show (appbar1);
 
403
  gtk_box_pack_start (GTK_BOX (vbox1), appbar1, TRUE, TRUE, 0);
 
404
 
 
405
  dialog_action_area1 = GNOME_DIALOG (dialog1)->action_area;
 
406
  gtk_object_set_data (GTK_OBJECT (dialog1), "dialog_action_area1", dialog_action_area1);
 
407
  gtk_widget_show (dialog_action_area1);
 
408
  gtk_button_box_set_spacing (GTK_BUTTON_BOX (dialog_action_area1), 8);
 
409
  gtk_button_box_set_layout (GTK_BUTTON_BOX (dialog_action_area1), GTK_BUTTONBOX_EDGE);
 
410
 
 
411
  gnome_dialog_append_button (GNOME_DIALOG (dialog1), GNOME_STOCK_BUTTON_OK);
 
412
  norms->ok_button = button1 = GTK_WIDGET (g_list_last (GNOME_DIALOG (dialog1)->buttons)->data);
 
413
  gtk_widget_ref (button1);
 
414
  gtk_object_set_data_full (GTK_OBJECT (dialog1), "button1", button1,
 
415
                            (GtkDestroyNotify) gtk_widget_unref);
 
416
  gtk_widget_show (button1);
 
417
  GTK_WIDGET_SET_FLAGS (button1, GTK_CAN_DEFAULT);
 
418
 
 
419
  gtk_signal_connect(GTK_OBJECT(button1), "clicked",
 
420
                     (GtkSignalFunc)normalize_cb, norms);
 
421
  
 
422
  gnome_dialog_append_button (GNOME_DIALOG (dialog1), GNOME_STOCK_BUTTON_CANCEL);
 
423
  button3 = GTK_WIDGET (g_list_last (GNOME_DIALOG (dialog1)->buttons)->data);
 
424
  gtk_widget_ref (button3);
 
425
  gtk_object_set_data_full (GTK_OBJECT (dialog1), "button3", button3,
 
426
                            (GtkDestroyNotify) gtk_widget_unref);
 
427
  gtk_widget_show (button3);
 
428
  GTK_WIDGET_SET_FLAGS (button3, GTK_CAN_DEFAULT);
 
429
  gtk_signal_connect(GTK_OBJECT(button3), "clicked",
 
430
                     (GtkSignalFunc)cancel_cb, norms);
 
431
 
 
432
  gnome_dialog_append_button(GNOME_DIALOG(dialog1), GNOME_STOCK_BUTTON_HELP);
 
433
  gnome_dialog_button_connect(GNOME_DIALOG(dialog1), 2,
 
434
                              glame_help_cb, "Normalize");
 
435
 
 
436
 
 
437
  /* paranoia */
 
438
  gtk_signal_connect(GTK_OBJECT(norms->dialog),
 
439
                     "delete-event",
 
440
                     GTK_SIGNAL_FUNC(paranoia_cb), norms);
 
441
 
 
442
  norms->running = 0;
 
443
  norms->ampl_abs = 1.0;
 
444
  norms->ampl_db = 0.0;
 
445
  norms->changed = 1;
 
446
}
 
447
 
 
448
static float get_max_rms(task_entry_t* head, gpsm_item_t** item) {
 
449
        task_entry_t* task, *last;
 
450
        float maxrms=-1.0;
 
451
 
 
452
        task = last = head;
 
453
        
 
454
        do {
 
455
                if (task->rms > maxrms) {
 
456
                        maxrms = task->rms;
 
457
                        *item = task->item;
 
458
                }
 
459
               task = glame_list_getnext(&task->list, task, task_entry_t, list);
 
460
        } while ( (task!=last) && (task!=NULL));
 
461
 
 
462
        return maxrms;
 
463
}
 
464
 
 
465
static void analyze_rms(struct normalize_s *ns) {
 
466
        task_entry_t *te, *ote, *task, *last;
 
467
        filter_t *net, *ssp, *maxrms, *swap;
 
468
        filter_param_t  *param;
 
469
        float percentage, mrms;
 
470
        int num = 0;
 
471
        gpsm_item_t* item;
 
472
        char label[128], string[2048];
 
473
        long done = 0;
 
474
        int bsize;
 
475
 
 
476
        ote = NULL;
 
477
 
 
478
        string[0] = '\0';
 
479
        label[127] = '\0';
 
480
        gpsm_grp_foreach_item(ns->grp, item) {
 
481
                num++;
 
482
                snprintf(label, 127, "Analyzing Track %s", gpsm_item_label(item));
 
483
                gnome_appbar_set_status(GNOME_APPBAR(ns->appbar), label);
 
484
 
 
485
                te =  ALLOC(task_entry_t);
 
486
                GLAME_INIT_LIST_HEAD(&te->list);
 
487
                te->rms = 0.0;
 
488
                te->item = item;
 
489
 
 
490
                if (ote!=NULL)
 
491
                        glame_list_add(&te->list, &ote->list);
 
492
                ote = te;
 
493
                ns->head = te;
 
494
 
 
495
                if (ns->mode < 2)
 
496
                        bsize = 1;
 
497
                else {
 
498
                        bsize = MAX(gpsm_swfile_samplerate(item)/ns->freq, 1);
 
499
                }
 
500
 
 
501
                net = filter_creat(NULL);
 
502
                ssp = net_add_plugin_by_name(net, "ssp_streamer");
 
503
                maxrms = net_add_plugin_by_name(net, "maxrms");
 
504
                swap = net_add_gpsm_input(net, (gpsm_swfile_t *)item,
 
505
                                          ns->start, MIN(ns->length, gpsm_item_hsize(item)), 0);
 
506
                DPRINTF("Processing %ld samples\n", MIN(ns->length, (gpsm_item_hsize(item))));
 
507
                net_apply_node(net, ssp);
 
508
                net_apply_node(net, maxrms);
 
509
 
 
510
                param = filterparamdb_get_param(filter_paramdb(ssp), "bsize");
 
511
                filterparam_set(param, &bsize);
 
512
 
 
513
                if (filter_launch(net, GLAME_BULK_BUFSIZE) == -1
 
514
                    || filter_start(net) == -1)
 
515
                        goto fail_cleanup;
 
516
                
 
517
                param = filterparamdb_get_param(filter_paramdb(swap), 
 
518
                                                FILTERPARAM_LABEL_POS);
 
519
 
 
520
                ns->running=1;
 
521
                while(!filter_is_ready(net)) {
 
522
                        while (gtk_events_pending())
 
523
                                gtk_main_iteration();
 
524
                        usleep(40000);
 
525
                        
 
526
                        percentage = (float)(done+filterparam_val_pos(param))/
 
527
                                     (float)ns->total_size;
 
528
 
 
529
                        if (ns->running==0)
 
530
                                goto cancel_cleanup;
 
531
 
 
532
                        gnome_appbar_set_progress(GNOME_APPBAR(ns->appbar),
 
533
                                                  percentage);
 
534
                }
 
535
                ns->running = 0;
 
536
 
 
537
                done+=filterparam_val_pos(param);
 
538
                DPRINTF("posparam=%ld\n", filterparam_val_pos(param));
 
539
 
 
540
                param = filterparamdb_get_param(filter_paramdb(maxrms), "maxrms");
 
541
                te->rms = filterparam_val_float(param);
 
542
                DPRINTF("found rms = %f\n", te->rms);
 
543
                
 
544
                filter_delete(net);
 
545
        }
 
546
        ns->running = 0;
 
547
        
 
548
        task = last = te;
 
549
 
 
550
        strcat(string, "Results:\n");
 
551
        do {
 
552
                snprintf(label, 127, "%s (max rms = %.3f = %.3f dB)\n", gpsm_item_label(task->item), task->rms, GAIN2DB(task->rms));
 
553
                strcat(string, label);
 
554
                task = glame_list_getnext(&task->list, task, task_entry_t, list);
 
555
        } while ( (task!=last) && (task!=NULL));
 
556
        ns->maxrms = mrms = get_max_rms(te, &item);
 
557
        snprintf(label, 127, "Found maximum rms = %.3f(%.3f dB) in track %s.\n\n", mrms, GAIN2DB(mrms), gpsm_item_label(item));
 
558
        strcat(string, label);
 
559
        gtk_text_insert(GTK_TEXT(ns->text), NULL, NULL, NULL, string, strlen(string));
 
560
 
 
561
        ns->changed = 0;
 
562
        return;
 
563
 
 
564
 cancel_cleanup:
 
565
        filter_terminate(net);
 
566
        filter_delete(net);
 
567
        gpsm_item_destroy(ns->grp);
 
568
        cleanup_task_list(ns);
 
569
        free(ns);
 
570
        return;
 
571
 
 
572
 fail_cleanup:
 
573
        filter_delete(net);
 
574
        free(te);
 
575
        return;
 
576
}
 
577
 
 
578
static void normalize_do_task(struct normalize_s *ns) {
 
579
        int num;
 
580
        filter_t *net, *vadjust, *swapi, *swapo;
 
581
        filter_param_t  *param;
 
582
        char label[128];
 
583
        float gain, percentage;
 
584
        long done = 0;
 
585
        gpsm_item_t * item;
 
586
 
 
587
        /* FIXME 
 
588
           This is probably ok for peak normalizing, but otherwise ?
 
589
        */
 
590
 
 
591
        if (ns->changed==1)
 
592
                analyze_rms(ns);
 
593
 
 
594
        gain = ns->ampl_abs/ns->maxrms;
 
595
 
 
596
        gpsm_op_prepare(ns->grp);
 
597
 
 
598
        gpsm_grp_foreach_item(ns->grp, item) {
 
599
                num++;
 
600
                snprintf(label, 128, "Normalizing Track %s", gpsm_item_label(item));
 
601
                gnome_appbar_set_status(GNOME_APPBAR(ns->appbar), label);
 
602
                net = filter_creat(NULL);
 
603
                vadjust = net_add_plugin_by_name(net, "volume_adjust");
 
604
                swapi = net_add_gpsm_input(net, (gpsm_swfile_t *)item,
 
605
                                           ns->start, MIN(ns->length, gpsm_item_hsize(item)) , 0);
 
606
 
 
607
                net_apply_node(net, vadjust);
 
608
                swapo = net_add_gpsm_output(net, (gpsm_swfile_t *)item,
 
609
                                            ns->start, MIN(ns->length, gpsm_item_hsize(item)) , 0);
 
610
                net_apply_node(net, swapo);
 
611
 
 
612
                param = filterparamdb_get_param(filter_paramdb(vadjust), "factor");
 
613
                filterparam_set(param, &gain);
 
614
 
 
615
 
 
616
                if (filter_launch(net, GLAME_BULK_BUFSIZE) == -1
 
617
                    || filter_start(net) == -1)
 
618
                        goto fail_cleanup;
 
619
 
 
620
                param = filterparamdb_get_param(filter_paramdb(swapi), 
 
621
                                                FILTERPARAM_LABEL_POS);
 
622
 
 
623
                ns->running=1;
 
624
                while(!filter_is_ready(net)) {
 
625
                        while (gtk_events_pending())
 
626
                                gtk_main_iteration();
 
627
                        usleep(40000);
 
628
                        
 
629
                        percentage = (float)(done+filterparam_val_pos(param))/
 
630
                                     (float)ns->total_size;
 
631
 
 
632
                        if (ns->running==0)
 
633
                                goto cancel_cleanup;
 
634
 
 
635
                        gnome_appbar_set_progress(GNOME_APPBAR(ns->appbar),
 
636
                                                  percentage);
 
637
                }
 
638
                ns->running = 0;
 
639
        
 
640
                done+=filterparam_val_pos(param);
 
641
                DPRINTF("posparam=%ld\n", filterparam_val_pos(param));
 
642
 
 
643
                filter_delete(net);
 
644
        }
 
645
 
 
646
        gpsm_grp_foreach_item(ns->grp, item) {
 
647
                gpsm_notify_swapfile_change(gpsm_swfile_filename(item), 
 
648
                                            ns->start, MIN(ns->length, (gpsm_item_hsize(item)-ns->start+1)));
 
649
        }
 
650
 
 
651
        gtk_widget_destroy(ns->dialog);
 
652
        gpsm_item_destroy(ns->grp);
 
653
        cleanup_task_list(ns);
 
654
        free(ns);
 
655
        return;
 
656
 
 
657
 cancel_cleanup:
 
658
        filter_terminate(net);
 
659
        filter_delete(net);
 
660
        cleanup_task_list(ns);
 
661
        gpsm_op_undo_and_forget(ns->grp);
 
662
        gpsm_item_destroy(ns->grp);
 
663
        free(ns);
 
664
        return;
 
665
 fail_cleanup:
 
666
        filter_delete(net);
 
667
        DPRINTF("Error starting normalizing network!\n");
 
668
        return;
 
669
}
 
670
 
 
671
static long get_total_size(struct normalize_s *ns) {
 
672
        long size = 0;
 
673
        int num = 0;
 
674
        gpsm_item_t* item;
 
675
 
 
676
        gpsm_grp_foreach_item(ns->grp, item) {
 
677
                num++;
 
678
                size+=MIN(gpsm_item_hsize(item), ns->length);
 
679
                DPRINTF("hsize=%ld\n vsize = %ld processed length=%ld\n", 
 
680
                        gpsm_item_hsize(item), 
 
681
                        gpsm_item_vsize(item),
 
682
                        MIN(gpsm_item_hsize(item), ns->length));
 
683
                
 
684
        }
 
685
 
 
686
        DPRINTF("%d tracks with total size %ld\n", num, size);
 
687
        return (size == 0 ? 1 : size);
 
688
}
 
689
 
 
690
/*
 
691
static void simulate_cb(GtkWidget *button, struct normalize_s* ns) {
 
692
        DPRINTF("working hard ;)\n");
 
693
}
 
694
*/
 
695
 
 
696
static void normalize_cb(GtkWidget *button, struct normalize_s* ns) {
 
697
        DPRINTF("working like a dog every night and day ;)\n");
 
698
        gtk_widget_set_sensitive(ns->ok_button, FALSE);
 
699
        gtk_widget_set_sensitive(ns->analyze_button, FALSE);
 
700
        /* gtk_widget_set_sensitive(ns->simulate_button, FALSE); */
 
701
        normalize_do_task(ns);
 
702
}
 
703
 
 
704
static void analyze_cb(GtkWidget *button, struct normalize_s* ns) {
 
705
        gtk_widget_set_sensitive(ns->analyze_button, FALSE);
 
706
        gtk_widget_set_sensitive(ns->ok_button, FALSE);
 
707
        /* gtk_widget_set_sensitive(ns->simulate_button, FALSE); */
 
708
        analyze_rms(ns);
 
709
        gtk_widget_set_sensitive(ns->analyze_button, TRUE);
 
710
        gtk_widget_set_sensitive(ns->ok_button, TRUE);
 
711
        /* gtk_widget_set_sensitive(ns->simulate_button, TRUE); */
 
712
}
 
713
 
 
714
 
 
715
static int normalize_gpsm(gpsm_item_t *grp, long start, long length)
 
716
{
 
717
        struct normalize_s *ns;
 
718
 
 
719
        ns = ALLOCN(1, struct normalize_s);
 
720
 
 
721
        ns->grp = (gpsm_item_t*)gpsm_collect_swfiles(grp);
 
722
        if (ns->grp==NULL)
 
723
                return -1;
 
724
 
 
725
        normalize_dialog(ns);
 
726
        gtk_widget_show(ns->dialog);
 
727
 
 
728
        ns->start = start;
 
729
        ns->length = length;
 
730
        ns->total_size = get_total_size(ns);
 
731
 
 
732
 
 
733
        DPRINTF("Size of all selected tracks: %ld\n", ns->total_size);
 
734
 
 
735
        return 0;
 
736
}
 
737
 
 
738
int normalize_register(plugin_t *p)
 
739
{
 
740
        plugin_set(p, PLUGIN_GPSMOP, normalize_gpsm);
 
741
        plugin_set(p, PLUGIN_DESCRIPTION, "normalizes a gpsm subtree");
 
742
        plugin_set(p, PLUGIN_CATEGORY, "Volume");
 
743
        
 
744
        return 0;
 
745
}
 
746
/* Generalization strikes 240 lines for a simple function :) */