~ubuntu-branches/ubuntu/wily/alsaplayer/wily

« back to all changes in this revision

Viewing changes to interface/gtk/ScopesWindow.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Hubert Chathi
  • Date: 2007-10-10 15:33:10 UTC
  • mto: (9.2.5 sid)
  • mto: This revision was merged to the branch mainline in revision 15.
  • Revision ID: james.westby@ubuntu.com-20071010153310-h3holq75eu2cigb0
Tags: upstream-0.99.80~rc4
ImportĀ upstreamĀ versionĀ 0.99.80~rc4

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*  ScopesWindow.cpp
2
 
 *  Copyright (C) 1999-2002 Andy Lo A Foe <andy@alsaplayer.org>
3
 
 *
4
 
 *  This program is free software; you can redistribute it and/or modify
5
 
 *  it under the terms of the GNU General Public License as published by
6
 
 *  the Free Software Foundation; either version 2 of the License, or
7
 
 *  (at your option) any later version.
8
 
 *
9
 
 *  This program is distributed in the hope that it will be useful,
10
 
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 
 *  GNU General Public License for more details.
13
 
 *
14
 
 *  You should have received a copy of the GNU General Public License
15
 
 *  along with this program; if not, write to the Free Software
16
 
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17
 
 *
18
 
 *  $Id: ScopesWindow.cpp 954 2003-04-08 15:23:31Z adnans $
19
 
 *
20
 
*/ 
21
 
#include "ScopesWindow.h"
22
 
#include "CorePlayer.h"
23
 
#include "Effects.h"
24
 
#include "support.h"
25
 
#include "gladesrc.h"
26
 
#include "gtk_interface.h"
27
 
#include "pixmaps/note.xpm"
28
 
#include "alsaplayer_error.h"
29
 
#include "alsaplayer_fft.h"
30
 
#include "prefs.h"
31
 
#include <pthread.h>
32
 
#include <dlfcn.h>
33
 
#include <math.h>
34
 
 
35
 
extern int global_scopes_show;
36
 
static GtkWidget *scopes_window = (GtkWidget *)NULL;
37
 
static GdkPixmap *active_pix = (GdkPixmap *)NULL;
38
 
static GdkBitmap *active_mask = (GdkBitmap *)NULL;
39
 
static scope_entry *root_scope = NULL;
40
 
static pthread_mutex_t sl_mutex;
41
 
 
42
 
void dl_close_scopes()
43
 
{
44
 
        scope_entry *current = root_scope;
45
 
 
46
 
        while (current) {
47
 
                if (current->sp) {
48
 
                        dlclose(current->sp->handle);
49
 
                }       
50
 
                current = current->next;
51
 
        }       
52
 
}
53
 
 
54
 
void scope_entry_destroy_notify(gpointer)
55
 
{
56
 
}
57
 
 
58
 
#define SCOPE_BUFFER 2048
59
 
 
60
 
bool  scope_feeder_func(void *arg, void *data, int size) 
61
 
