~ubuntu-branches/ubuntu/karmic/mhwaveedit/karmic

« back to all changes in this revision

Viewing changes to src/effectbrowser.c

  • Committer: Bazaar Package Importer
  • Author(s): Free Ekanayaka
  • Date: 2008-01-08 22:20:37 UTC
  • mfrom: (2.1.6 hardy)
  • Revision ID: james.westby@ubuntu.com-20080108222037-tsazhckl5vmc8yih
Tags: 1.4.14-2
Added desktop file (Closes: #457849), thanks to Marco Rodrigues

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
 
 * Copyright (C) 2003 2004, Magnus Hjorth
 
2
 * Copyright (C) 2003 2004 2007, Magnus Hjorth
3
3
 *
4
4
 * This file is part of mhWaveEdit.
5
5
 *
34
34
#include "documentlist.h"
35
35
#include "um.h"
36
36
#include "gettext.h"
 
37
#include "mapchannelsdialog.h"
 
38
 
 
39
struct source {
 
40
     gchar tag;
 
41
     gchar *name;
 
42
     effect_register_rebuild_func rebuild_func;
 
43
     effect_register_get_func get_func;
 
44
     gpointer rebuild_func_data,get_func_data;
 
45
     int is_new;
 
46
};
37
47
 
38
48
struct effect {
39
 
     gchar *name;
40
 
     gchar *title;
41
 
     GtkType dialog_type;
 
49
     gchar *name,*title,*location,*author,source_tag;
 
50
     gboolean process_tag;
42
51
};
43
52
 
44
 
static GSList *effects = NULL;
45
 
static guint num_effects = 0;
 
53
static ListObject *effect_list = NULL;
 
54
static GSList *sources = NULL;
46
55
 
47
56
static GSList *geometry_stack = NULL;
48
57
static gboolean geometry_stack_inited = FALSE;
49
58
 
50
59
static GtkObjectClass *parent_class;
51
60
 
52
 
static void effect_browser_remove_effect(EffectBrowser *eb);
53
 
 
54
 
void effect_browser_register_effect(gchar *name, gchar *title, 
55
 
                                    GtkType dialog_type)
 
61
static void list_widget_rebuild(gpointer dummy, gpointer dummy2, 
 
62
                                EffectBrowser *eb);
 
63
 
 
64
void effect_register_add_source(gchar *name, gchar tag,
 
65
                                effect_register_rebuild_func rebuild_func,
 
66
                                gpointer rebuild_func_data,
 
67
                                effect_register_get_func get_func,
 
68
                                gpointer get_func_data)
 
69
{
 
70
     struct source *s;
 
71
     s = g_malloc(sizeof(*s));
 
72
     s->tag = tag;
 
73
     s->name = name;
 
74
     s->rebuild_func = rebuild_func;
 
75
     s->rebuild_func_data = rebuild_func_data;
 
76
     s->get_func = get_func;
 
77
     s->get_func_data = get_func_data;
 
78
     s->is_new = TRUE;
 
79
     sources = g_slist_append(sources,s);
 
80
}
 
81
 
 
82
void effect_register_add_effect(gchar source_tag, const gchar *name, 
 
83
                                const gchar *title, const gchar *author, 
 
84
                                const gchar *location)
56
85
{
57
86
     struct effect *e;
58
87
     e = g_malloc(sizeof(*e));
 
88
     e->source_tag = source_tag;
59
89
     e->name = g_strdup(name);
60
90
     e->title = g_strdup(title);
61
 
     e->dialog_type = dialog_type;
62
 
     effects = g_slist_append(effects,e);
63
 
     num_effects ++;
64
 
}
65
 
 
66
 
void effect_browser_register_default_effects(void)
67
 
{     
68
 
     effect_browser_register_effect("volume",_("[B] Volume adjust/fade"),
69
 
                                    volume_dialog_get_type());
70
 
     effect_browser_register_effect("srate",_("[B] Convert samplerate"),
71
 
                                    samplerate_dialog_get_type());
72
 
     effect_browser_register_effect("ssize",_("[B] Convert sample format"),
73
 
                                    samplesize_dialog_get_type());
74
 
     effect_browser_register_effect("combine",_("[B] Combine channels"),
75
 
                                    combine_channels_dialog_get_type());
76
 
     effect_browser_register_effect("speed",_("[B] Speed"),
77
 
                                    speed_dialog_get_type());
78
 
     effect_browser_register_effect("pipe",_("[B] Pipe through program"),
79
 
                                    pipe_dialog_get_type());
 
91
     e->author = g_strdup(author);
 
92
     e->location = g_strdup(location);
 
93
     list_object_add(effect_list, e);
 
94
}
 
95
 
 
96
static void builtin_rebuild_func(gchar source_tag, gpointer user_data)
 
97
{
 
98
     gchar *author = _("Built-in");
 
99
     static const gchar loc[] = "";     
 
100
 
 
101
     effect_register_add_effect(source_tag,"volume",_("Volume adjust/fade"),
 
102
                                author,loc);
 
103
     effect_register_add_effect(source_tag,"srate",_("Convert samplerate"),
 
104
                                author,loc);
 
105
     effect_register_add_effect(source_tag,"ssize",_("Convert sample format"),
 
106
                                author,loc);
 
107
     effect_register_add_effect(source_tag,"mapchannels",_("Map channels"),
 
108
                                author,loc);
 
109
     effect_register_add_effect(source_tag,"combine",_("Combine channels"),
 
110
                                author,loc);
 
111
     effect_register_add_effect(source_tag,"speed",_("Speed"),author,loc);
 
112
     effect_register_add_effect(source_tag,"pipe",_("Pipe through program"),
 
113
                                author,loc);
 
114
}
 
115
 
 
116
static EffectDialog *builtin_get_func(gchar *name, gchar source_tag,
 
117
                                      gpointer user_data)
 
118
{
 
119
     GtkType type = -1;
 
120
     if (!strcmp(name,"volume")) type = volume_dialog_get_type();
 
121
     else if (!strcmp(name,"srate")) type = samplerate_dialog_get_type();
 
122
     else if (!strcmp(name,"ssize")) type = samplesize_dialog_get_type();
 
123
     else if (!strcmp(name,"mapchannels")) 
 
124
          type = map_channels_dialog_get_type();
 
125
     else if (!strcmp(name,"combine")) 
 
126
          type = combine_channels_dialog_get_type();
 
127
     else if (!strcmp(name,"speed")) type = speed_dialog_get_type();
 
128
     else if (!strcmp(name,"pipe")) type = pipe_dialog_get_type();
 
129
     if (type >= 0) 
 
130
          return EFFECT_DIALOG(gtk_type_new(type));
 
131
     else
 
132
          return NULL;
 
133
}
 
134
 
 
135
void effect_register_init(void)
 
136
{
 
137
     /* Add built-in effects source */
 
138
     effect_register_add_source("Built-in",'B',builtin_rebuild_func,NULL,
 
139
                                builtin_get_func,NULL);
 
140
}
 
141
 
 
142
static void effect_register_update_list(void)
 
143
{
 
144
     GSList *s;
 
145
     struct source *src;
 
146
     gboolean b = FALSE;
 
147
     
 
148
     if (effect_list == NULL)
 
149
          effect_list = list_object_new(FALSE);
 
150
 
 
151
     for (s=sources; s!=NULL; s=s->next) {
 
152
          src = (struct source *)s->data;
 
153
          if (src -> is_new) {
 
154
               /* TODO: Cache instead of requesting from source each time */
 
155
               src->rebuild_func(src->tag, src->rebuild_func_data);
 
156
               src->is_new = FALSE;
 
157
               b = TRUE;
 
158
          }
 
159
     }
 
160
     
 
161
     if (b) list_object_notify(effect_list,NULL);
 
162
}
 
163
 
 
164
void free_effect(struct effect *e)
 
165
{
 
166
     g_free(e->name);
 
167
     g_free(e->title);
 
168
     g_free(e->location);
 
169
     g_free(e->author);
 
170
     g_free(e);
 
171
}
 
172
 
 
173
void effect_register_rebuild(void)
 
174
{
 
175
     GSList *s;
 
176
     struct source *src;
 
177
     list_object_foreach(effect_list,(GFunc)free_effect,NULL);
 
178
     list_object_clear(effect_list,FALSE);
 
179
     for (s=sources; s!=NULL; s=s->next) {
 
180
          src = (struct source *)s->data;
 
181
          src->is_new = TRUE;
 
182
     }
 
183
     effect_register_update_list();
 
184
}
 
185
 
 
186
static void effect_browser_remove_effect(EffectBrowser *eb)
 
187
{
 
188
     if (eb->current_dialog >= 0) 
 
189
          gtk_container_remove
 
190
               (GTK_CONTAINER(eb->dialog_container),
 
191
                GTK_WIDGET(eb->dialogs[eb->current_dialog]));
 
192
     eb->current_dialog = -1;
80
193
}
81
194
 
82
195
static void effect_browser_destroy(GtkObject *obj)
84
197
     EffectBrowser *eb = EFFECT_BROWSER(obj);
85
198
     guint i;
86
199
     effect_browser_remove_effect(eb);
87
 
     eb->current_dialog = -1;
88
 
     if (eb->dialogs != NULL)
89
 
          for (i=0; i<num_effects; i++) 
90
 
               if (eb->dialogs[i] != NULL) {
91
 
                    gtk_widget_unref(GTK_WIDGET(eb->dialogs[i]));
92
 
               }
93
 
     g_free(eb->dialogs);
94
 
     eb->dialogs = NULL;
 
200
     for (i=0; i<EFFECT_BROWSER_CACHE_SIZE; i++) {
 
201
          if (eb->dialogs[i] != NULL) {
 
202
               gtk_widget_unref(GTK_WIDGET(eb->dialogs[i]));
 
203
               eb->dialogs[i] = NULL;
 
204
          }
 
205
     }
95
206
     if (parent_class->destroy) parent_class->destroy(obj);
96
207
}
97
208
 
