CGL_Guardian
21st June 2002, 11:25
I seem to be having a problem with the closing of my plugin.
Currently I'm developing an XMMS plugin that also works with Winamp. To achieve this, I am using SDL (www.libsdl.org) for all my graphics. However, the problem I have is that when I try to stop the plugin and the restart it, Winamp quits (with no crash dialog).
Since I am still fairly new to windows programming (mostly develop on linux), I wonder if I'm doing something wrong. Can anyone help? (even an explanation of how winamp loads and unloads plugins would help).
Below is the code.
Thanks, Lance
/*
* Winamp SDL Test Visualisation Plugin
*/
#include <windows.h>
#include "SDL.h"
#include "vis.h"
static SDL_Surface *screen = NULL;
static Uint32 red = 0, green = 0;
/* returns a winampVisModule when requested. Used in hdr, below */
winampVisModule *getModule(int which);
/* "member" functions */
void config(struct winampVisModule *this_mod); /* configuration dialog */
int init(struct winampVisModule *this_mod); /* initialization for module */
int render(struct winampVisModule *this_mod); /* rendering for module */
void quit(struct winampVisModule *this_mod); /* deinitialization for module */
/* Module header, includes version, description, and address of the module retriever function */
winampVisHeader hdr = { VIS_HDRVER, "SDL Test Visualisation", getModule };
/* first module (oscilliscope) */
winampVisModule mod =
{
"SDL Testvis",
NULL, // hwndParent
NULL, // hDllInstance
0, // sRate
0, // nCh
25, // latencyMS
25, // delayMS
0, // spectrumNch
2, // waveformNch
{ 0, }, // spectrumData
{ 0, }, // waveformData
NULL,
init,
render,
quit
};
/* this is the only exported symbol. returns our main header.
if you are compiling C++, the extern "C" { is necessary, so we just #ifdef it */
#ifdef __cplusplus
extern "C" {
#endif
__declspec( dllexport ) winampVisHeader *winampVisGetHeader()
{
return &hdr;
}
#ifdef __cplusplus
}
#endif
/* Returns a pointer to the appropriate module based upon which */
winampVisModule *getModule(int which)
{
switch (which)
{
case 0: return &mod;
default:return NULL;
}
}
/*
* Set the pixel at (x, y) to the given value
* NOTE: The surface must be locked before calling this!
*/
void putpixel(SDL_Surface *surface, int x, int y, Uint32 pixel)
{
int bpp = surface->format->BytesPerPixel;
/* Here p is the address to the pixel we want to set */
Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp;
switch(bpp) {
case 1:
*p = pixel;
break;
case 2:
*(Uint16 *)p = pixel;
break;
case 3:
if(SDL_BYTEORDER == SDL_BIG_ENDIAN) {
p[0] = (pixel >> 16) & 0xff;
p[1] = (pixel >> 8) & 0xff;
p[2] = pixel & 0xff;
} else {
p[0] = pixel & 0xff;
p[1] = (pixel >> 8) & 0xff;
p[2] = (pixel >> 16) & 0xff;
}
break;
case 4:
*(Uint32 *)p = pixel;
break;
}
}
/* Initialise the module */
int init(struct winampVisModule *this_mod)
{
/* Initialize the SDL library */
if( SDL_Init(SDL_INIT_VIDEO) < 0 )
{
printf("Couldn't initialize SDL: %s\n", SDL_GetError());
return 1;
}
atexit(SDL_Quit);
/*
* Initialize the display in a 640x480 16-bit mode,
* requesting a software surface
*/
screen = SDL_SetVideoMode(640, 480, 16, SDL_HWSURFACE);
if ( screen == NULL )
{
printf("Couldn't set 640x480x16 video mode: %s\n",
SDL_GetError());
return 1;
}
SDL_WM_SetCaption("SDL Test Vis", NULL);
/* Setup colours */
red = SDL_MapRGB(screen->format, 255, 0, 0);
green = SDL_MapRGB(screen->format, 0, 255, 0);
return 0;
}
/* render function for oscilliscope. Returns 0 if successful,
1 if visualization should end.*/
int render(struct winampVisModule *this_mod)
{
int x, y;
Uint32 colour;
SDL_Event event;
/* Clear the screen */
SDL_FillRect(screen, NULL, SDL_MapRGB(screen->format,0,0,0));
/* Poll for events */
while(SDL_PollEvent(&event))
{
switch(event.type)
{
/* Keyboard event */
case SDL_KEYDOWN:
{
switch(event.key.keysym.sym)
{
case SDLK_ESCAPE:
return 1;
break;
}
break;
}
/* SDL_QUIT event (window close) */
case SDL_QUIT:
{
return 1;
break;
}
default:
{
break;
}
}
}
/* Use data */
for (y = 0; y < this_mod->nCh; y ++)
{
for (x = 0; x < 576; x ++)
{
if (y == 0)
{
colour = red;
}
else
{
colour = green;
}
if (SDL_MUSTLOCK(screen))
{
SDL_LockSurface(screen);
}
putpixel(screen,20+x,(y*200+(this_mod->waveformData[y][x]^128))>>(this_mod->nCh-1),colour);
if (SDL_MUSTLOCK(screen))
{
SDL_UnlockSurface(screen);
}
}
}
/* Update the screen */
SDL_UpdateRect(screen, 0, 0, 0, 0);
return 0;
}
/* Quit! */
void quit(struct winampVisModule *this_mod)
{
SDL_Quit();
}
Currently I'm developing an XMMS plugin that also works with Winamp. To achieve this, I am using SDL (www.libsdl.org) for all my graphics. However, the problem I have is that when I try to stop the plugin and the restart it, Winamp quits (with no crash dialog).
Since I am still fairly new to windows programming (mostly develop on linux), I wonder if I'm doing something wrong. Can anyone help? (even an explanation of how winamp loads and unloads plugins would help).
Below is the code.
Thanks, Lance
/*
* Winamp SDL Test Visualisation Plugin
*/
#include <windows.h>
#include "SDL.h"
#include "vis.h"
static SDL_Surface *screen = NULL;
static Uint32 red = 0, green = 0;
/* returns a winampVisModule when requested. Used in hdr, below */
winampVisModule *getModule(int which);
/* "member" functions */
void config(struct winampVisModule *this_mod); /* configuration dialog */
int init(struct winampVisModule *this_mod); /* initialization for module */
int render(struct winampVisModule *this_mod); /* rendering for module */
void quit(struct winampVisModule *this_mod); /* deinitialization for module */
/* Module header, includes version, description, and address of the module retriever function */
winampVisHeader hdr = { VIS_HDRVER, "SDL Test Visualisation", getModule };
/* first module (oscilliscope) */
winampVisModule mod =
{
"SDL Testvis",
NULL, // hwndParent
NULL, // hDllInstance
0, // sRate
0, // nCh
25, // latencyMS
25, // delayMS
0, // spectrumNch
2, // waveformNch
{ 0, }, // spectrumData
{ 0, }, // waveformData
NULL,
init,
render,
quit
};
/* this is the only exported symbol. returns our main header.
if you are compiling C++, the extern "C" { is necessary, so we just #ifdef it */
#ifdef __cplusplus
extern "C" {
#endif
__declspec( dllexport ) winampVisHeader *winampVisGetHeader()
{
return &hdr;
}
#ifdef __cplusplus
}
#endif
/* Returns a pointer to the appropriate module based upon which */
winampVisModule *getModule(int which)
{
switch (which)
{
case 0: return &mod;
default:return NULL;
}
}
/*
* Set the pixel at (x, y) to the given value
* NOTE: The surface must be locked before calling this!
*/
void putpixel(SDL_Surface *surface, int x, int y, Uint32 pixel)
{
int bpp = surface->format->BytesPerPixel;
/* Here p is the address to the pixel we want to set */
Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp;
switch(bpp) {
case 1:
*p = pixel;
break;
case 2:
*(Uint16 *)p = pixel;
break;
case 3:
if(SDL_BYTEORDER == SDL_BIG_ENDIAN) {
p[0] = (pixel >> 16) & 0xff;
p[1] = (pixel >> 8) & 0xff;
p[2] = pixel & 0xff;
} else {
p[0] = pixel & 0xff;
p[1] = (pixel >> 8) & 0xff;
p[2] = (pixel >> 16) & 0xff;
}
break;
case 4:
*(Uint32 *)p = pixel;
break;
}
}
/* Initialise the module */
int init(struct winampVisModule *this_mod)
{
/* Initialize the SDL library */
if( SDL_Init(SDL_INIT_VIDEO) < 0 )
{
printf("Couldn't initialize SDL: %s\n", SDL_GetError());
return 1;
}
atexit(SDL_Quit);
/*
* Initialize the display in a 640x480 16-bit mode,
* requesting a software surface
*/
screen = SDL_SetVideoMode(640, 480, 16, SDL_HWSURFACE);
if ( screen == NULL )
{
printf("Couldn't set 640x480x16 video mode: %s\n",
SDL_GetError());
return 1;
}
SDL_WM_SetCaption("SDL Test Vis", NULL);
/* Setup colours */
red = SDL_MapRGB(screen->format, 255, 0, 0);
green = SDL_MapRGB(screen->format, 0, 255, 0);
return 0;
}
/* render function for oscilliscope. Returns 0 if successful,
1 if visualization should end.*/
int render(struct winampVisModule *this_mod)
{
int x, y;
Uint32 colour;
SDL_Event event;
/* Clear the screen */
SDL_FillRect(screen, NULL, SDL_MapRGB(screen->format,0,0,0));
/* Poll for events */
while(SDL_PollEvent(&event))
{
switch(event.type)
{
/* Keyboard event */
case SDL_KEYDOWN:
{
switch(event.key.keysym.sym)
{
case SDLK_ESCAPE:
return 1;
break;
}
break;
}
/* SDL_QUIT event (window close) */
case SDL_QUIT:
{
return 1;
break;
}
default:
{
break;
}
}
}
/* Use data */
for (y = 0; y < this_mod->nCh; y ++)
{
for (x = 0; x < 576; x ++)
{
if (y == 0)
{
colour = red;
}
else
{
colour = green;
}
if (SDL_MUSTLOCK(screen))
{
SDL_LockSurface(screen);
}
putpixel(screen,20+x,(y*200+(this_mod->waveformData[y][x]^128))>>(this_mod->nCh-1),colour);
if (SDL_MUSTLOCK(screen))
{
SDL_UnlockSurface(screen);
}
}
}
/* Update the screen */
SDL_UpdateRect(screen, 0, 0, 0, 0);
return 0;
}
/* Quit! */
void quit(struct winampVisModule *this_mod)
{
SDL_Quit();
}