blob: 2c904335578b97cc0513abeb61041722272c4912 [file] [log] [blame]
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <string>
#include <math.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <libvisual/libvisual.h>
#include <projectM.hpp>
#include "lvtoprojectM.h"
#include "ConfigFile.h"
#define CONFIG_FILE "/share/projectM/config.inp"
std::string read_config();
int texsize=512;
int gx=32,gy=24;
int wvw=512,wvh=512;
int fvw=1024,fvh=768;
int fps=30, fullscreen=0;
/* Private context sensitive data goes here, */
typedef struct {
projectM *PM;
} ProjectmPrivate;
extern "C" int lv_projectm_init (VisPluginData *plugin);
extern "C" int lv_projectm_cleanup (VisPluginData *plugin);
extern "C" int lv_projectm_requisition (VisPluginData *plugin, int *width, int *height);
extern "C" int lv_projectm_dimension (VisPluginData *plugin, VisVideo *video, int width, int height);
extern "C" int lv_projectm_events (VisPluginData *plugin, VisEventQueue *events);
extern "C" VisPalette *lv_projectm_palette (VisPluginData *plugin);
extern "C" int lv_projectm_render (VisPluginData *plugin, VisVideo *video, VisAudio *audio);
VISUAL_PLUGIN_API_VERSION_VALIDATOR
/* Main plugin stuff */
/* The get_plugin_info function provides the libvisual plugin registry, and plugin loader
* with the very basic plugin information */
extern "C" const VisPluginInfo *get_plugin_info (int *count)
{
/* Initialize the plugin specific data structure
* with pointers to the functions that represent
* the plugin interface it's implementation, more info:
* http://libvisual.sourceforge.net/newdocs/docs/html/struct__VisActorPlugin.html */
static VisActorPlugin actor[1];
static VisPluginInfo info[1];
actor[0].requisition = lv_projectm_requisition;
actor[0].palette = lv_projectm_palette;
actor[0].render = lv_projectm_render;
actor[0].vidoptions.depth = VISUAL_VIDEO_DEPTH_GL; /* We want GL clearly */
info[0].type = (char*)VISUAL_PLUGIN_TYPE_ACTOR;
info[0].plugname = (char*)"projectM";
info[0].name = (char*)"libvisual projectM";
info[0].author = (char*)"Peter Sperl";
info[0].version = (char*)"1.1";
info[0].about = (char*)"projectM";
info[0].help = (char*)"";
info[0].init = lv_projectm_init;
info[0].cleanup = lv_projectm_cleanup;
info[0].events = lv_projectm_events;
info[0].plugin = VISUAL_OBJECT (&actor[0]);
*count = sizeof (info) / sizeof (*info);
VISUAL_VIDEO_ATTRIBUTE_OPTIONS_GL_ENTRY(actor[0].vidoptions, VISUAL_GL_ATTRIBUTE_ALPHA_SIZE, 8);
VISUAL_VIDEO_ATTRIBUTE_OPTIONS_GL_ENTRY(actor[0].vidoptions, VISUAL_GL_ATTRIBUTE_DEPTH_SIZE, 16);
VISUAL_VIDEO_ATTRIBUTE_OPTIONS_GL_ENTRY(actor[0].vidoptions, VISUAL_GL_ATTRIBUTE_DOUBLEBUFFER, 1);
VISUAL_VIDEO_ATTRIBUTE_OPTIONS_GL_ENTRY(actor[0].vidoptions, VISUAL_GL_ATTRIBUTE_RED_SIZE, 8);
VISUAL_VIDEO_ATTRIBUTE_OPTIONS_GL_ENTRY(actor[0].vidoptions, VISUAL_GL_ATTRIBUTE_GREEN_SIZE, 8);
VISUAL_VIDEO_ATTRIBUTE_OPTIONS_GL_ENTRY(actor[0].vidoptions, VISUAL_GL_ATTRIBUTE_BLUE_SIZE, 8);
return info;
}
/* This function is called before we really start rendering, it's the init function */
extern "C" int lv_projectm_init (VisPluginData *plugin)
{
char projectM_data[1024];
ProjectmPrivate *priv;
std::string config_file;
config_file = read_config();
ConfigFile config(config_file);
wvw = config.read<int>( "Window Width", 512 );
wvh = config.read<int>( "Window Height", 512 );
fullscreen = 0;
/* Allocate the projectm private data structure, and register it as a private */
priv = new ProjectmPrivate;
visual_mem_set (priv, 0, sizeof (ProjectmPrivate));
//priv = visual_mem_new0 (ProjectmPrivate, 1);
visual_object_set_private (VISUAL_OBJECT (plugin), priv);
//FIXME
priv->PM = new projectM(config_file);
//globalPM = (projectM *)wipemalloc( sizeof( projectM ) );
return 0;
}
extern "C" int lv_projectm_cleanup (VisPluginData *plugin)
{
ProjectmPrivate *priv = (ProjectmPrivate*)visual_object_get_private (VISUAL_OBJECT (plugin));
/* Cleanup, and thus also free our private */
visual_mem_free (priv->PM);
visual_mem_free (priv);
return 0;
}
/* This is used to ask a plugin if it can handle a certain size, and if not, to
* set the size it wants by putting a value in width, height that represents the
* required size */
extern "C" int lv_projectm_requisition (VisPluginData *plugin, int *width, int *height)
{
int reqw, reqh;
/* Size negotiate with the window */
reqw = *width;
reqh = *height;
if (reqw < 64)
reqw = 64;
if (reqh < 64)
reqh = 64;
*width = reqw;
*height = reqh;
return 0;
}
extern "C" int lv_projectm_dimension (VisPluginData *plugin, VisVideo *video, int width, int height)
{
ProjectmPrivate *priv = (ProjectmPrivate*)visual_object_get_private (VISUAL_OBJECT (plugin));
visual_video_set_dimension (video, width, height);
priv->PM->projectM_resetGL( width, height );
return 0;
}
/* This is the main event loop, where all kind of events can be handled, more information
* regarding these can be found at:
* http://libvisual.sourceforge.net/newdocs/docs/html/union__VisEvent.html
*/
extern "C" int lv_projectm_events (VisPluginData *plugin, VisEventQueue *events)
{
ProjectmPrivate *priv = (ProjectmPrivate*)visual_object_get_private (VISUAL_OBJECT (plugin));
VisEvent ev;
VisParamEntry *param;
projectMEvent evt;
projectMKeycode key;
projectMModifier mod;
while (visual_event_queue_poll (events, &ev))
{
switch (ev.type)
{
case VISUAL_EVENT_KEYUP:
evt = lv2pmEvent( ev.type );
key = lv2pmKeycode( ev.event.keyboard.keysym.sym );
mod = lv2pmModifier( ev.event.keyboard.keysym.mod );
priv->PM->key_handler(PROJECTM_KEYDOWN, key,mod);
break;
case VISUAL_EVENT_RESIZE:
lv_projectm_dimension (plugin, ev.event.resize.video,
ev.event.resize.width, ev.event.resize.height);
break;
case VISUAL_EVENT_NEWSONG:
priv->PM->projectM_setTitle(ev.event.newsong.songinfo->songname);
break;
default: /* to avoid warnings */
break;
}
}
return 0;
}
/* Using this function we can update the palette when we're in 8bits mode, which
* we aren't with projectm, so just ignore :) */
extern "C" VisPalette *lv_projectm_palette (VisPluginData *plugin)
{
return (VisPalette *) NULL;
}
/* This is where the real rendering happens! This function is what we call, many times
* a second to get our graphical frames. */
extern "C" int lv_projectm_render (VisPluginData *plugin, VisVideo *video, VisAudio *audio)
{
ProjectmPrivate *priv = (ProjectmPrivate*)visual_object_get_private (VISUAL_OBJECT (plugin));
VisBuffer pcmb;
float pcm[2][512];
int i;
if (video->parent != NULL) lv_projectm_dimension (plugin, video->parent, video->parent->width, video->parent->height);
else lv_projectm_dimension (plugin, video, video->width, video->height);
visual_buffer_set_data_pair (&pcmb, pcm[0], sizeof (pcm[0]));
visual_audio_get_sample (audio, &pcmb, (char*)VISUAL_AUDIO_CHANNEL_LEFT);
visual_buffer_set_data_pair (&pcmb, pcm[1], sizeof (pcm[1]));
visual_audio_get_sample (audio, &pcmb, (char*)VISUAL_AUDIO_CHANNEL_RIGHT);
priv->PM->pcm()->addPCMfloat(*pcm,512);
priv->PM->renderFrame();
return 0;
}
std::string read_config()
{
int n;
char num[512];
FILE *in;
FILE *out;
char* home;
char projectM_home[1024];
char projectM_config[1024];
strcpy(projectM_config, PROJECTM_PREFIX);
strcpy(projectM_config+strlen(PROJECTM_PREFIX), CONFIG_FILE);
projectM_config[strlen(PROJECTM_PREFIX)+strlen(CONFIG_FILE)]='\0';
printf("dir:%s \n",projectM_config);
home=getenv("HOME");
strcpy(projectM_home, home);
strcpy(projectM_home+strlen(home), "/.projectM/config.inp");
projectM_home[strlen(home)+strlen("/.projectM/config.inp")]='\0';
if ((in = fopen(projectM_home, "r")) != 0)
{
printf("reading ~/.projectM/config.inp \n");
fclose(in);
return std::string(projectM_home);
}
else
{
printf("trying to create ~/.projectM/config.inp \n");
strcpy(projectM_home, home);
strcpy(projectM_home+strlen(home), "/.projectM");
projectM_home[strlen(home)+strlen("/.projectM")]='\0';
mkdir(projectM_home,0755);
strcpy(projectM_home, home);
strcpy(projectM_home+strlen(home), "/.projectM/config.inp");
projectM_home[strlen(home)+strlen("/.projectM/config.inp")]='\0';
if((out = fopen(projectM_home,"w"))!=0)
{
if ((in = fopen(projectM_config, "r")) != 0)
{
while(fgets(num,80,in)!=NULL)
{
fputs(num,out);
}
fclose(in);
fclose(out);
if ((in = fopen(projectM_home, "r")) != 0)
{
printf("created ~/.projectM/config.inp successfully\n");
fclose(in);
return std::string(projectM_home);
}
else{printf("This shouldn't happen, using implementation defualts\n");abort();}
}
else{printf("Cannot find projectM default config, using implementation defaults\n");abort();}
}
else
{
printf("Cannot create ~/.projectM/config.inp, using default config file\n");
if ((in = fopen(projectM_config, "r")) != 0)
{ printf("Successfully opened default config file\n");
fclose(in);
return std::string(projectM_config);}
else{ printf("Using implementation defaults, your system is really messed up, I'm suprised we even got this far\n"); abort();}
}
}
}