122
233
     GTK_WIDGET_CLASS(klass)->delete_event = effect_browser_delete_event;
123
234
}
124
235
 
125
 
static void apply_click(GtkWidget *widget, EffectBrowser *eb)
126
 
{
127
 
     if (eb->dl->selected == NULL) {
128
 
          user_error(_("You have no open file to apply the effect to!"));
129
 
          return;
130
 
     }
131
 
     effect_dialog_apply(eb->dialogs[eb->current_dialog]);     
132
 
     if (!inifile_get_gboolean("mainwinFront",TRUE))
133
 
          gdk_window_raise(GTK_WIDGET(eb)->window);
134
 
}
135
 
 
136
236
static void effect_browser_close(EffectBrowser *eb)
137
237
{
138
238
     geom_push(eb);
139
239
     gtk_widget_destroy(GTK_WIDGET(eb));
140
240
}
141
241
 
142
 
static void ok_click(GtkWidget *widget, EffectBrowser *eb)
 
242
static void apply_click(GtkWidget *widget, EffectBrowser *eb)
143
243
{
 
244
     gboolean ca,b,mwf;
144
245
     if (eb->dl->selected == NULL) {
145
246
          user_error(_("You have no open file to apply the effect to!"));
146
247
          return;
147
248
     }
148
 
     gtk_widget_hide(GTK_WIDGET(eb));
149
 
     if (effect_dialog_apply(eb->dialogs[eb->current_dialog]))
150
 
          gtk_widget_show(GTK_WIDGET(eb));
151
 
     else
152
 
          effect_browser_close(eb);
153
 
}
154
 
 
155
 
static void effect_browser_remove_effect(EffectBrowser *eb)
156
 
{
157
 
     if (eb->current_dialog >= 0) 
158
 
          gtk_container_remove
159
 
               (GTK_CONTAINER(eb->dialog_container),
160
 
                GTK_WIDGET(eb->dialogs[eb->current_dialog]));
161
 
}
162
 
 
163
 
static void effect_browser_set_effect_main(EffectBrowser *eb, struct effect *e,
164
 
                                           gint i)
165
 
