2
* Copyright (C) 1998-2002 Andy Lo A Foe <andy@alsaplayer.org>
3
* Original code by Tinic Uro
5
* This program is free software; you can redistribute it and/or modify
6
* it under the terms of the GNU General Public License as published by
7
* the Free Software Foundation; either version 2 of the License, or
8
* (at your option) any later version.
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License
16
* along with this program; if not, write to the Free Software
17
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19
* $Id: monoscope.c 1017 2003-11-09 13:28:30Z adnans $
33
#include "scope_config.h"
35
#include "alsaplayer_convolve.h"
36
#include "alsaplayer_error.h"
38
short newEq[CONVOLVE_BIG]; /* latest block of 512 samples. */
39
static short copyEq[CONVOLVE_BIG];
40
int avgEq[CONVOLVE_SMALL]; /* a running average of the last few. */
41
int avgMax; /* running average of max sample. */
43
static GtkWidget *area = NULL;
44
static GtkWidget *scope_win = NULL;
45
static GdkRgbCmap *color_map = NULL;
46
static int ready_state = 0;
47
static pthread_t monoscope_thread;
48
static pthread_mutex_t monoscope_mutex;
49
static pthread_mutex_t update_mutex;
50
static int is_init = 0;
51
static int running = 0;
52
static convolve_state *state = NULL;
54
static void monoscope_hide(void);
55
static int monoscope_running(void);
57
static const int default_colors[] = {
62
void monoscope_set_data(void *audio_buffer, int size)
65
short *sound = (short *)audio_buffer;
67
if (pthread_mutex_trylock(&update_mutex) != 0) {
68
/* alsaplayer_error("missing an update"); */
72
memset(&newEq, 0, sizeof(newEq));
73
pthread_mutex_unlock(&update_mutex);
76
if (running && size >= CONVOLVE_BIG) {
77
short * newset = newEq;
78
int skip = (size / (CONVOLVE_BIG * 2)) * 2;
79
for (i = 0; i < CONVOLVE_BIG; i++) {
80
*newset++ = (((int) sound[0]) + (int) sound[1]) >> 1;
84
pthread_mutex_unlock(&update_mutex);
93
guchar bits[ 257 * 129];
103
pthread_mutex_lock(&update_mutex);
104
memcpy (copyEq, newEq, sizeof (short) * CONVOLVE_BIG);
107
val = convolve_match (avgEq, copyEq, state);
110
pthread_mutex_unlock(&update_mutex);
111
memset(bits, 0, 256 * 128);
112
for (i=0; i < 256; i++) {
113
foo = thisEq[i] + (avgEq[i] >> 1);
120
avgMax += max - (avgMax >> 8);
122
avgMax = max; /* Avoid overflow */
123
factor = 0x7fffffff / avgMax;
124
/* Keep the scaling sensible. */
125
if (factor > (1 << 18))
127
if (factor < (1 << 8))
129
for (i=0; i < 256; i++) {
130
foo = avgEq[i] * factor;
136
val = (i + ((foo+64) << 8));
138
if ((bar > 0) && (bar < (256 * 128))) {
141
for (h = 0; h <= (-foo); h++) {
146
for (h = 0; h <= foo; h++) {
153
for (i=16;i < 128; i+=16) {
154
for (h = 0; h < 256; h+=2) {
155
bits[(i << 8) + h] = 63;
157
bits[(i << 8) + h + 1] = 63;
160
for (i = 16; i < 256; i+=16) {
161
for (h = 0; h < 128; h+=2) {
162
bits[i + (h << 8)] = 63;
166
gdk_draw_indexed_image(area->window,area->style->white_gc,
167
0, 0, 256, 128, GDK_RGB_DITHER_NONE, bits, 256, color_map);
170
dosleep(SCOPE_SLEEP);
180
static void test_cb(GtkWidget *widget, gpointer data)
186
void stop_monoscope(void);
188
static gboolean close_monoscope_window(GtkWidget *widget, GdkEvent *event, gpointer data)
198
GtkWidget *init_monoscope_window(void)
200
GtkWidget *monoscope_win;
205
pthread_mutex_init(&monoscope_mutex, NULL);
206
pthread_mutex_init(&update_mutex, NULL);
208
monoscope_win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
209
gtk_window_set_title(GTK_WINDOW(monoscope_win), "Monoscope");
210
gtk_widget_set_usize(monoscope_win, 256,128);
211
gtk_window_set_wmclass (GTK_WINDOW(monoscope_win), "Monoscope", "AlsaPlayer");
212
gtk_window_set_policy (GTK_WINDOW (monoscope_win), FALSE, FALSE, FALSE);
214
gtk_widget_realize(monoscope_win);
216
color.red = SCOPE_BG_RED << 8;
217
color.blue = SCOPE_BG_BLUE << 8;
218
color.green = SCOPE_BG_GREEN << 8;
219
gdk_color_alloc(gdk_colormap_get_system(), &color);
222
for (i = 1; i < 32; i++) {
223
colors[i] = (i*8 << 16) +(255 << 8);
224
colors[i+31] = (255 << 16) + (((31 - i) * 8) << 8);
226
colors[63] = (40 << 16) + (75 << 8);
227
color_map = gdk_rgb_cmap_new(colors, 64);
228
area = gtk_drawing_area_new();
229
gtk_container_add(GTK_CONTAINER(monoscope_win), area);
230
gtk_widget_realize(area);
231
gdk_window_set_background(area->window, &color);
233
gtk_widget_show(area);
234
gtk_widget_show(monoscope_win);
238
gtk_signal_connect(GTK_OBJECT(monoscope_win), "delete_event",
239
GTK_SIGNAL_FUNC(close_monoscope_window), monoscope_win);
244
return monoscope_win;
248
void monoscope_hide(void)
253
gdk_window_get_root_origin(scope_win->window, &x, &y);
254
gtk_widget_hide(scope_win);
255
gtk_widget_set_uposition(scope_win, x, y);
257
printf("Tried to hide destroyed widget!\n");
262
void stop_monoscope(void)
266
pthread_join(monoscope_thread, NULL);
271
void run_monoscope(void *data)
273
nice(SCOPE_NICE); /* Be nice to most processes */
277
pthread_mutex_unlock(&monoscope_mutex);
282
void start_monoscope(void)
286
scope_win = init_monoscope_window();
288
if (pthread_mutex_trylock(&monoscope_mutex) != 0) {
289
printf("monoscope already running\n");
292
gtk_widget_show(scope_win);
293
pthread_create(&monoscope_thread, NULL, (void * (*)(void *))run_monoscope, NULL);
297
static int init_monoscope(void *arg)
299
state = convolve_init();
302
/* FIXME - Need to call convolve_close(state); at some point
303
* if this is going to become a proper plugin. */
305
if (prefs_get_bool(ap_prefs, "monoscope", "active", 0))
311
static void shutdown_monoscope(void)
313
prefs_set_bool(ap_prefs, "monoscope", "active", monoscope_running());
315
if (monoscope_running())
322
static int monoscope_running(void)
327
scope_plugin monoscope_plugin = {
328
SCOPE_PLUGIN_VERSION,
342
scope_plugin *scope_plugin_info(void)
344
return &monoscope_plugin;