{
62
 
        static char buf[32768];
63
 
        static int latency = -1;
64
 
        static int fft_buf[512];
65
 
        static int fill = 0;
66
 
        static int left = 0;
67
 
        static int init = 0;
68
 
        static int buf_size = 0;
69
 
        static AlsaNode *the_node = NULL;
70
 
        int i;
71
 
        short *sound;
72
 
        int *left_pos;
73
 
        int *right_pos;
74
 
 
75
 
        static double fftmult[FFT_BUFFER_SIZE / 2 + 1];
76
 
 
77
 
        static sound_sample left_actEq[SCOPE_BUFFER];
78
 
        static double left_fftout[FFT_BUFFER_SIZE / 2 + 1];
79
 
        static fft_state *left_fftstate;
80
 
 
81
 
        static sound_sample right_actEq[SCOPE_BUFFER];
82
 
        static double right_fftout[FFT_BUFFER_SIZE / 2 + 1];
83
 
        static fft_state *right_fftstate;
84
 
 
85
 
        sound_sample *left_newset;
86
 
        sound_sample *right_newset;
87
 
 
88
 
        size <<= 1; // To bytes again
89
 
        
90
 
        if (size > 32768) 
91
 
                return true;
92
 
        if (!init) {
93
 
                for(i = 0; i <= FFT_BUFFER_SIZE / 2 + 1; i++) {
94
 
                        double mult = (double)128 / ((FFT_BUFFER_SIZE * 16384) ^ 2);
95
 
                        mult *= log(i + 1) / log(2);
96
 
                        mult *= 3;
97
 
                        fftmult[i] = mult;
98
 
                }
99
 
                right_fftstate = fft_init();
100
 
                left_fftstate = fft_init();
101
 
                if (!left_fftstate || !right_fftstate)
102
 
                        alsaplayer_error("WARNING: could not do fft_init()");
103
 
                buf_size = SCOPE_BUFFER <= (FFT_BUFFER_SIZE * 2) ? SCOPE_BUFFER : FFT_BUFFER_SIZE;
104
 
                CorePlayer *the_coreplayer = (CorePlayer *)arg;
105
 
                if (the_coreplayer) {
106
 
                        the_node = the_coreplayer->GetNode();
107
 
                }
108
 
                if (the_node) {
109
 
                        latency = the_node->GetLatency();
110
 
                }
111
 
                if (latency < SCOPE_BUFFER)
112
 
                        latency = SCOPE_BUFFER;
113
 
                //init_effects();
114
 
                
115
 
                init = 1;       
116
 
        }       
117
 
 
118
 
        scope_entry *se = root_scope;
119
 
 
120
 
        //buffer_effect(data, size);
121
 
 
122
 
        if (fill + size >= SCOPE_BUFFER) {
123
 
                left = SCOPE_BUFFER - fill;
124
 
                memcpy(buf + fill, data, left);
125
 
 
126
 
                // Do global FFT
127
 
                left_newset = left_actEq;
128
 
                right_newset = right_actEq;
129
 
                
130
 
                sound = (short *)buf;
131
 
                //sound = (short *)delay_feed(latency, SCOPE_BUFFER);
132
 
                
133
 
                for (i = 0; i < buf_size; i++) {
134
 
                        *left_newset++ = (sound_sample)((int)(*sound));
135
 
                        *right_newset++ = (sound_sample)((int)(*(sound+1)));
136
 
                        sound +=2;
137
 
                }
138
 
                
139
 
                fft_perform(right_actEq, right_fftout, right_fftstate);
140
 
                fft_perform(left_actEq, left_fftout, left_fftstate);
141
 
                        
142
 
                for (i = 0, left_pos = fft_buf, right_pos = fft_buf + 256; i < 256; i++) {
143
 
                        left_pos[i] = (int)(sqrt(left_fftout[i + 1])) >> 8; //* fftmult[i]);
144
 
                        right_pos[i] = (int)(sqrt(right_fftout[i + 1])) >> 8; //* fftmult[i]);
145
 
                }       
146
 
                while (se && se->sp && se->active) {
147
 
                        if (se->sp->running()) {
148
 
                                if (se->sp->set_data)
149
 
                                        se->sp->set_data((short *)buf, SCOPE_BUFFER >> 1);
150
 
                                if (se->sp->set_fft)
151
 
                                        se->sp->set_fft((int *)fft_buf, 256, 2);
152
 
                        }       
153
 
                        if (se->next) 
154
 
                                se = se->next;
155
 
                        else 
156
 
                                break;
157
 
                }
158
 
                // Copy the remainder
159
 
                fill = 0;
160
 
                memcpy(buf + fill, ((char *)data) + left, size - left);
161
 
        } else {
162
 
                memcpy(buf + fill, data, size);
163
 
                fill += size;
164
 
        }       
165
 
        return true;
166
 
}
167
 
 
168
 
 
169
 