{
 
249
 
 
250
     ca = gtk_toggle_button_get_active(eb->close_after);
 
251
     mwf = inifile_get_gboolean("mainwinFront",TRUE);
 
252
 
 
253
     if (ca) gtk_widget_hide(GTK_WIDGET(eb));     
 
254
     
 
255
     b = effect_dialog_apply(eb->dialogs[eb->current_dialog]);
 
256
     
 
257
     if (ca) {
 
258
          if (b) 
 
259
               gtk_widget_show(GTK_WIDGET(eb));
 
260
          else
 
261
               effect_browser_close(eb);
 
262
     } else if (!mwf)
 
263
          gdk_window_raise(GTK_WIDGET(eb)->window);
 
264
}
 
265
 
 
266
static EffectDialog *get_effect_missing_dialog(gchar *name, gchar source_tag)
 
267
{
 
268
     EffectDialog *ed;
166
269
     GtkWidget *w;
 
270
     ed = gtk_type_new(effect_dialog_get_type());
 
271
     w = gtk_label_new(_("This effect could not be loaded."));
 
272
     gtk_container_add(ed->input_area,w);
 
273
     gtk_widget_show(w);
 
274
     return ed;
 
275
}
 
276
 
 
277
static void effect_browser_set_effect_main(EffectBrowser *eb, struct effect *e)
 
278
{
 
279
     int i;
 
280
     EffectDialog *ed;
 
281
     GSList *s;
 
282
     struct source *src;
 
283
     gchar *c;
 
284
 
167
285
     effect_browser_remove_effect(eb);
 
286
 
 
287
     /* Check dialog cache */
 
288
     for (i=0; i<EFFECT_BROWSER_CACHE_SIZE; i++) {
 
289
          if (eb->dialog_effects[i] == e) break;
 
290
     }
 
291
 
 
292
     if (i >= EFFECT_BROWSER_CACHE_SIZE) {
 
293
          /* Dialog not in cache */
 
294
 
 
295
          /* Make room in top of cache */
 
296
          for (i=0; i<EFFECT_BROWSER_CACHE_SIZE; i++) {
 
297
               if (eb->dialog_effects[i] == NULL) break;
 
298
          }
 
299
          if (i >= EFFECT_BROWSER_CACHE_SIZE) {
 
300
               /* No room in cache, throw out last element */
 
301
               i = EFFECT_BROWSER_CACHE_SIZE-1;
 
302
               gtk_object_unref(GTK_OBJECT(eb->dialogs[i]));
 
303
               eb->dialogs[i] = NULL;
 
304
               eb->dialog_effects[i] = NULL;
 
305
          }
 
306
          for (; i>0; i--) {
 
307
               eb->dialogs[i] = eb->dialogs[i-1];
 
308
               eb->dialog_effects[i] = eb->dialog_effects[i-1];
 
309
          }
 
310
 
 
311
          /* Get the new dialog */
 
312
 
 
313
          ed = NULL;
 
314
          for (s=sources; s!=NULL; s=s->next) {
 
315
               src = (struct source *)s->data;
 
316
               if (src->tag == e->source_tag) {
 
317
                    ed = src->get_func(e->name, e->source_tag,
 
318
                                       src->get_func_data);
 
319
                    effect_dialog_setup(ed, e->name, eb);
 
320
                    break;
 
321
               }
 
322
          }
 
323
 
 
324
          if (ed == NULL)
 
325
               ed = get_effect_missing_dialog(e->name,e->source_tag);     
 
326
 
 
327
          g_assert(i == 0);
 
328
          eb->dialogs[i] = ed;
 
329
          gtk_object_ref(GTK_OBJECT(ed));
 
330
          gtk_object_sink(GTK_OBJECT(ed));
 
331
          eb->dialog_effects[i] = e;
 
332
     }
 
333
 
168
334
     eb->current_dialog = i;
169
 
     if (eb->dialogs[i] == NULL) {
170
 
          w = GTK_WIDGET(gtk_type_new(e->dialog_type));
171
 
          effect_dialog_setup(EFFECT_DIALOG(w),e->name,(gpointer)eb);
172
 
          eb->dialogs[i] = EFFECT_DIALOG(w);
173
 
          gtk_widget_ref(w);
174
 
          gtk_object_sink(GTK_OBJECT(w));
175
 
          inifile_set("lastEffect",e->name);
176
 
     }
 
335
 
177
336
     gtk_container_add(eb->dialog_container,
178
337
                       GTK_WIDGET(eb->dialogs[i]));
179
338
     gtk_widget_show(GTK_WIDGET(eb->dialogs[i]));
 
339
 
 
340
     c = g_strdup_printf("%c%s",e->source_tag,e->name);
 
341
     inifile_set("lastEffect",c);
 
342
     g_free(c);
180
343
}
181
344
 
182
 
void effect_browser_invalidate_effect(EffectBrowser *eb, gchar *effect_name)
 
345
void effect_browser_invalidate_effect(EffectBrowser *eb, gchar *effect_name, 
 
346
                                      gchar source_tag)
183
347
{
184
 
     GSList *sl;
 
348
     gboolean displayed = FALSE;
185
349
     struct effect *e;
186
350
     gint i=0;
187
 
     sl = effects;
188
 
     while (1) {
189
 
          g_assert(sl != NULL);
190
 
          e = (struct effect *)sl->data;
191
 
          if (!strcmp(e->name,effect_name)) break;
192
 
          sl=sl->next;
193
 
          i++;
194
 
     }
195
 
     if (i == eb->current_dialog) {
196
 
          effect_browser_remove_effect(eb);
197
 
          eb->current_dialog = -1;
198
 
          gtk_widget_unref(GTK_WIDGET(eb->dialogs[i]));
199
 
          eb->dialogs[i] = NULL;
200
 
          effect_browser_set_effect_main(eb,e,i);
201
 
     } else if (eb->dialogs[i] != NULL) {
202
 
          gtk_widget_unref(GTK_WIDGET(eb->dialogs[i]));
203
 
          eb->dialogs[i] = NULL;
204
 
     }
 
351
 
 
352
     /* Search the cache for the effect */
 
353
     for (i=0; i<EFFECT_BROWSER_CACHE_SIZE; i++) {
 
354
          e = eb->dialog_effects[i];
 
355
          if (e != NULL && e->source_tag == source_tag && 
 
356
              !strcmp(e->name, effect_name))
 
357
               break;
 
358
     }
 
359
 
 
360
     if (i >= EFFECT_BROWSER_CACHE_SIZE) return; /* Not found */
 
361
     
 
362
     displayed = (i == eb->current_dialog);
 
363
     if (displayed) effect_browser_remove_effect(eb);
 
364
     gtk_object_unref(GTK_OBJECT(eb->dialogs[i]));
 
365
     eb->dialogs[i] = NULL;
 
366
     eb->dialog_effects[i] = NULL;
 
367
     if (displayed) effect_browser_set_effect_main(eb,e);
205
368
}
206
369
 
