/* 
projectM v0.95 - xmms-projectm.sourceforge.net
--------------------------------------------------

Lead Developers:  Carmelo Piccione (cep@andrew.cmu.edu) &
                  Peter Sperl (peter@sperl.com)

We have also been advised by some professors at CMU, namely Roger B. Dannenberg.
http://www-2.cs.cmu.edu/~rbd/    
  
The inspiration for this program was Milkdrop by Ryan Geiss. Obviously. 

This code is distributed under the GPL.


THANKS FOR THE CODE!!!
-------------------------------------------------
The base for this program was andy@nobugs.org's XMMS plugin tutorial
http://www.xmms.org/docs/vis-plugin.html

We used some FFT code by Takuya OOURA instead of XMMS' built-in fft code
fftsg.c - http://momonga.t.u-tokyo.ac.jp/~ooura/fft.html

For font rendering we used GLF by Roman Podobedov
glf.c - http://astronomy.swin.edu.au/~pbourke/opengl/glf/

and some beat detection code was inspired by Frederic Patin @
www.gamedev.net/reference/programming/features/beatdetection/

*/

#include <stdio.h>
#include <xmms/plugin.h>
#include <string.h>
#include <stdlib.h>
#include <xmms/util.h>
#include <SDL/SDL.h>
#include <SDL/SDL_thread.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <xmms/xmmsctrl.h>
#include <math.h>

#include "../projectM/projectM.h"
#include "sdltoprojectM.h"
#include "video_init.h"



// Forward declarations 
static void projectM_xmms_init(void); 
static void projectM_cleanup(void);
static void projectM_about(void);
static void projectM_configure(void);
static void projectM_playback_start(void);
static void projectM_playback_stop(void);
static void projectM_render_pcm(gint16 pcm_data[2][512]);
static void projectM_render_freq(gint16 pcm_data[2][256]);


//extern preset_t * active_preset;

// Callback functions
VisPlugin projectM_vtable = {
  0, // Handle, filled in by xmms
  0, // Filename, filled in by xmms
  0,                     // Session ID
  "projectM v0.95",       // description
  2, // # of PCM channels for render_pcm()
  0, // # of freq channels wanted for render_freq()
  projectM_xmms_init,     // Called when plugin is enabled
  projectM_cleanup,        // Called when plugin is disabled
  projectM_about,          // Show the about box
  projectM_configure,      // Show the configure box
  0,                     // Called to disable plugin, filled in by xmms
  projectM_playback_start, // Called when playback starts
  projectM_playback_stop,  // Called when playback stops
  projectM_render_pcm,      // Render the PCM data, must return quickly
  projectM_render_freq     // Render the freq data, must return quickly
};

// XMMS entry point
VisPlugin *get_vplugin_info(void)
{
  return &projectM_vtable;
}

// Our worker thread
SDL_Thread *worker_thread;

SDL_mutex *mutex;

SDL_Event event;

SDL_Surface *screen;
//SDL_RenderTarget *RenderTarget = NULL;
//GLuint RenderTargetTextureID;

projectM_t *globalPM = NULL;

double *pcmdataL;
double *pcmdataR;

int maxsamples=512;

int texsize=256;
int gx=32,gy=24;
int wvw=400,wvh=400;
int fvw=1024,fvh=768;
int fps=60, fullscreen=0;
char *disp;


void worker_func()
{ 
  int title; 
 
  init_display(wvw,wvh,fullscreen);
  SDL_WM_SetCaption("projectM v0.95", "projectM v0.95");

  title=xmms_remote_get_playlist_title(projectM_vtable.xmms_session, xmms_remote_get_playlist_pos(projectM_vtable.xmms_session)); 


  /** Initialise projectM */
    globalPM = (projectM_t *)malloc( sizeof( projectM_t ) );
    projectM_reset( globalPM );

    globalPM->fullscreen = 0;
    globalPM->texsize = 512;

    globalPM->fontURL = (char *)malloc( sizeof( char ) * 512 );
    strcpy( globalPM->fontURL, "\\etc\\projectM\\fonts" );
    
    globalPM->presetURL = (char *)malloc( sizeof( char ) * 512 );
    strcpy( globalPM->presetURL, "\\etc\\projectM\\presets" );

    projectM_init( globalPM );

    projectM_resetGL( globalPM, wvw, wvh );

 
    /** Initialise the thread */
    renderLoop( globalPM );


  while (1)   //MAIN LOOP
    {

  
    }
		
  printf("Worker thread: Exiting\n");
}

           
void renderLoop( projectM_t *pm ) {

    int i;
    int x, y;
    int index;
    short pcm_data[2][512];

    while ( 1 ) {
        projectMEvent evt;
        projectMKeycode key;
        projectMModifier mod;

        /** Process SDL events */
        SDL_Event event;
        while ( SDL_PollEvent( &event ) ) {
            /** Translate into projectM codes and process */
            evt = sdl2pmEvent( event );
            key = sdl2pmKeycode( event.key.keysym.sym );
            mod = sdl2pmModifier( event.key.keysym.mod );
            if ( evt == PROJECTM_KEYDOWN ) {
                key_handler( evt, key, mod );
              }
          }

        /** Produce some fake PCM data to stuff into projectM */
        if ( pm->count % 5 == 0 ) {
            for ( i = 0 ; i < 512 ; i++ ) {
                pcm_data[0][i] = 0;
                pcm_data[1][i] = 0;
              }
          } else {
            for ( i = 0 ; i < 512 ; i++ ) {
                if ( i % 2 == 0 ) {
                    pcm_data[0][i] = (float)( rand() / ( (float)RAND_MAX ) * (pow(2,14) ) );
                    pcm_data[1][i] = (float)( rand() / ( (float)RAND_MAX ) * (pow(2,14) ) );
                  } else {
                    pcm_data[0][i] = (float)( rand() / ( (float)RAND_MAX ) * (pow(2,14) ) );
                    pcm_data[1][i] = (float)( rand() / ( (float)RAND_MAX ) * (pow(2,14) ) );
                  }
                if ( i % 2 == 1 ) {
                    pcm_data[0][i] = -pcm_data[0][i];
                    pcm_data[1][i] = -pcm_data[1][i];
                  }
            }
        }

        /** Add the waveform data */
        addPCM16( pcm_data );

        /** Render the new frame */
        renderFrame( pm );

      

        SDL_GL_SwapBuffers();
      }
	
  printf("Worker thread: Exiting\n");
  }