void apUnregiserScopePlugins()
170
 
{
171
 
        scope_entry *current = root_scope;
172
 
        
173
 
        pthread_mutex_lock(&sl_mutex);
174
 
        while (current && current->sp) {
175
 
                //printf("closing and unloading scope plugin %s\n", current->sp->name);
176
 
                current->active = 0;
177
 
                current->sp->shutdown();
178
 
                current = current->next;
179
 
        }
180
 
        pthread_mutex_unlock(&sl_mutex);
181
 
}       
182
 
 
183
 
 
184
 
int apRegisterScopePlugin(scope_plugin *plugin)
185
 
{
186
 
        GtkWidget *list;
187
 
        char *list_item[2];
188
 
        scope_entry *se;
189
 
        if (!scopes_window) {
190
 
                printf("No scopes_window\n");
191
 
                return 0;
192
 
        }       
193
 
        list = (GtkWidget *)gtk_object_get_data(GTK_OBJECT(scopes_window),
194
 
                        "list");
195
 
        se = new scope_entry;
196
 
        se->next = (scope_entry *)NULL;
197
 
        se->sp = plugin;
198
 
        if (se->sp->version != SCOPE_PLUGIN_VERSION) {
199
 
                alsaplayer_error("Wrong version number on scope plugin (v%d, wanted v%d)",
200
 
                        se->sp->version - 0x1000,
201
 
                        SCOPE_PLUGIN_VERSION - 0x1000);
202
 
                delete se;
203
 
                return -1;
204
 
        }               
205
 
        se->active = 0;
206
 
 
207
 
        // Add new scope to GtkClist
208
 
        list_item[0] = g_strdup(" ");
209
 
        list_item[1] = g_strdup(se->sp->name);
210
 
        int index = gtk_clist_append(GTK_CLIST(list), list_item);
211
 
        gtk_clist_set_row_data_full(GTK_CLIST(list), index, se, scope_entry_destroy_notify);
212
 
 
213
 
        // Init scope
214
 
        se->sp->init(NULL);
215
 
        // Add scope to scope list
216
 
        // NOTE: WE CURRENTLY NEVER UNLOAD SCOPES
217
 
        pthread_mutex_lock(&sl_mutex);  
218
 
        if (root_scope == NULL) {
219
 
                //printf("registering first scope...\n");
220
 
                root_scope = se;
221
 
                root_scope->next = (scope_entry *)NULL;
222
 
                root_scope->active = 1;
223
 
        } else { // Not root scope, so insert it at the start
224
 
                se->next = root_scope->next;
225
 
                se->active = 1;
226
 
                root_scope->next = se;
227
 
        }
228
 
        pthread_mutex_unlock(&sl_mutex);
229
 
        //fprintf(stdout, "Loading Scope plugin: %s (%x)\n", se->sp->name, se->sp->handle);
230
 
        return 1;
231
 
}
232
 
 
233
 
 
234
 
static void close_all_cb(GtkWidget *, gpointer data)
235
 
{
236
 
        GtkWidget *list = (GtkWidget *)data;
237
 
 
238
 
        if (list) {
239
 
                scope_entry *current = root_scope;
240
 
 
241
 
                while (current) {
242
 
                        GDK_THREADS_LEAVE();
243
 
                        if (current->sp) current->sp->stop();
244
 
                        GDK_THREADS_ENTER();
245
 
                        current = current->next;
246
 
                }
247
 
        }       
248
 
}
249
 
 
250
 
 
251
 
static void close_scope_cb(GtkWidget *, gpointer data)
252
 