207
370
static void effect_browser_select_child(GtkList *list, GtkWidget *widget,
208
371
                                        gpointer user_data)
209
372
{
210
 
     EffectBrowser *eb = EFFECT_BROWSER(user_data);
211
 
     GSList *sl;
212
 
     gint i,j;
213
 
     i = gtk_list_child_position(eb->effect_list,widget);
214
 
     g_assert(i>=0);
215
 
     for (sl=effects,j=i; j>0; j--) {
216
 
          sl=sl->next;
217
 
          g_assert(sl!=NULL);
218
 
     }
219
 
     effect_browser_set_effect_main(eb,(struct effect *)(sl->data),i);
 
373
     EffectBrowser *eb = EFFECT_BROWSER(user_data);     
 
374
     struct effect *effect;
 
375
     
 
376
     effect = gtk_object_get_data(GTK_OBJECT(widget),"effectptr");
 
377
     g_assert(effect != NULL);
 
378
     effect_browser_set_effect_main(eb,effect);
 
379
     eb->list_widget_sel = GTK_LIST_ITEM(widget);
 
380
}
 
381
 
 
382
static void save_effect_order(EffectBrowser *eb)
 
383
{
 
384
     GList *l;
 
385
     gint i;
 
386
     gchar *c,*d;
 
387
     struct effect *effect;
 
388
     l = gtk_container_get_children(GTK_CONTAINER(eb->list_widget));
 
389
     for (i=0; l!=NULL; l=l->next,i++) {
 
390
          c = g_strdup_printf("effectBrowserOrder%d",i);
 
391
          effect = gtk_object_get_data(GTK_OBJECT(l->data),"effectptr");
 
392
          d = g_strdup_printf("%c%s",effect->source_tag,effect->name);
 
393
          inifile_set(c,d);
 
394
          g_free(c);
 
395
          g_free(d);
 
396
     }
 
397
     c = g_strdup_printf("effectBrowserOrder%d",i);
 
398
     inifile_set(c,NULL);
 
399
     g_free(c);
 
400
     g_list_free(l);
 
401
}
 
402
 
 
403
static void moveup_main(EffectBrowser *eb, GtkListItem *item)
 
404
{
 
405
     gint i;
 
406
     GList *l;
 
407
     i = gtk_list_child_position(GTK_LIST(eb->list_widget),
 
408
                                 GTK_WIDGET(item));
 
409
     if (i <= 0) return;
 
410
     l = g_list_append(NULL, item);
 
411
     gtk_list_remove_items_no_unref(GTK_LIST(eb->list_widget),l);
 
412
     gtk_list_insert_items(GTK_LIST(eb->list_widget),l,i-1);
 
413
     gtk_list_item_select(GTK_LIST_ITEM(eb->list_widget_sel));
 
414
     save_effect_order(eb);    
 
415
}
 
416
 
 
417
static void movedown_main(EffectBrowser *eb, GtkListItem *item)
 
418
{
 
419
     gint i;
 
420
     GList *l;
 
421
     i = gtk_list_child_position(GTK_LIST(eb->list_widget),
 
422
                                 GTK_WIDGET(item));
 
423
     l = g_list_append(NULL, item);
 
424
     gtk_list_remove_items_no_unref(GTK_LIST(eb->list_widget),l);
 
425
     gtk_list_insert_items(GTK_LIST(eb->list_widget),l,i+1);
 
426
     gtk_list_item_select(GTK_LIST_ITEM(eb->list_widget_sel));
 
427
     save_effect_order(eb);    
 
428
}
 
429
 
 
430
static void movetop_main(EffectBrowser *eb, GtkListItem *item)
 
431
{
 
432
     GList *l;
 
433
     l = g_list_append(NULL, item);
 
434
     gtk_list_remove_items_no_unref(GTK_LIST(eb->list_widget),l);
 
435
     gtk_list_prepend_items(GTK_LIST(eb->list_widget),l);
 
436
     gtk_list_item_select(GTK_LIST_ITEM(eb->list_widget_sel));
 
437
     save_effect_order(eb);    
 
438
}
 
439
 
 
440
static void movebot_main(EffectBrowser *eb, GtkListItem *item)
 
441
{
 
442
     GList *l;
 
443
     l = g_list_append(NULL, item);
 
444
     gtk_list_remove_items_no_unref(GTK_LIST(eb->list_widget),l);
 
445
     gtk_list_append_items(GTK_LIST(eb->list_widget),l);
 
446
     gtk_list_item_select(GTK_LIST_ITEM(eb->list_widget_sel));
 
447
     save_effect_order(eb);    
 
448
}
 
449
 
 
450
static EffectBrowser *clicked_eb;
 
451
 
 
452
static void list_item_moveup(GtkMenuItem *menuitem, gpointer user_data)
 
453
{
 
454
     moveup_main(clicked_eb, clicked_eb->list_widget_clicked);
 
455
}
 
456
 
 
457
static void list_item_movedown(GtkMenuItem *menuitem, gpointer user_data)
 
458
{
 
459
     movedown_main(clicked_eb, clicked_eb->list_widget_clicked);
 
460
}
 
461
 
 
462
static void list_item_movetotop(GtkMenuItem *menuitem, gpointer user_data)
 
463
{
 
464
     movetop_main(clicked_eb, clicked_eb->list_widget_clicked);
 
465
}
 
466
 
 
467
static void list_item_movetobottom(GtkMenuItem *menuitem, gpointer user_data)
 
468
{
 
469
     movebot_main(clicked_eb, clicked_eb->list_widget_clicked);
 
470
}
 
471
 
 
472
static void list_item_sort_main(EffectBrowser *eb, GCompareFunc compfunc)
 
