wmxmms_spectrum.c

/* [<][>]
[^][v][top][bottom][index][help] */

FUNCTIONS

This source file includes following functions.
  1. get_vplugin_info
  2. plug_init
  3. plug_cleanup
  4. draw_leds
  5. draw_func
  6. plug_playback_start
  7. plug_playback_stop
  8. 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;
}

/* [<][>][^][v][top][bottom][index][help] */