{
253
 
        GtkWidget *list = (GtkWidget *)data;
254
 
        
255
 
        if (list) {
256
 
                if (!GTK_CLIST(list)->selection)
257
 
                        return;
258
 
                gint row = GPOINTER_TO_INT(GTK_CLIST(list)->selection->data);
259
 
 
260
 
                scope_entry *se = (scope_entry *)
261
 
                        gtk_clist_get_row_data(GTK_CLIST(list), row);
262
 
                if (se && se->sp) {
263
 
                        GDK_THREADS_LEAVE();
264
 
                        se->sp->stop();
265
 
                        GDK_THREADS_ENTER();
266
 
                }       
267
 
        }
268
 
}
269
 
 
270
 
 
271
 
static void open_scope_cb(GtkWidget *, gpointer data)
272
 
{
273
 
        GtkWidget *list = (GtkWidget *)data;
274
 
        
275
 
        if (list) {
276
 
                if (!GTK_CLIST(list)->selection)
277
 
                        return;
278
 
                gint row = GPOINTER_TO_INT(GTK_CLIST(list)->selection->data);
279
 
 
280
 
                scope_entry *se = (scope_entry *)
281
 
                        gtk_clist_get_row_data(GTK_CLIST(list), row);
282
 
                if (se && se->sp) {
283
 
                        GDK_THREADS_LEAVE();
284
 
                        se->sp->start();
285
 
                        GDK_THREADS_ENTER();
286
 
                }       
287
 
        }
288
 
}
289
 
 
290
 
 
291
 
static void exclusive_open_cb(GtkWidget *widget, gpointer data)
292
 
{
293
 
        GtkWidget *list = (GtkWidget *)data;
294
 
 
295
 
        if (list) {
296
 
                scope_entry *current = root_scope;
297
 
                scope_entry *exclusive_one = NULL;
298
 
 
299
 
                if (!GTK_CLIST(list)->selection)
300
 
                        return;
301
 
 
302
 
                gint row = GPOINTER_TO_INT(GTK_CLIST(list)->selection->data);   
303
 
                
304
 
                scope_entry *se = (scope_entry *)
305
 
                        gtk_clist_get_row_data(GTK_CLIST(list), row);
306
 
                if (se && se->sp) {
307
 
                        while (current) {
308
 
                                if (current == se) {
309
 
                                        exclusive_one = current;
310
 
                                }
311
 
                                GDK_THREADS_LEAVE();
312
 
                                //alsaplayer_error("Stopping \"%s\"", current->sp->name);
313
 
                                current->sp->stop();
314
 
                                GDK_THREADS_ENTER();
315
 
                                current = current->next;
316
 
                        }
317
 
                        if (exclusive_one && exclusive_one->sp) {
318
 
                                //alsaplayer_error("Starting exclusive scope \"%s\"", exclusive_one->sp->name);
319
 
                                exclusive_one->sp->start();
320
 
                        }
321
 
                }
322
 
        }
323
 
}
324
 
 
325
 
 
326
 
void scopes_list_button_press(GtkWidget *widget, GdkEvent *bevent, gpointer)
327
 