473
{
 
474
     /* Not the quickest way, but preserves original order if compfunc 
 
475
        returns >0 when objects are equal */
 
476
     GList *k,*l,*m=NULL;
 
477
     gint i;
 
478
     struct effect *e;
 
479
     gchar *c,*d;
 
480
     k = gtk_container_get_children(GTK_CONTAINER(eb->list_widget));
 
481
     for (l=k; l!=NULL; l=l->next) {
 
482
          e = gtk_object_get_data(GTK_OBJECT(l->data),"effectptr");
 
483
          g_assert(e != NULL);
 
484
          m = g_list_insert_sorted(m,e,compfunc);
 
485
     }
 
486
     g_list_free(k);
 
487
     for (l=m,i=0; l!=NULL; l=l->next,i++) {
 
488
          e = (struct effect *)l->data;
 
489
          c = g_strdup_printf("effectBrowserOrder%d",i);
 
490
          d = g_strdup_printf("%c%s",e->source_tag,e->name);
 
491
          inifile_set(c,d);
 
492
          g_free(d);
 
493
          g_free(c);
 
494
     }
 
495
     c = g_strdup_printf("effectBrowserOrder%d",i);
 
496
     inifile_set(c,NULL);
 
497
     g_free(c);
 
498
     g_list_free(m);
 
499
     list_widget_rebuild(NULL,NULL,eb);
 
500
}
 
501
 
 
502
gint title_sort_func(gconstpointer a, gconstpointer b)
 
503
{
 
504
     struct effect const *ae = a, *be = b;
 
505
     int i;
 
506
     i = strcmp(ae->title,be->title);
 
507
     if (i==0) return 1; else return i;
 
508
}
 
509
 
 
510
gint auth_sort_func(gconstpointer a, gconstpointer b)
 
511
{
 
512
     struct effect const *ae = a, *be = b;
 
513
     int i;
 
514
     i = strcmp(ae->author,be->author);
 
515
     if (i==0) return 1; else return i;
 
516
}
 
517
 
 
518
gint type_sort_func(gconstpointer a, gconstpointer b)
 
519
{
 
520
     struct effect const *ae = a, *be = b;
 
521
     int i;
 
522
     i = ae->source_tag - be->source_tag;
 
523
     if (i==0) return 1; else return i;
 
524
}
 
525
 
 
526
gint loc_sort_func(gconstpointer a, gconstpointer b)
 
527
{
 
528
     struct effect const *ae = a, *be = b;
 
529
     int i;
 
530
     i = strcmp(ae->location,be->location);
 
531
     if (i==0) return 1; else return i;
 
532
}
 
533
 
 
534
 
 
535
static void list_item_sortbytitle(GtkMenuItem *menuitem, gpointer user_data)
 
536
{     
 
537
     list_item_sort_main(clicked_eb, title_sort_func);
 
538
}
 
539
 
 
540
static void list_item_sortbytype(GtkMenuItem *menuitem, gpointer user_data)
 
541
{
 
542
     list_item_sort_main(clicked_eb, type_sort_func);
 
543
}
 
544
 
 
545
static void list_item_sortbyloc(GtkMenuItem *menuitem, gpointer user_data)
 
546
{
 
547
     list_item_sort_main(clicked_eb, loc_sort_func);
 
548
}
 
549
 
 
550
static void list_item_sortbyauth(GtkMenuItem *menuitem, gpointer user_data)
 
551
{
 
552
     list_item_sort_main(clicked_eb, auth_sort_func);
 
553
}
 
554
 
 
555
static void list_item_unsort(GtkMenuItem *menuitem, gpointer user_data)
 
556
{
 
557
     inifile_set("effectBrowserOrder0",NULL);
 
558
     list_widget_rebuild(NULL,NULL,clicked_eb);
 
559
}
 
560
 
 
561
static void list_item_rebuild(GtkMenuItem *menuitem, gpointer user_data)
 
562
{
 
563
     effect_register_rebuild();
 
564
}
 
565
 
 
566
static gchar *translate_menu_path(const gchar *path, gpointer func_data)
 
567
{
 
568
    return _(path);
 
569
}
 
570
 
 
571
static gint list_item_button_press(GtkWidget *widget, GdkEventButton *event,
 
572
                                   gpointer user_data)
 
573
{
 
574
     EffectBrowser *eb = EFFECT_BROWSER(user_data);
 
575
     static GtkItemFactory *item_factory = NULL;
 
576
     GtkWidget *w;
 
577
     static GtkItemFactoryEntry menu_items[] = {
 
578
          { N_("/Move Up"),        NULL, list_item_moveup,      0, NULL },
 
579
          { N_("/Move Down"),      NULL, list_item_movedown,    0, NULL },
 
580
          { N_("/Move to Top"),    NULL, list_item_movetotop,   0, NULL },
 
581
          { N_("/Move to Bottom"), NULL, list_item_movetobottom,0, NULL },
 
582
          { "/sep1",           NULL, NULL,                  0, "<Separator>" },
 
583
          { N_("/Sort by Name"), NULL, list_item_sortbytitle, 0, NULL },
 
584
          { N_("/Sort by Type"), NULL, list_item_sortbytype, 0, NULL },
 
585
          { N_("/Sort by Location"), NULL, list_item_sortbyloc,0,NULL },
 
586
          { N_("/Sort by Author"), NULL, list_item_sortbyauth,0, NULL },
 
587
          { "/sep2", NULL, NULL, 0, "<Separator>" },
 
588
          { N_("/Restore Order"), NULL, list_item_unsort, 0, NULL },
 
589
          { N_("/Rebuild Effect List"), NULL, list_item_rebuild,0,NULL }
 
590
     };
 
591
 
 
592
     if (event->button == 3) {
 
593
          if (item_factory == NULL) {
 
594
               item_factory = gtk_item_factory_new(GTK_TYPE_MENU,"<popup>",NULL);
 
595
#ifdef ENABLE_NLS
 
596
               gtk_item_factory_set_translate_func(item_factory, 
 
597
                                                   translate_menu_path, NULL, NULL);
 
598
#endif
 
599
               gtk_item_factory_create_items(item_factory,
 
600
                                             ARRAY_LENGTH(menu_items),
 
601
                                             menu_items,NULL);
 
602
          }
 
603
          clicked_eb = eb;
 
604
          eb->list_widget_clicked = GTK_LIST_ITEM(widget);
 
605
          w = gtk_item_factory_get_widget(item_factory,"<popup>");
 
606
          gtk_menu_popup(GTK_MENU(w),NULL,NULL,NULL,NULL,event->button,
 
607
                         event->time);
 
608
     }
 
609
     return FALSE;
 
610
}
 
