wmxmms_spectrum.c
/* [<][>][^][v][top][bottom][index][help] */
FUNCTIONS
This source file includes following functions.
- get_vplugin_info
- plug_init
- plug_cleanup
- draw_leds
- draw_func
- plug_playback_start
- plug_playback_stop
- plug_render_freq
/*
*
* XMMS Spectrum Analyzer WindowMaker Dock Applet
* wmxmms_spectrum.so v0.1
*
* Author: Pontus Klang (c96pkg@cs.umu.se) - 1999
* Copyright (C) 1999 Pontus Klang
* Copyright (C) 2000 Joe MacDonald
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2, or (at your option) any later
* version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program (see the file COPYING); if not, write to the Free
* Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA
*
* Borrowed code from Martijn Pieterse (wmgenereal.c, wmgeneral.h) for the wm*
* code. Altough that code seems to be based on some other work too :) see the
* file wmgeneral.c for details.
*
* The XMMS plugin code is _heavily_ based on the examples that came with XMMS.
*
*/
#include <math.h>
#include <gtk/gtk.h>
#include <X11/xpm.h>
#include "wmgeneral.h"
#include "plugin.h"
#include "wmapp.xpm"
#define SCREEN_X 64
#define SCREEN_Y 64
#define NUM_BANDS 4 /* x2 */
#define LED_WIDTH 5
#define LED_HEIGHT 2
static char wmapp_mask_bits[64 * 64];
static int wmapp_mask_width = 64;
static int wmapp_mask_height = 64;
int peaks[NUM_BANDS * NUM_BANDS];
gint16 bar_heights[2][NUM_BANDS];
float dscale;
static int doneflag = 0;
static void plug_init (void);
static void plug_cleanup (void);
static void plug_playback_start (void);
static void plug_playback_stop (void);
static void plug_render_freq (gint16 data[2][256]);
static void plug_cleanup (void);
VisPlugin sanalyzer_vp =
{
NULL,
NULL,
0,
"XMMS Spectrum analyzer dock applet",
0,
2,
plug_init, /* init */
plug_cleanup, /* cleanup */
NULL, /* about */
NULL, /* configure */
NULL, /* disable_plugin */
plug_playback_start, /* playback_start */
plug_playback_stop, /* playback_stop */
NULL, /* render_pcm */
plug_render_freq /* render_freq */
};
VisPlugin *get_vplugin_info (void)
/* [<][>][^][v][top][bottom][index][help] */
{
return &sanalyzer_vp;
}
static void plug_init (void)
/* [<][>][^][v][top][bottom][index][help] */
{
char *fake[] = { "wmplug, wmplug" };
createXBMfromXPM (wmapp_mask_bits, wmapp_xpm, wmapp_mask_width,
wmapp_mask_height);
openXwindow (1, fake, wmapp_xpm, wmapp_mask_bits, wmapp_mask_width,
wmapp_mask_height);
copyXPMArea (120, 0, 60, 60 - 12, 0, 12);
RedrawWindow ();
memset (bar_heights, 0, 2 * NUM_BANDS * sizeof (gint16));
memset (peaks, 0, 2 * NUM_BANDS * sizeof (float));
dscale = (SCREEN_Y - 12) / log (256);
}
static void plug_cleanup (void)
/* [<][>][^][v][top][bottom][index][help] */
{
XCloseDisplay (display);
sanalyzer_vp.disable_plugin (&sanalyzer_vp);
}
void draw_leds (void)
/* [<][>][^][v][top][bottom][index][help] */
{
int y;
int bar_xposition;
int bar;
copyXPMArea (120, 0, 60, 60 - 12, 0, 12);
/* center ===> right */
bar_xposition = NUM_BANDS * (LED_WIDTH + 2) + 4;
for (bar = 0; bar < NUM_BANDS; bar++)
{
/* draw the bar/line */
for (y = 63 - LED_HEIGHT; y > (SCREEN_Y - bar_heights[0][bar]);
y -= (LED_HEIGHT + 1))
{
copyXPMArea (65, y, LED_WIDTH, LED_HEIGHT, bar_xposition, y);
}
/* draw the falloff in a different colour */
copyXPMArea (0, 70, LED_WIDTH, 1, bar_xposition,
SCREEN_Y - peaks[bar] / 4);
/* falloff is the same colour as the bar */
/*
copyXPMArea ( 65, SCREEN_Y - peaks[bar] / 4, LED_WIDTH, 1,
bar_xposition, SCREEN_Y - peaks[bar] / 4);
*/
bar_xposition += LED_WIDTH + 1;
}
/* left <=== center */
bar_xposition = NUM_BANDS * (LED_WIDTH + 2) - 3;
/* for (bar = NUM_BANDS; bar > 0; bar--) */
for (bar = 0; bar < NUM_BANDS; bar++)
{
for (y = 63 - LED_HEIGHT; y > (SCREEN_Y - bar_heights[1][bar]);
y -= (LED_HEIGHT + 1))
{
copyXPMArea (65, y, LED_WIDTH, LED_HEIGHT, bar_xposition + 1, y);
}
copyXPMArea (0, 70, LED_WIDTH, 1, bar_xposition + 1,
SCREEN_Y - peaks[bar * NUM_BANDS] / 4);
bar_xposition -= LED_WIDTH + 1;
}
}
static gint draw_func (void)
/* [<][>][^][v][top][bottom][index][help] */
{
if (doneflag)
return FALSE;
GDK_THREADS_ENTER ();
{
doneflag = 1;
draw_leds ();
RedrawWindow ();
}
GDK_THREADS_LEAVE ();
doneflag = 0;
return TRUE;
}
static void plug_playback_start (void)
/* [<][>][^][v][top][bottom][index][help] */
{
}
static void plug_playback_stop (void)
/* [<][>][^][v][top][bottom][index][help] */
{
copyXPMArea (120, 0, 60, 60 - 12, 0, 12);
RedrawWindow ();
memset (bar_heights, 0, 2 * NUM_BANDS * sizeof (gint16));
memset (peaks, 0, 2 * NUM_BANDS * sizeof (float));
}
static void plug_render_freq (gint16 data[2][256])
/* [<][>][^][v][top][bottom][index][help] */
{
int i;
gint c,
y;
gint scale[] = { 0, 1, 2, 3, 5 };
if (doneflag)
return;
for (i = 0; i < NUM_BANDS; i++)
{
for (c = scale[i], y = 0; c < scale[i + 1]; c++)
{
if (data[0][c] > y)
y = data[0][c];
}
y >>= 7;
if (y != 0)
{
y = (gint) (log (y) * dscale);
if (y >= SCREEN_Y - 13)
y = SCREEN_Y - 13;
}
if (y > bar_heights[0][i])
bar_heights[0][i] = y;
else if (bar_heights[0][i] > 2)
bar_heights[0][i] -= 2;
else
bar_heights[0][i] = 0;
for (c = scale[i], y = 0; c < scale[i + 1]; c++)
{
if (data[1][c] > y)
y = data[1][c];
}
y >>= 7;
if (y != 0)
{
y = (gint) (log (y) * dscale);
if (y >= SCREEN_Y - 13)
y = SCREEN_Y - 13;
}
if (y > bar_heights[1][i])
bar_heights[1][i] = y;
else if (bar_heights[1][i] > 2)
bar_heights[1][i] -= 2;
else
bar_heights[1][i] = 0;
if (bar_heights[0][i] * 4 >= peaks[i])
peaks[i] = bar_heights[0][i] * 4;
else
peaks[i] -= 1;
if (bar_heights[1][i] * 4 >= peaks[i * NUM_BANDS])
peaks[i * NUM_BANDS] = bar_heights[1][i] * 4;
else
peaks[i * NUM_BANDS] -= 1;
}
draw_func ();
return;
}