{
328
 
        GtkWidget *menu_item;
329
 
        GtkWidget *the_menu;
330
 
        gint row, col;
331
 
        //alsaplayer_error("Button pressed! (%.2f, %.2f, %d)", bevent->button.x, 
332
 
        //      bevent->button.y, bevent->button.button);
333
 
        gtk_clist_get_selection_info(GTK_CLIST(widget), 
334
 
                (gint)bevent->button.x, (gint)bevent->button.y,
335
 
                &row, &col);
336
 
        if (bevent->button.button == 3) { // Right mouse
337
 
                bool selection;
338
 
 
339
 
                gtk_clist_select_row(GTK_CLIST(widget), row, 0);
340
 
 
341
 
                if (!GTK_CLIST(widget)->selection)
342
 
                        selection = false;
343
 
                else
344
 
                        selection = true;
345
 
        
346
 
                // Construct a popup
347
 
                the_menu = gtk_menu_new();
348
 
                menu_item = gtk_menu_item_new_with_label("Open");
349
 
                gtk_menu_append(GTK_MENU(the_menu), menu_item);
350
 
                gtk_widget_show(menu_item);
351
 
                gtk_signal_connect(GTK_OBJECT(menu_item), "activate",
352
 
                        GTK_SIGNAL_FUNC(open_scope_cb), widget);
353
 
                if (!selection)
354
 
                        gtk_widget_set_sensitive(menu_item, false);
355
 
        
356
 
                menu_item = gtk_menu_item_new_with_label("Open exclusively");
357
 
                gtk_menu_append(GTK_MENU(the_menu), menu_item);
358
 
                gtk_widget_show(menu_item);
359
 
                gtk_signal_connect(GTK_OBJECT(menu_item), "activate", 
360
 
                        GTK_SIGNAL_FUNC(exclusive_open_cb), widget);
361
 
                if (!selection)
362
 
                        gtk_widget_set_sensitive(menu_item, false);
363
 
 
364
 
                // Separator
365
 
                menu_item = gtk_menu_item_new();
366
 
                gtk_menu_append(GTK_MENU(the_menu), menu_item);
367
 
                gtk_widget_show(menu_item);
368
 
 
369
 
 
370
 
                 menu_item = gtk_menu_item_new_with_label("Close");
371
 
                 gtk_menu_append(GTK_MENU(the_menu), menu_item);
372
 
                 gtk_widget_show(menu_item);
373
 
                 gtk_signal_connect(GTK_OBJECT(menu_item), "activate",
374
 
                        GTK_SIGNAL_FUNC(close_scope_cb), widget);
375
 
                 if (!selection)
376
 
                        gtk_widget_set_sensitive(menu_item, false);
377
 
 
378
 
                 menu_item = gtk_menu_item_new_with_label("Close all");
379
 
                 gtk_menu_append(GTK_MENU(the_menu), menu_item);
380
 
                 gtk_signal_connect(GTK_OBJECT(menu_item), "activate",
381
 
                        GTK_SIGNAL_FUNC(close_all_cb), widget);
382
 
                 gtk_widget_show(menu_item);
383
 
                 
384
 
                        
385
 
                gtk_menu_popup(GTK_MENU(the_menu), NULL, NULL, NULL, NULL,
386
 
                        bevent->button.button, bevent->button.time);
387
 
        }
388
 
        
389
 
        //alsaplayer_error("Row = %d, Col = %d", row, col);     
390
 
}
391
 
 
392
 
void scopes_list_click(GtkWidget *widget, gint row, gint /* column */,
393
 
        GdkEvent *bevent, gpointer /* data */)
394
 
{
395
 
        if (bevent && bevent->type == GDK_2BUTTON_PRESS) {
396
 
                scope_entry *se = (scope_entry *)
397
 
                        gtk_clist_get_row_data(GTK_CLIST(widget), row);
398
 
                if (se && se->sp) {
399
 
#ifdef STUPID_FLUFF             
400
 
                        if (se->active)
401
 
                                se->sp->stop();
402
 
                        else
403
 
                                se->sp->start(NULL);
404
 
                        se->active = 1 - se->active;
405
 
                        if (se->active) {
406
 
                                gtk_clist_set_pixmap(GTK_CLIST(widget),
407
 
                                        row, 0, active_pix, active_mask);
408
 
                        } else {
409
 
                                gtk_clist_set_text(GTK_CLIST(widget),
410
 
                                        row, 0, "");    
411
 
                        }
412
 
#else
413
 
                        se->sp->start();
414
 
#endif                  
415
 
                }
416
 
        }
417
 
}
418
 
 
419
 
 
420
 
void scopes_window_ok_cb(GtkWidget * /*button_widget*/, gpointer data)
421
 