611
 
 
612
static void add_list_item_main(struct effect *e, GtkList *l, EffectBrowser *eb)
 
613
{
 
614
     gchar *c,*d;
 
615
     GtkWidget *w;
 
616
     c = g_strdup_printf("[%c] %s",e->source_tag,e->title);
 
617
 
 
618
     /* Translate here for keeping compatibility with old translations */
 
619
     /* New translations should translate the title without the prefix */
 
620
     if (e->source_tag == 'B' || e->source_tag == 'S') d = _(c); else d = c;
 
621
 
 
622
     w = gtk_list_item_new_with_label(d);
 
623
     g_free(c);
 
624
     gtk_object_set_data(GTK_OBJECT(w),"effectptr",e);
 
625
     gtk_signal_connect(GTK_OBJECT(w),"button_press_event",
 
626
                        GTK_SIGNAL_FUNC(list_item_button_press),eb);
 
627
     gtk_container_add(GTK_CONTAINER(l),w);
 
628
     gtk_widget_show(w);
 
629
}
 
630
 
 
631
static void add_list_item(gpointer item, gpointer user_data)
 
632
{
 
633
     EffectBrowser *eb = EFFECT_BROWSER(user_data);
 
634
     struct effect *e = (struct effect *)item;
 
635
     add_list_item_main(e,eb->list_widget,eb);
 
636
}
 
637
 
 
638
static void top_click(GtkButton *button, gpointer user_data)
 
639
{     
 
640
     EffectBrowser *eb = EFFECT_BROWSER(user_data);
 
641
     movetop_main(eb,eb->list_widget_sel);
 
642
}
 
643
 
 
644
static void bottom_click(GtkButton *button, gpointer user_data)
 
645
{
 
646
     EffectBrowser *eb = EFFECT_BROWSER(user_data);
 
647
     movebot_main(eb,eb->list_widget_sel);
 
648
}
 
649
 
 
650
static void up_click(GtkButton *button, gpointer user_data)
 
651
{
 
652
     EffectBrowser *eb = EFFECT_BROWSER(user_data);
 
653
     moveup_main(eb, eb->list_widget_sel);
 
654
}
 
655
 
 
656
static void down_click(GtkButton *button, gpointer user_data)
 
657
{
 
658
     EffectBrowser *eb = EFFECT_BROWSER(user_data);
 
659
     movedown_main(eb, eb->list_widget_sel);
 
660
}
 
661
 
 
662
static void add_list_widget_items(GtkList *list, EffectBrowser *eb)
 
663
{
 
664
     gint i;
 
665
     gchar *c,*d;
 
666
     GList *l;
 
667
     struct effect *e;
 
668
     if (inifile_get("effectBrowserOrder0",NULL) == NULL) {
 
669
          list_object_foreach(effect_list,add_list_item,eb);
 
670
     } else {
 
671
          for (l=effect_list->list; l!=NULL; l=l->next) {
 
672
               e = (struct effect *)l->data;
 
673
               e->process_tag = FALSE;
 
674
          }
 
675
          for (i=0; ; i++) {
 
676
               c = g_strdup_printf("effectBrowserOrder%d",i);
 
677
               d = inifile_get(c,NULL);
 
678
               g_free(c);
 
679
               if (d == NULL) break;
 
680
               for (l=effect_list->list; l!=NULL; l=l->next) {
 
681
                    e = (struct effect *)l->data;
 
682
                    if (e->process_tag) continue;
 
683
                    if (e->source_tag != d[0] || strcmp(e->name,d+1)) continue;
 
684
                    add_list_item_main(e,list,eb);
 
685
                    e->process_tag = TRUE;
 
686
                    break;
 
687
               }
 
688
          }
 
689
          for (l=effect_list->list; l!=NULL; l=l->next) {
 
690
               e = (struct effect *)l->data;
 
691
               if (!e->process_tag)
 
692
                    add_list_item_main(e,list,eb);
 
693
          }
 
694
     }
 
695
}
 
696
 
 
697
static void list_widget_rebuild(gpointer dummy, gpointer dummy2, 
 
698
                                EffectBrowser *eb)
 
699
{
 
700
     gtk_list_clear_items(eb->list_widget,0,-1);
 
701
     add_list_widget_items(eb->list_widget, eb);
220
702
}
221
703
 
222
704
static void effect_browser_init(EffectBrowser *eb)
223
705
{
224
 
     GtkWidget *b,*b1,*b1w,*b2,*b21,*b21w,*b22,*b23,*b24,*b241,*b242;
225
 
     GtkWidget *b243,*w;
226
 
     GSList *sl;
 
706
     GtkWidget *b,*b1,*b11,*b11w,*b12,*b121,*b122,*b123,*b124,*b2,*b21;
 
707
     GtkWidget *b21w,*b22,*b23,*b24,*b25,*b251,*b252;
227
708
     GtkAccelGroup* ag;
228
 
     struct effect *e;
229
709
     gchar *c,*d;
230
710
     gint x;
231
711
 
 
712
     eb->list_widget_sel = NULL;
 
713
 
232
714
     ag = gtk_accel_group_new();
233
715
 
234
 
     eb->dialogs = g_malloc0(num_effects * sizeof(eb->dialogs[0]));
 
716
     memset(eb->dialogs,0,sizeof(eb->dialogs));
 
717
     memset(eb->dialog_effects,0,sizeof(eb->dialog_effects));
235
718
     eb->current_dialog = -1;
236
719
     
237
 
     b1w = gtk_list_new();
238
 
     eb->effect_list = GTK_LIST(b1w);
239
 
     gtk_list_set_selection_mode(GTK_LIST(b1w),GTK_SELECTION_SINGLE);
240
 
 
241
 
     for (sl=effects; sl!=NULL; sl=sl->next) {
242
 
          e = (struct effect *)sl->data;
243
 
          w = gtk_list_item_new_with_label(e->title);
244
 
          gtk_container_add(GTK_CONTAINER(b1w),w);
245
 
          gtk_widget_show(w);
246
 
     }
247
 
 
248
 
     b1 = gtk_scrolled_window_new(NULL,NULL);
249
 
     gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(b1),
 
720
     b11w = gtk_list_new();
 
721
     eb->list_widget = GTK_LIST(b11w);
 
722
     gtk_list_set_selection_mode(GTK_LIST(b11w),GTK_SELECTION_SINGLE);
 
723
 
 
724
     effect_register_update_list();
 
725
     add_list_widget_items(eb->list_widget,eb);
 
726
 
 
727
     gtk_signal_connect(GTK_OBJECT(effect_list),"item-notify",
 
728
                        GTK_SIGNAL_FUNC(list_widget_rebuild),eb);
 
729
 
 
730
     b11 = gtk_scrolled_window_new(NULL,NULL);
 
731
     gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(b11),
250
732
                                    GTK_POLICY_AUTOMATIC,GTK_POLICY_AUTOMATIC);