static void projectM_xmms_init(void) 
{
  

  // read_cfg();
  printf("projectM plugin: Initializing\n");
  if (SDL_Init (SDL_INIT_VIDEO) < 0) {
    printf ("Failed to initialize SDL\n");
    //    projectM_vtable.disable_plugin (&projectM_vtable);
    exit(-1);
    return;
  }
  
  SDL_EnableUNICODE(1);

  pcmdataL=(double *)malloc(maxsamples*sizeof(double));
 pcmdataR=(double *)malloc(maxsamples*sizeof(double));

  /* Preset loading function */
 // initPresetLoader();
  
  /* Load default preset directory */
  //  loadPresetDir("/etc/projectM/presets/"); 
  //loadPresetDir("/home/pete/103");
  //loadPresetDir("/home/carm/carm_presets");
  // loadPresetDir("/home/pete/good");
  //loadPresetDir("/home/carm/presets");
  //loadPresetDir("/mnt/huge/winxpsave/Program Files/winamp/Plugins/Milkdrop/2001");
 

  //glfInit();   
  //initMenu();  


  //  printf("%d %d\n", gx,gy(;

  //initPCM(maxsamples);
  //initBeatDetect();
 
  
  mutex = SDL_CreateMutex();

  worker_thread = SDL_CreateThread ((void *) worker_func, NULL);
}



static void projectM_cleanup(void)
{
  
  free(pcmdataL); 
  free(pcmdataR); 
 
  
 
  SDL_WaitThread(worker_thread, NULL);
  

  SDL_DestroyMutex(mutex);
  
  SDL_Quit();

  printf("projectM plugin: Cleanup completed\n");
}
static void projectM_about(void)
{
  printf("projectM plugin: About\n");
}
static void projectM_configure(void)
{
  printf("projectM plugin: Configure\n");
}
static void projectM_playback_start(void)
{//thread_control = GO;
  printf("projectM plugin: Playback starting\n");
}
static void projectM_playback_stop(void)
{//thread_control = STOP;
  printf("projectM plugin: Playback stopping\n");
}
static void projectM_render_pcm(gint16 pcm_data[2][512])
{

  	SDL_mutexP(mutex);
       
	// addPCM(pcm_data);
	 
	SDL_mutexV(mutex);
	
}

static void projectM_render_freq(gint16 freq_data[2][256])
{
  printf("NO GOOD\n");
 }


void read_config()
{
  
   int n;
   
   char num[80];
   FILE *in; 

 if ((in = fopen("/etc/projectM/config", "r")) != 0) 
   {
     fgets(num, 80, in);  fgets(num, 80, in);  fgets(num, 80, in);
     if(fgets(num, 80, in) != NULL) sscanf (num, "%d", &texsize);  

     fgets(num, 80, in);
     if(fgets(num, 80, in) != NULL) sscanf (num, "%d", &gx);  

     fgets(num, 80, in);
     if(fgets(num, 80, in) != NULL) sscanf (num, "%d", &gy);   

     fgets(num, 80, in);
     if(fgets(num, 80, in) != NULL) sscanf (num, "%d", &wvw);  

     fgets(num, 80, in);
     if(fgets(num, 80, in) != NULL) sscanf (num, "%d", &wvh);  

     fgets(num, 80, in);
     if(fgets(num, 80, in) != NULL) sscanf (num, "%d", &fvw);  

     fgets(num, 80, in);
     if(fgets(num, 80, in) != NULL) sscanf (num, "%d", &fvh);  

     fgets(num, 80, in);
     if(fgets(num, 80, in) != NULL) sscanf (num, "%d", &fps);

     fgets(num, 80, in);
     if(fgets(num, 80, in) != NULL) sscanf (num, "%d", &fullscreen);
     /*
     fgets(num, 80, in);
     fgets(num, 80, in);
     
     n=0;
     while (num[n]!=' ' && num[n]!='\n' && n < 80 && num[n]!=EOF)
       {
	 	 disp[n]=num[n];
		 n++;
       }
     disp[n]=0;

    
     // sprintf(disp,"%s",num );
      setenv("DISPLAY",disp,1);
      printf("%s %d\n", disp,strlen(disp));
      setenv("LD_PRELOAD", "/usr/lib/tls/libGL.so.1.0.4496", 1);
     */
   fclose(in); 
     }
 
} 