{
422
 
        gint x, y;
423
 
        static gint s_windows_x_offset = 0;
424
 
        static gint s_windows_y_offset = 0;
425
 
        
426
 
        GtkWidget *widget = (GtkWidget *)data;
427
 
        
428
 
        gdk_window_get_origin(widget->window, &x, &y);
429
 
        if (windows_x_offset >= 0) {
430
 
                x -= s_windows_x_offset;
431
 
                y -= s_windows_y_offset;
432
 
        }       
433
 
        gtk_widget_hide(widget);
434
 
        gtk_widget_set_uposition(widget, x, y);
435
 
        global_scopes_show = 0;
436
 
 
437
 
}
438
 
 
439
 
gboolean scopes_window_delete_event(GtkWidget *widget, GdkEvent * /*event*/, gpointer /* data */)
440
 
{
441
 
        gint x, y;
442
 
 
443
 
        gdk_window_get_origin(widget->window, &x, &y);
444
 
        if (windows_x_offset >= 0) {
445
 
                x -= windows_x_offset;
446
 
                y -= windows_y_offset;
447
 
        }       
448
 
        gtk_widget_hide(widget);
449
 
        gtk_widget_set_uposition(widget, x, y);
450
 
        global_scopes_show = 0;
451
 
 
452
 
        return TRUE;
453
 
}
454
 
 
455
 
 
456
 
void destroy_scopes_window()
457
 
{
458
 
        if (!scopes_window)
459
 
                return;
460
 
        prefs_set_bool(ap_prefs, "gtk_interface", "scopeswindow_active",
461
 
                global_scopes_show);
462
 
}
463
 
 
464
 
GtkWidget *init_scopes_window()
465
 
{
466
 
        GtkWidget *working;
467
 
        GtkStyle *style;
468
 
 
469
 
        scopes_window = create_scopes_window();
470
 
        gtk_widget_realize(scopes_window);
471
 
        GtkWidget *list = get_widget(scopes_window, "scopes_list");
472
 
 
473
 
        style = gtk_widget_get_style(list);     
474
 
        active_pix = gdk_pixmap_create_from_xpm_d(scopes_window->window, &active_mask,
475
 
                &style->bg[GTK_STATE_NORMAL], note_xpm);
476
 
        
477
 
 
478
 
        gtk_object_set_data(GTK_OBJECT(scopes_window), "list", list);
479
 
        gtk_clist_set_column_width(GTK_CLIST(list), 0, 16);
480
 
        gtk_clist_set_row_height(GTK_CLIST(list), 20);
481
 
        gtk_signal_connect(GTK_OBJECT(list), "select_row",
482
 
                GTK_SIGNAL_FUNC(scopes_list_click), NULL);
483
 
        gtk_signal_connect(GTK_OBJECT(list), "button_press_event",
484
 
                GTK_SIGNAL_FUNC(scopes_list_button_press), NULL);
485
 
        working = get_widget(scopes_window, "ok_button");
486
 
        gtk_signal_connect(GTK_OBJECT(working), "clicked",
487
 
                GTK_SIGNAL_FUNC(scopes_window_ok_cb), scopes_window);
488
 
 
489
 
        // Close/delete signals
490
 
        gtk_signal_connect(GTK_OBJECT(scopes_window), "destroy",
491
 
                GTK_SIGNAL_FUNC(scopes_window_delete_event), NULL);
492
 
        gtk_signal_connect(GTK_OBJECT(scopes_window), "delete_event",
493
 
                GTK_SIGNAL_FUNC(scopes_window_delete_event), NULL);
494
 
 
495
 
        // Init scope list
496
 
        pthread_mutex_init(&sl_mutex, (pthread_mutexattr_t *)NULL);
497
 
 
498
 
        if (prefs_get_bool(ap_prefs, "gtk_interface", "scopeswindow_active", 0)) {
499
 
                gtk_widget_show(scopes_window);
500
 
                global_scopes_show = 1;
501
 
        }       
502
 
 
503
 
        return scopes_window;
504
 
}