251
 
     gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(b1),b1w);
252
 
     gtk_widget_set_usize(GTK_WIDGET(b1),150,150);
253
 
     eb->effect_list_container = GTK_CONTAINER(b1);
 
733
     gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(b11),b11w);
 
734
     gtk_widget_set_usize(GTK_WIDGET(b11),150,150);
 
735
     eb->effect_list_container = GTK_CONTAINER(b11);
 
736
 
 
737
#ifdef GTK_STOCK_GOTO_TOP
 
738
     b121 = gtk_button_new_from_stock(GTK_STOCK_GOTO_TOP);
 
739
#else
 
740
     b121 = gtk_button_new_with_label(_("Top"));
 
741
#endif
 
742
     gtk_signal_connect(GTK_OBJECT(b121),"clicked",
 
743
                        GTK_SIGNAL_FUNC(top_click),eb);
 
744
#ifdef GTK_STOCK_GO_UP
 
745
     b122 = gtk_button_new_from_stock(GTK_STOCK_GO_UP);
 
746
#else
 
747
     b122 = gtk_button_new_with_label(_("Up"));
 
748
#endif
 
749
     gtk_signal_connect(GTK_OBJECT(b122),"clicked",
 
750
                        GTK_SIGNAL_FUNC(up_click),eb);
 
751
#ifdef GTK_STOCK_GO_DOWN
 
752
     b123 = gtk_button_new_from_stock(GTK_STOCK_GO_DOWN);
 
753
#else
 
754
     b123 = gtk_button_new_with_label(_("Down"));
 
755
#endif
 
756
     gtk_signal_connect(GTK_OBJECT(b123),"clicked",
 
757
                        GTK_SIGNAL_FUNC(down_click),eb);
 
758
#ifdef GTK_STOCK_GOTO_BOTTOM
 
759
     b124 = gtk_button_new_from_stock(GTK_STOCK_GOTO_BOTTOM);
 
760
#else
 
761
     b124 = gtk_button_new_with_label(_("Bottom"));
 
762
#endif
 
763
     gtk_signal_connect(GTK_OBJECT(b124),"clicked",
 
764
                        GTK_SIGNAL_FUNC(bottom_click),eb);
 
765
 
 
766
     b12 = gtk_hbox_new(FALSE,5);
 
767
     gtk_box_pack_start(GTK_BOX(b12),b121,FALSE,FALSE,0);
 
768
     gtk_box_pack_start(GTK_BOX(b12),b122,FALSE,FALSE,0);
 
769
     gtk_box_pack_start(GTK_BOX(b12),b123,FALSE,FALSE,0);
 
770
     gtk_box_pack_start(GTK_BOX(b12),b124,FALSE,FALSE,0);
 
771
 
 
772
     b1 = gtk_vbox_new(FALSE,5);
 
773
     gtk_box_pack_start(GTK_BOX(b1),b11,TRUE,TRUE,0);
 
774
     gtk_box_pack_start(GTK_BOX(b1),b12,FALSE,FALSE,0);
254
775
 
255
776
     b21w = gtk_alignment_new(0.5,0.5,1.0,1.0);
256
777
     eb->dialog_container = GTK_CONTAINER(b21w);
265
786
     b23 = gtk_hbox_new(FALSE,3);
266
787
     eb->mw_list_box = GTK_BOX(b23);
267
788
 
268
 
     b241 = gtk_button_new_with_label(_("OK"));
269
 
     gtk_widget_add_accelerator (b241, "clicked", ag, GDK_KP_Enter, 0, (GtkAccelFlags) 0);
270
 
     gtk_widget_add_accelerator (b241, "clicked", ag, GDK_Return, 0, (GtkAccelFlags) 0);
271
 
     gtk_signal_connect(GTK_OBJECT(b241),"clicked",(GtkSignalFunc)ok_click,eb);
 
789
     b24 = gtk_check_button_new_with_label(_("Close dialog after applying "
 
790
                                             "effect"));
 
791
     eb->close_after = GTK_TOGGLE_BUTTON(b24);
272
792
 
273
 
     b242 = gtk_button_new_with_label(_("Apply"));
274
 
     gtk_signal_connect(GTK_OBJECT(b242),"clicked",(GtkSignalFunc)apply_click,
 
793
#ifdef GTK_STOCK_APPLY
 
794
     b251 = gtk_button_new_from_stock(GTK_STOCK_APPLY);
 
795
#else
 
796
     b251 = gtk_button_new_with_label(_("Apply"));
 
797
#endif
 
798
     gtk_widget_add_accelerator (b251, "clicked", ag, GDK_KP_Enter, 0, (GtkAccelFlags) 0);
 
799
     gtk_widget_add_accelerator (b251, "clicked", ag, GDK_Return, 0, (GtkAccelFlags) 0);
 
800
     gtk_signal_connect(GTK_OBJECT(b251),"clicked",(GtkSignalFunc)apply_click,
275
801
                        eb);
276
 
     
277
 
     b243 = gtk_button_new_with_label(_("Close"));
278
 
     gtk_widget_add_accelerator (b243, "clicked", ag, GDK_Escape, 0, (GtkAccelFlags) 0);
279
 
     gtk_signal_connect_object(GTK_OBJECT(b243),"clicked",
 
802
 
 
803
#ifdef GTK_STOCK_CLOSE
 
804
     b252 = gtk_button_new_from_stock(GTK_STOCK_CLOSE);
 
805
#else
 
806
     b252 = gtk_button_new_with_label(_("Close"));
 
807
#endif
 
808
     gtk_widget_add_accelerator (b252, "clicked", ag, GDK_Escape, 0, (GtkAccelFlags) 0);
 
809
     gtk_signal_connect_object(GTK_OBJECT(b252),"clicked",
280
810
                               (GtkSignalFunc)effect_browser_close,
281
811
                               GTK_OBJECT(eb));
282
812
 
283
 
     b24 = gtk_hbutton_box_new(); 
284
 
     gtk_box_pack_start(GTK_BOX(b24),b241,FALSE,TRUE,3);
285
 
     gtk_box_pack_start(GTK_BOX(b24),b242,FALSE,TRUE,3);
286
 
     gtk_box_pack_start(GTK_BOX(b24),b243,FALSE,TRUE,3);
 
813
     b25 = gtk_hbutton_box_new(); 
 
814
     gtk_box_pack_start(GTK_BOX(b25),b251,FALSE,TRUE,3);
 
815
     gtk_box_pack_start(GTK_BOX(b25),b252,FALSE,TRUE,3);
287
816
 
288
817
     b2 = gtk_vbox_new(FALSE,5);     
289
818
     gtk_box_pack_start(GTK_BOX(b2),b21,TRUE,TRUE,0);
 
819
     gtk_box_pack_end(GTK_BOX(b2),b25,FALSE,FALSE,0);
290
820
     gtk_box_pack_end(GTK_BOX(b2),b24,FALSE,FALSE,0);
291
821
     gtk_box_pack_end(GTK_BOX(b2),b23,FALSE,TRUE,0);
292
822
     gtk_box_pack_end(GTK_BOX(b2),b22,FALSE,TRUE,0);
338
868
 
339
869
GtkWidget *effect_browser_new(Document *doc)
340
870
{
341
 
     return effect_browser_new_with_effect(doc,"volume");
 
871
     return effect_browser_new_with_effect(doc,"volume",'B',FALSE);
342
872
}
343
873
 
344
 
GtkWidget *effect_browser_new_with_effect(Document *doc, gchar *effect)
 
874
GtkWidget *effect_browser_new_with_effect(Document *doc, gchar *effect, 
 
875
                                          gchar source_tag, 
 
876
                                          gboolean close_after)
345
877
{
346
878
     GtkWidget *w;
347
879
     EffectBrowser *eb = 
348
880
          EFFECT_BROWSER(gtk_type_new(effect_browser_get_type()));
349
 
     gtk_signal_connect(GTK_OBJECT(eb->effect_list),"select_child",
 
881
     gtk_signal_connect(GTK_OBJECT(eb->list_widget),"select_child",
350
882
                        (GtkSignalFunc)effect_browser_select_child,eb);
351
883
 
352
884
     w = document_list_new(doc);
357
889
     gtk_box_pack_end(GTK_BOX(eb->mw_list_box),w,FALSE,FALSE,0);
358
890
     gtk_widget_show(w);     
359
891
 
360
 
     if (effect == NULL) effect = inifile_get("lastEffect","volume");
361
 
     effect_browser_set_effect(eb,effect);
362
 
     if (eb->current_dialog == -1) effect_browser_set_effect(eb,"volume");
 
892
     if (effect == NULL) {
 
893
          effect = inifile_get("lastEffect","Bvolume");
 
894
          source_tag = effect[0];
 
895
          effect++;
 
896
     }
 
897
     effect_browser_set_effect(eb,effect,source_tag);
 
898
     if (eb->current_dialog < 0) effect_browser_set_effect(eb,"volume",'B');
363
899
     g_assert(eb->current_dialog >= 0);
 
900
     gtk_toggle_button_set_active(eb->close_after,close_after);
364
901
     return GTK_WIDGET(eb);
365
902
}
366
903
 
367
 
void effect_browser_set_effect(EffectBrowser *eb, gchar *effect)
 
904
void effect_browser_set_effect(EffectBrowser *eb, gchar *effect, 
 
905
                               gchar source_tag)
368
906
{
369
907
     struct effect *e;
370
 
     GSList *s;
371
 
     gint i=0;
372
 
 
373
 
     s=effects;
374
 
     while (s != NULL) {
375
 
          e=(struct effect *)s->data;
376
 
          if (!strcmp(e->name,effect)) break;
377
 
          s=s->next;
378
 
          i++;
 
908
     GList *l,*w;
 
909
     gpointer p;
 
910
     
 
911
     for (l=effect_list->list; l!=NULL; l=l->next) {
 
912
          e = (struct effect *)l->data;
 
913
          if (e->source_tag == source_tag && !strcmp(e->name, effect)) {
 
914
               /* Find the list item which points to this effect */
 
915
               w = gtk_container_get_children(GTK_CONTAINER(eb->list_widget));
 
916
               for (; w!=NULL; w=w->next) {
 
917
                    p = gtk_object_get_data(GTK_OBJECT(w->data),"effectptr");
 
918
                    g_assert(p != NULL);
 
919
                    if (p == e) {
 
920
                         gtk_list_select_child(eb->list_widget,
 
921
                                               GTK_WIDGET(w->data));
 
922
                         return;
 
923
                    }
 
924
               }
 
925
               /* Effect exists but not in list, shouldn't happen */
 
926
               g_assert_not_reached();
 
927
          }       
379
928
     }
380
 
     if (s != NULL) 
381
 
          gtk_list_select_item(eb->effect_list,i);
 
929
     /* Effect doesn't exist - do nothing */
382
930
}
383
931
 
384
932
void effect_browser_shutdown(void)
386
934
     if (inifile_get_gboolean("useGeometry",FALSE))
387
935
          geometry_stack_save_to_inifile("effectGeometry",geometry_stack);  
388
936
}
 
937